// File: /workspace/github_c_makefile_star2_O2/voithos[P]awl/src/builtins.c
// Function: builtin_num_op
awlval* builtin_num_op(awlenv* e, awlval* a, char* op) {
    /* Argcount must be checked in calling function, because
     * different operators have different requirements */
    EVAL_ARGS(e, a);

    for (int i = 0; i < a->count; i++) {
        AWLASSERT_ISNUMERIC(a, i, op);
    }

    awlval* x = awlval_pop(a, 0);
    if (streq(op, "-") && a->count == 0) {
        UNARY_OP(x, -);
    }

    while (a->count > 0) {
        awlval* y = awlval_pop(a, 0);

        awlval_maybe_promote_numeric(x, y);

        if (streq(op, "+")) { BINARY_OP(x, y, +); }
        if (streq(op, "-")) { BINARY_OP(x, y, -); }
        if (streq(op, "*")) { BINARY_OP(x, y, *); }
        if (streq(op, "/") || streq(op, "//") || streq(op, "%")) {
            /* Handle division or modulo by zero */
            if ((y->type == AWLVAL_INT && y->lng == 0) ||
                (y->type == AWLVAL_FLOAT && y->dbl == 0)) {
                awlval* err = awlval_err("division by zero; %i %s 0", x->lng, op);
                awlval_del(x);
                awlval_del(y);
                x = err;
                break;
            }

            if (strstr(op, "/")) {
                awlval_type_t oldtype_x = x->type;
                awlval_type_t oldtype_y = y->type;

                /* Handle fractional integer division */
                if (x->type == AWLVAL_INT && y->type == AWLVAL_INT && x->lng % y->lng != 0) {
                    awlval_promote_numeric(x);
                    awlval_promote_numeric(y);
                }

                BINARY_OP(x, y, /);

                if (streq(op, "//")) {
                    /* Truncating division, based on old types */
                    if (oldtype_x == AWLVAL_INT && oldtype_y == AWLVAL_INT) {
                        awlval_demote_numeric(x);
                    } else {
                        /* Truncate, but we still need to keep result a float */
                        awlval_demote_numeric(x);
                        awlval_promote_numeric(x);
                    }
                }
            } else {
                /* Handle modulo */
                if (x->type == AWLVAL_FLOAT || y->type == AWLVAL_FLOAT) {
                    BINARY_OP_FUNC(x, y, fmodulo);
                } else {
                    x->lng = modulo(x->lng, y->lng);
                }
            }
        }
        if (streq(op, "^")) {
            if (x->type == AWLVAL_FLOAT || y->type == AWLVAL_FLOAT) {
                BINARY_OP_FUNC(x, y, pow);
            } else {
                /* Handle case where result is fractional */
                double ans = pow((double)x->lng, y->lng);
                if (ans - (double)(long)ans != 0.0) {
                    x->type = AWLVAL_FLOAT;
                    x->dbl = ans;
                } else {
                    x->lng = (long)ans;
                }
            }

            // Check for NaN
            if (x->type == AWLVAL_FLOAT && isnan(x->dbl)) {
                awlval_del(x);
                x = awlval_err("pow resulted in NaN");
            }
        }

        awlval_del(y);
    }

    awlval_del(a);
    return x;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %r14
callq 0x55f9
movq %rax, %rbx
cmpl $0x2, (%rax)
je 0x297b
movl 0x4(%rbx), %eax
xorl %r15d, %r15d
testl %eax, %eax
cmovlel %r15d, %eax
cmpq %r15, %rax
je 0x25f3
movq 0x8(%rbx), %rcx
movq (%rcx,%r15,8), %rcx
movl (%rcx), %edi
cmpl $0x1, %edi
ja 0x2924
incq %r15
jmp 0x25d6
movq %rbx, %rdi
xorl %esi, %esi
callq 0xe2bf
movq %rax, %r15
leaq 0xe732(%rip), %rsi      # 0x10d39
movq %r14, %rdi
callq 0xf0d6
testb %al, %al
je 0x261d
cmpl $0x0, 0x4(%rbx)
je 0x298d
cmpl $0x0, 0x4(%rbx)
jle 0x2970
movq %rbx, %rdi
xorl %esi, %esi
callq 0xe2bf
movq %rax, %rbp
movq %r15, %rdi
movq %rax, %rsi
callq 0xe587
movq %r14, %rdi
leaq 0xda45(%rip), %rsi      # 0x1008e
callq 0xf0d6
testb %al, %al
je 0x2679
movl (%r15), %eax
cmpl $0x1, %eax
je 0x2668
testl %eax, %eax
jne 0x2679
movq 0x18(%rbp), %rax
addq %rax, 0x18(%r15)
jmp 0x2679
movsd 0x18(%r15), %xmm0
addsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0xe6b6(%rip), %rsi      # 0x10d39
callq 0xf0d6
testb %al, %al
je 0x26b3
movl (%r15), %eax
cmpl $0x1, %eax
je 0x26a2
testl %eax, %eax
jne 0x26b3
movq 0x18(%rbp), %rax
subq %rax, 0x18(%r15)
jmp 0x26b3
movsd 0x18(%r15), %xmm0
subsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0xd9d3(%rip), %rsi      # 0x10090
callq 0xf0d6
testb %al, %al
je 0x26f2
movl (%r15), %eax
cmpl $0x1, %eax
je 0x26e1
testl %eax, %eax
jne 0x26f2
movq 0x18(%rbp), %rax
imulq 0x18(%r15), %rax
movq %rax, 0x18(%r15)
jmp 0x26f2
movsd 0x18(%r15), %xmm0
mulsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0xf1e3(%rip), %rsi      # 0x118df
callq 0xf0d6
testb %al, %al
jne 0x272f
movq %r14, %rdi
leaq 0xd983(%rip), %rsi      # 0x10092
callq 0xf0d6
testb %al, %al
jne 0x272f
movq %r14, %rdi
leaq 0xd973(%rip), %rsi      # 0x10095
callq 0xf0d6
testb %al, %al
je 0x285e
movl (%rbp), %r12d
cmpl $0x1, %r12d
je 0x274e
testl %r12d, %r12d
jne 0x2749
cmpq $0x0, 0x18(%rbp)
je 0x2945
xorl %r13d, %r13d
jmp 0x2766
movsd 0x18(%rbp), %xmm0
movb $0x1, %r13b
ucomisd 0xd8d2(%rip), %xmm0     # 0x10030
jne 0x2766
jnp 0x2945
movq %r14, %rdi
pushq $0x2f
popq %rsi
callq 0x2120
movl (%r15), %ecx
testq %rax, %rax
je 0x27b9
orl %ecx, %r12d
jne 0x27a0
movq 0x18(%r15), %rax
cqto
idivq 0x18(%rbp)
testq %rdx, %rdx
je 0x27a0
movq %r15, %rdi
callq 0xe5c9
movq %rbp, %rdi
callq 0xe5c9
movl (%r15), %ecx
cmpl $0x1, %ecx
je 0x27d9
testl %ecx, %ecx
jne 0x27ea
movq 0x18(%r15), %rax
cqto
idivq 0x18(%rbp)
movq %rax, 0x18(%r15)
jmp 0x27ea
cmpl $0x1, %ecx
jne 0x2814
movsd 0x18(%r15), %xmm0
movsd 0x18(%rbp), %xmm1
callq 0x2599
movsd %xmm0, 0x18(%r15)
jmp 0x285e
movsd 0x18(%r15), %xmm0
divsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0xd89e(%rip), %rsi      # 0x10092
callq 0xf0d6
testb %al, %al
je 0x285e
movq %r15, %rdi
callq 0xe5e0
testl %r12d, %r12d
je 0x285e
movq %r15, %rdi
callq 0xe5c9
jmp 0x285e
testb %r13b, %r13b
je 0x2839
testl %ecx, %ecx
jne 0x285e
cvtsi2sdq 0x18(%r15), %xmm0
cvtsi2sdq 0x18(%rbp), %xmm1
callq 0x2599
cvttsd2si %xmm0, %rax
movq %rax, 0x18(%r15)
jmp 0x285e
movq 0x18(%r15), %rcx
movq 0x18(%rbp), %rdx
movq %rcx, %rax
negq %rax
cmovsq %rcx, %rax
movq %rdx, %rcx
negq %rcx
cmovsq %rdx, %rcx
xorl %edx, %edx
divq %rcx
movq %rdx, 0x18(%r15)
movq %r14, %rdi
leaq 0xd849(%rip), %rsi      # 0x100b1
callq 0xf0d6
testb %al, %al
je 0x28fc
movl (%r15), %eax
cmpl $0x1, %eax
jne 0x2895
movsd 0x18(%r15), %xmm0
movsd 0x18(%rbp), %xmm1
callq 0x20f0
movsd %xmm0, 0x18(%r15)
jmp 0x28ea
cmpl $0x1, (%rbp)
jne 0x28b7
testl %eax, %eax
jne 0x28ea
cvtsi2sdq 0x18(%r15), %xmm0
cvtsi2sdq 0x18(%rbp), %xmm1
callq 0x20f0
cvttsd2si %xmm0, %rax
jmp 0x28e6
cvtsi2sdq 0x18(%r15), %xmm0
cvtsi2sdq 0x18(%rbp), %xmm1
callq 0x20f0
cvttsd2si %xmm0, %rax
cvtsi2sd %rax, %xmm1
ucomisd %xmm1, %xmm0
jne 0x28da
jnp 0x28e6
movl $0x1, (%r15)
movq %xmm0, %rax
movq %rax, 0x18(%r15)
cmpl $0x1, (%r15)
jne 0x28fc
movsd 0x18(%r15), %xmm0
ucomisd %xmm0, %xmm0
jp 0x2909
movq %rbp, %rdi
callq 0xded1
jmp 0x261d
movq %r15, %rdi
callq 0xded1
leaq 0xd79b(%rip), %rdi      # 0x100b3
xorl %eax, %eax
callq 0xdb45
movq %rax, %r15
jmp 0x28fc
callq 0xd97c
leaq 0xd710(%rip), %rdi      # 0x10040
movq %r14, %rsi
movl %r15d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0xdb45
movq %rax, %r15
jmp 0x2970
movq 0x18(%r15), %rsi
leaq 0xd747(%rip), %rdi      # 0x10097
movq %r14, %rdx
xorl %eax, %eax
callq 0xdb45
movq %rax, %r14
movq %r15, %rdi
callq 0xded1
movq %rbp, %rdi
callq 0xded1
movq %r14, %r15
movq %rbx, %rdi
callq 0xded1
movq %r15, %rbx
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl (%r15), %eax
cmpl $0x1, %eax
je 0x29a6
testl %eax, %eax
jne 0x261d
negq 0x18(%r15)
jmp 0x261d
movsd 0x18(%r15), %xmm0
xorpd 0xd66c(%rip), %xmm0     # 0x10020
movlpd %xmm0, 0x18(%r15)
jmp 0x261d