// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x7c60
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x262e
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x2c79
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x26d6
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x0, (%rax)
je 0x26c6
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x1, (%rax)
je 0x26c6
movq -0x20(%rbp), %rax
movq %rax, -0x68(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x5c(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl (%rax), %edi
callq 0x161a0
movq -0x68(%rbp), %rsi
movl -0x5c(%rbp), %edx
movq %rax, %rcx
leaq 0x17983(%rip), %rdi     # 0x1a028
movb $0x0, %al
callq 0x16600
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x2c79
jmp 0x26c8
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x2635
movq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0x174b0
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rdi
leaq 0x18939(%rip), %rsi     # 0x1b029
callq 0x18d50
testb $0x1, %al
jne 0x26fb
jmp 0x2761
movq -0x18(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x2761
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x6c(%rbp)
testl %eax, %eax
je 0x271e
jmp 0x2714
movl -0x6c(%rbp), %eax
subl $0x1, %eax
je 0x2732
jmp 0x275d
movq -0x38(%rbp), %rax
xorl %ecx, %ecx
subq 0x18(%rax), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x275f
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x275f
jmp 0x275f
jmp 0x2761
jmp 0x2763
movq -0x18(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jle 0x2c68
movq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0x174b0
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x17b60
movq -0x20(%rbp), %rdi
leaq 0x178de(%rip), %rsi     # 0x1a076
callq 0x18d50
testb $0x1, %al
jne 0x27a3
jmp 0x27f7
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x70(%rbp)
testl %eax, %eax
je 0x27bc
jmp 0x27b2
movl -0x70(%rbp), %eax
subl $0x1, %eax
je 0x27d6
jmp 0x27f3
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x40(%rbp), %rax
addq 0x18(%rax), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x27f5
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
addsd 0x18(%rax), %xmm0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x27f5
jmp 0x27f5
jmp 0x27f7
movq -0x20(%rbp), %rdi
leaq 0x18827(%rip), %rsi     # 0x1b029
callq 0x18d50
testb $0x1, %al
jne 0x280d
jmp 0x2861
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x74(%rbp)
testl %eax, %eax
je 0x2826
jmp 0x281c
movl -0x74(%rbp), %eax
subl $0x1, %eax
je 0x2840
jmp 0x285d
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x40(%rbp), %rax
subq 0x18(%rax), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x285f
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
subsd 0x18(%rax), %xmm0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x285f
jmp 0x285f
jmp 0x2861
movq -0x20(%rbp), %rdi
leaq 0x1780c(%rip), %rsi     # 0x1a078
callq 0x18d50
testb $0x1, %al
jne 0x2877
jmp 0x28cc
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x78(%rbp)
testl %eax, %eax
je 0x2890
jmp 0x2886
movl -0x78(%rbp), %eax
subl $0x1, %eax
je 0x28ab
jmp 0x28c8
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x40(%rbp), %rax
imulq 0x18(%rax), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x28ca
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
mulsd 0x18(%rax), %xmm0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x28ca
jmp 0x28ca
jmp 0x28cc
movq -0x20(%rbp), %rdi
leaq 0x19300(%rip), %rsi     # 0x1bbd7
callq 0x18d50
testb $0x1, %al
jne 0x290d
movq -0x20(%rbp), %rdi
leaq 0x1778f(%rip), %rsi     # 0x1a07a
callq 0x18d50
testb $0x1, %al
jne 0x290d
movq -0x20(%rbp), %rdi
leaq 0x1777e(%rip), %rsi     # 0x1a07d
callq 0x18d50
testb $0x1, %al
jne 0x290d
jmp 0x2b1d
movq -0x40(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x2921
movq -0x40(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x293e
movq -0x40(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x297b
movq -0x40(%rbp), %rax
movsd 0x18(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x297b
jp 0x297b
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x20(%rbp), %rdx
leaq 0x1772e(%rip), %rdi     # 0x1a07f
movb $0x0, %al
callq 0x16600
movq %rax, -0x48(%rbp)
movq -0x38(%rbp), %rdi
callq 0x16cf0
movq -0x40(%rbp), %rdi
callq 0x16cf0
movq -0x48(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x2c68
movq -0x20(%rbp), %rdi
leaq 0x19251(%rip), %rsi     # 0x1bbd7
callq 0x2370
cmpq $0x0, %rax
je 0x2a80
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x4c(%rbp)
movq -0x40(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x50(%rbp)
movq -0x38(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x29e3
movq -0x40(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x29e3
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x40(%rbp), %rcx
cqto
idivq 0x18(%rcx)
cmpq $0x0, %rdx
je 0x29e3
movq -0x38(%rbp), %rdi
callq 0x17bc0
movq -0x40(%rbp), %rdi
callq 0x17bc0
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x7c(%rbp)
testl %eax, %eax
je 0x29fc
jmp 0x29f2
movl -0x7c(%rbp), %eax
subl $0x1, %eax
je 0x2a1b
jmp 0x2a38
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x40(%rbp), %rcx
cqto
idivq 0x18(%rcx)
movq %rax, %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x2a3a
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
divsd 0x18(%rax), %xmm0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x2a3a
jmp 0x2a3a
movq -0x20(%rbp), %rdi
leaq 0x17635(%rip), %rsi     # 0x1a07a
callq 0x18d50
testb $0x1, %al
jne 0x2a50
jmp 0x2a7b
cmpl $0x0, -0x4c(%rbp)
jne 0x2a67
cmpl $0x0, -0x50(%rbp)
jne 0x2a67
movq -0x38(%rbp), %rdi
callq 0x17bf0
jmp 0x2a79
movq -0x38(%rbp), %rdi
callq 0x17bf0
movq -0x38(%rbp), %rdi
callq 0x17bc0
jmp 0x2a7b
jmp 0x2b1b
movq -0x38(%rbp), %rax
cmpl $0x1, (%rax)
je 0x2a92
movq -0x40(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x2af9
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x80(%rbp)
testl %eax, %eax
je 0x2aab
jmp 0x2aa1
movl -0x80(%rbp), %eax
subl $0x1, %eax
je 0x2ad3
jmp 0x2af5
movq -0x38(%rbp), %rax
cvtsi2sdq 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
cvtsi2sdq 0x18(%rax), %xmm1
callq 0x25b0
cvttsd2si %xmm0, %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x2af7
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
movsd 0x18(%rax), %xmm1
callq 0x25b0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x2af7
jmp 0x2af7
jmp 0x2b19
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x40(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x2570
movq %rax, %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x2b1b
jmp 0x2b1d
movq -0x20(%rbp), %rdi
leaq 0x17571(%rip), %rsi     # 0x1a099
callq 0x18d50
testb $0x1, %al
jne 0x2b36
jmp 0x2c5a
movq -0x38(%rbp), %rax
cmpl $0x1, (%rax)
je 0x2b48
movq -0x40(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x2bb5
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x84(%rbp)
testl %eax, %eax
je 0x2b67
jmp 0x2b5a
movl -0x84(%rbp), %eax
subl $0x1, %eax
je 0x2b8f
jmp 0x2bb1
movq -0x38(%rbp), %rax
cvtsi2sdq 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
cvtsi2sdq 0x18(%rax), %xmm1
callq 0x20d0
cvttsd2si %xmm0, %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x2bb3
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
movsd 0x18(%rax), %xmm1
callq 0x20d0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x2bb3
jmp 0x2bb3
jmp 0x2c1e
movq -0x38(%rbp), %rax
cvtsi2sdq 0x18(%rax), %xmm0
movq -0x40(%rbp), %rax
cvtsi2sdq 0x18(%rax), %xmm1
callq 0x20d0
movsd %xmm0, -0x58(%rbp)
movsd -0x58(%rbp), %xmm0
cvttsd2si -0x58(%rbp), %rax
cvtsi2sd %rax, %xmm1
subsd %xmm1, %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x2bf4
jp 0x2bf4
jmp 0x2c0e
movq -0x38(%rbp), %rax
movl $0x1, (%rax)
movsd -0x58(%rbp), %xmm0
movq -0x38(%rbp), %rax
movsd %xmm0, 0x18(%rax)
jmp 0x2c1c
cvttsd2si -0x58(%rbp), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x2c1e
movq -0x38(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x2c58
movq -0x38(%rbp), %rax
movsd 0x18(%rax), %xmm0
ucomisd %xmm0, %xmm0
setp %al
testb $0x1, %al
jne 0x2c3d
jmp 0x2c58
movq -0x38(%rbp), %rdi
callq 0x16cf0
leaq 0x1744e(%rip), %rdi     # 0x1a09b
movb $0x0, %al
callq 0x16600
movq %rax, -0x38(%rbp)
jmp 0x2c5a
movq -0x40(%rbp), %rdi
callq 0x16cf0
jmp 0x2763
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x38(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)