// File: /workspace/github_c_makefile_star2_O3/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 0x5f58
movq %rax, %rbx
cmpl $0x2, (%rax)
je 0x3146
movslq 0x4(%rbx), %rax
testq %rax, %rax
jle 0x2d55
movq 0x8(%rbx), %rcx
xorl %r15d, %r15d
movq (%rcx,%r15,8), %rdx
movl (%rdx), %edi
cmpl $0x1, %edi
ja 0x2d92
incq %r15
cmpq %r15, %rax
jne 0x2d42
movq %rbx, %rdi
xorl %esi, %esi
callq 0x1075b
movq %rax, %r15
leaq 0xffd8(%rip), %rsi      # 0x12d41
movq %r14, %rdi
callq 0x11692
testb %al, %al
je 0x2dca
movl 0x4(%rbx), %eax
testl %eax, %eax
jne 0x2dcd
movl (%r15), %eax
cmpl $0x1, %eax
je 0x2db6
testl %eax, %eax
jne 0x313b
negq 0x18(%r15)
jmp 0x2dca
callq 0xfc74
leaq 0xf2a2(%rip), %rdi      # 0x12040
movq %r14, %rsi
movl %r15d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0xfe6b
movq %rax, %r15
jmp 0x313b
movsd 0x18(%r15), %xmm0
xorpd 0xf25c(%rip), %xmm0     # 0x12020
movlpd %xmm0, 0x18(%r15)
movl 0x4(%rbx), %eax
testl %eax, %eax
jle 0x313b
movq %rbx, %rdi
xorl %esi, %esi
callq 0x1075b
movq %rax, %rbp
movq %r15, %rdi
movq %rax, %rsi
callq 0x10ae4
movq %r14, %rdi
leaq 0xf297(%rip), %rsi      # 0x1208e
callq 0x11692
testb %al, %al
je 0x2e27
movl (%r15), %eax
cmpl $0x1, %eax
je 0x2e16
testl %eax, %eax
jne 0x2e27
movq 0x18(%rbp), %rax
addq %rax, 0x18(%r15)
jmp 0x2e27
movsd 0x18(%r15), %xmm0
addsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0xff10(%rip), %rsi      # 0x12d41
callq 0x11692
testb %al, %al
je 0x2e61
movl (%r15), %eax
cmpl $0x1, %eax
je 0x2e50
testl %eax, %eax
jne 0x2e61
movq 0x18(%rbp), %rax
subq %rax, 0x18(%r15)
jmp 0x2e61
movsd 0x18(%r15), %xmm0
subsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0xf225(%rip), %rsi      # 0x12090
callq 0x11692
testb %al, %al
je 0x2ea0
movl (%r15), %eax
cmpl $0x1, %eax
je 0x2e8f
testl %eax, %eax
jne 0x2ea0
movq 0x18(%rbp), %rax
imulq 0x18(%r15), %rax
movq %rax, 0x18(%r15)
jmp 0x2ea0
movsd 0x18(%r15), %xmm0
mulsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0x10a3d(%rip), %rsi     # 0x138e7
callq 0x11692
testb %al, %al
jne 0x2edd
movq %r14, %rdi
leaq 0xf1d5(%rip), %rsi      # 0x12092
callq 0x11692
testb %al, %al
jne 0x2edd
movq %r14, %rdi
leaq 0xf1c5(%rip), %rsi      # 0x12095
callq 0x11692
testb %al, %al
je 0x3034
movl (%rbp), %r12d
cmpl $0x1, %r12d
je 0x2efc
testl %r12d, %r12d
jne 0x2ef7
cmpq $0x0, 0x18(%rbp)
je 0x3110
xorl %r13d, %r13d
jmp 0x2f14
movsd 0x18(%rbp), %xmm0
movb $0x1, %r13b
ucomisd 0xf124(%rip), %xmm0     # 0x12030
jne 0x2f14
jnp 0x3110
movq %r14, %rdi
movl $0x2f, %esi
callq 0x2120
movl (%r15), %ecx
testq %rax, %rax
je 0x2f69
orl %ecx, %r12d
jne 0x2f50
movq 0x18(%r15), %rax
cqto
idivq 0x18(%rbp)
testq %rdx, %rdx
je 0x2f50
movq %r15, %rdi
callq 0x10b29
movq %rbp, %rdi
callq 0x10b29
movl (%r15), %ecx
cmpl $0x1, %ecx
je 0x2f99
testl %ecx, %ecx
jne 0x2faa
movq 0x18(%r15), %rax
cqto
idivq 0x18(%rbp)
movq %rax, 0x18(%r15)
jmp 0x2faa
cmpl $0x1, %ecx
jne 0x2fd4
movsd 0x18(%r15), %xmm0
movapd 0xf094(%rip), %xmm2     # 0x12010
andpd %xmm2, %xmm0
movsd 0x18(%rbp), %xmm1
andpd %xmm2, %xmm1
callq 0x21a0
movsd %xmm0, 0x18(%r15)
jmp 0x3034
movsd 0x18(%r15), %xmm0
divsd 0x18(%rbp), %xmm0
movsd %xmm0, 0x18(%r15)
movq %r14, %rdi
leaq 0xf0de(%rip), %rsi      # 0x12092
callq 0x11692
testb %al, %al
je 0x3034
movq %r15, %rdi
callq 0x10b40
testl %r12d, %r12d
je 0x3034
movq %r15, %rdi
callq 0x10b29
jmp 0x3034
testb %r13b, %r13b
je 0x300f
testl %ecx, %ecx
jne 0x3034
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%r15), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x18(%rbp), %xmm1
movapd 0xf019(%rip), %xmm2     # 0x12010
andpd %xmm2, %xmm0
andpd %xmm2, %xmm1
callq 0x21a0
cvttsd2si %xmm0, %rax
movq %rax, 0x18(%r15)
jmp 0x3034
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 0xf073(%rip), %rsi      # 0x120b1
callq 0x11692
testb %al, %al
je 0x30e1
movl (%r15), %eax
cmpl $0x1, %eax
jne 0x306b
movsd 0x18(%r15), %xmm0
movsd 0x18(%rbp), %xmm1
callq 0x20f0
movsd %xmm0, 0x18(%r15)
jmp 0x30cf
cmpl $0x1, (%rbp)
jne 0x3093
testl %eax, %eax
jne 0x30cf
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%r15), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x18(%rbp), %xmm1
callq 0x20f0
cvttsd2si %xmm0, %rax
jmp 0x30cb
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%r15), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x18(%rbp), %xmm1
callq 0x20f0
cvttsd2si %xmm0, %rax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
ucomisd %xmm1, %xmm0
jne 0x30bf
jnp 0x30cb
movl $0x1, (%r15)
movq %xmm0, %rax
movq %rax, 0x18(%r15)
cmpl $0x1, (%r15)
jne 0x30e1
movsd 0x18(%r15), %xmm0
ucomisd %xmm0, %xmm0
jp 0x30f5
movq %rbp, %rdi
callq 0x1029f
cmpl $0x0, 0x4(%rbx)
jg 0x2dd5
jmp 0x313b
movq %r15, %rdi
callq 0x1029f
leaq 0xefaf(%rip), %rdi      # 0x120b3
xorl %eax, %eax
callq 0xfe6b
movq %rax, %r15
jmp 0x30e1
movq 0x18(%r15), %rsi
leaq 0xef7c(%rip), %rdi      # 0x12097
movq %r14, %rdx
xorl %eax, %eax
callq 0xfe6b
movq %rax, %r14
movq %r15, %rdi
callq 0x1029f
movq %rbp, %rdi
callq 0x1029f
movq %r14, %r15
movq %rbx, %rdi
callq 0x1029f
movq %r15, %rbx
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq