// File: /workspace/github_c_makefile_star2_O1/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, %rbx
callq 0x6214
movq %rax, %rbp
cmpl $0x2, (%rax)
jne 0x2d36
movq %rbp, %r14
jmp 0x3164
movslq 0x4(%rbp), %rax
testq %rax, %rax
setg %r12b
jle 0x2da9
movq 0x8(%rbp), %rcx
movq (%rcx), %rdx
movl (%rdx), %edi
xorl %r15d, %r15d
cmpl $0x1, %edi
ja 0x2d76
leaq -0x1(%rax), %rdx
xorl %r15d, %r15d
cmpq %r15, %rdx
je 0x2d9f
movq 0x8(%rcx,%r15,8), %rsi
movl (%rsi), %edi
incq %r15
cmpl $0x2, %edi
jb 0x2d5b
cmpq %rax, %r15
setb %r12b
callq 0x10138
leaq 0xf2be(%rip), %rdi      # 0x12040
movq %rbx, %rsi
movl %r15d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x1032f
movq %rax, %r14
movq %rbp, %rdi
callq 0x10767
jmp 0x2da9
incq %r15
cmpq %rax, %r15
setb %r12b
testb %r12b, %r12b
jne 0x3164
movq %rbp, %rdi
xorl %esi, %esi
callq 0x10c23
movq %rax, %r14
leaq 0xff23(%rip), %rsi      # 0x12ce9
movq %rbx, %rdi
callq 0x11b89
testb %al, %al
je 0x2ddc
cmpl $0x0, 0x4(%rbp)
je 0x3176
cmpl $0x0, 0x4(%rbp)
jle 0x315c
movq %rbp, %rdi
xorl %esi, %esi
callq 0x10c23
movq %rax, %r13
movq %r14, %rdi
movq %rax, %rsi
callq 0x10fb2
movq %rbx, %rdi
leaq 0xf286(%rip), %rsi      # 0x1208e
callq 0x11b89
testb %al, %al
je 0x2e39
movl (%r14), %eax
cmpl $0x1, %eax
je 0x2e27
testl %eax, %eax
jne 0x2e39
movq 0x18(%r13), %rax
addq %rax, 0x18(%r14)
jmp 0x2e39
movsd 0x18(%r14), %xmm0
addsd 0x18(%r13), %xmm0
movsd %xmm0, 0x18(%r14)
movq %rbx, %rdi
leaq 0xfea6(%rip), %rsi      # 0x12ce9
callq 0x11b89
testb %al, %al
je 0x2e74
movl (%r14), %eax
cmpl $0x1, %eax
je 0x2e62
testl %eax, %eax
jne 0x2e74
movq 0x18(%r13), %rax
subq %rax, 0x18(%r14)
jmp 0x2e74
movsd 0x18(%r14), %xmm0
subsd 0x18(%r13), %xmm0
movsd %xmm0, 0x18(%r14)
movq %rbx, %rdi
leaq 0xf212(%rip), %rsi      # 0x12090
callq 0x11b89
testb %al, %al
je 0x2eb4
movl (%r14), %eax
cmpl $0x1, %eax
je 0x2ea2
testl %eax, %eax
jne 0x2eb4
movq 0x18(%r13), %rax
imulq 0x18(%r14), %rax
movq %rax, 0x18(%r14)
jmp 0x2eb4
movsd 0x18(%r14), %xmm0
mulsd 0x18(%r13), %xmm0
movsd %xmm0, 0x18(%r14)
movq %rbx, %rdi
leaq 0x109d1(%rip), %rsi     # 0x1388f
callq 0x11b89
testb %al, %al
jne 0x2ef1
movq %rbx, %rdi
leaq 0xf1c1(%rip), %rsi      # 0x12092
callq 0x11b89
testb %al, %al
jne 0x2ef1
movq %rbx, %rdi
leaq 0xf1b1(%rip), %rsi      # 0x12095
callq 0x11b89
testb %al, %al
je 0x3077
movl (%r13), %r12d
testl %r12d, %r12d
jne 0x2f01
cmpq $0x0, 0x18(%r13)
je 0x2f19
cmpl $0x1, %r12d
jne 0x2f4c
movsd 0x18(%r13), %xmm0
ucomisd 0xf11b(%rip), %xmm0     # 0x12030
jne 0x2f4c
jp 0x2f4c
movq 0x18(%r14), %rsi
xorl %r12d, %r12d
leaq 0xf170(%rip), %rdi      # 0x12097
movq %rbx, %rdx
xorl %eax, %eax
callq 0x1032f
movq %rax, %r15
movq %r14, %rdi
callq 0x10767
movq %r13, %rdi
callq 0x10767
movq %r15, %r14
jmp 0x3136
movq %rbx, %rdi
movl $0x2f, %esi
callq 0x2120
movl (%r14), %r15d
testq %rax, %rax
je 0x2fa1
orl %r12d, %r15d
jne 0x2f85
movq 0x18(%r14), %rax
cqto
idivq 0x18(%r13)
testq %rdx, %rdx
je 0x2f85
movq %r14, %rdi
callq 0x11000
movq %r13, %rdi
callq 0x11000
movl (%r14), %eax
cmpl $0x1, %eax
je 0x2fd7
testl %eax, %eax
jne 0x2fe9
movq 0x18(%r14), %rax
cqto
idivq 0x18(%r13)
movq %rax, 0x18(%r14)
jmp 0x2fe9
cmpl $0x1, %r12d
je 0x3013
cmpl $0x1, %r15d
je 0x3013
movq 0x18(%r14), %rcx
movq 0x18(%r13), %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(%r14)
jmp 0x3077
movsd 0x18(%r14), %xmm0
divsd 0x18(%r13), %xmm0
movsd %xmm0, 0x18(%r14)
movq %rbx, %rdi
leaq 0xf09f(%rip), %rsi      # 0x12092
callq 0x11b89
testb %al, %al
je 0x3077
movq %r14, %rdi
callq 0x11017
testl %r15d, %r15d
je 0x3077
movq %r14, %rdi
callq 0x11000
jmp 0x3077
cmpl $0x1, %r15d
je 0x3050
testl %r15d, %r15d
jne 0x3077
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%r14), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x18(%r13), %xmm1
movapd 0xefd8(%rip), %xmm2     # 0x12010
andpd %xmm2, %xmm0
andpd %xmm2, %xmm1
callq 0x21a0
cvttsd2si %xmm0, %rax
movq %rax, 0x18(%r14)
jmp 0x3077
movsd 0x18(%r14), %xmm0
movapd 0xefb2(%rip), %xmm2     # 0x12010
andpd %xmm2, %xmm0
movsd 0x18(%r13), %xmm1
andpd %xmm2, %xmm1
callq 0x21a0
movsd %xmm0, 0x18(%r14)
movq %rbx, %rdi
leaq 0xf030(%rip), %rsi      # 0x120b1
callq 0x11b89
testb %al, %al
je 0x312b
movl (%r14), %eax
cmpl $0x1, %eax
jne 0x30af
movsd 0x18(%r14), %xmm0
movsd 0x18(%r13), %xmm1
callq 0x20f0
movsd %xmm0, 0x18(%r14)
jmp 0x3119
cmpl $0x1, (%r13)
jne 0x30dd
cmpl $0x1, %eax
je 0x3096
testl %eax, %eax
jne 0x3119
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%r14), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x18(%r13), %xmm1
callq 0x20f0
cvttsd2si %xmm0, %rax
jmp 0x3115
xorps %xmm0, %xmm0
cvtsi2sdq 0x18(%r14), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x18(%r13), %xmm1
callq 0x20f0
cvttsd2si %xmm0, %rax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
ucomisd %xmm1, %xmm0
jne 0x3109
jnp 0x3115
movl $0x1, (%r14)
movq %xmm0, %rax
movq %rax, 0x18(%r14)
cmpl $0x1, (%r14)
jne 0x312b
movsd 0x18(%r14), %xmm0
ucomisd %xmm0, %xmm0
jp 0x3141
movq %r13, %rdi
callq 0x10767
movb $0x1, %r12b
testb %r12b, %r12b
jne 0x2ddc
jmp 0x315c
movq %r14, %rdi
callq 0x10767
leaq 0xef63(%rip), %rdi      # 0x120b3
xorl %eax, %eax
callq 0x1032f
movq %rax, %r14
jmp 0x312b
movq %rbp, %rdi
callq 0x10767
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl (%r14), %eax
cmpl $0x1, %eax
je 0x318f
testl %eax, %eax
jne 0x2ddc
negq 0x18(%r14)
jmp 0x2ddc
movsd 0x18(%r14), %xmm0
xorpd 0xee83(%rip), %xmm0     # 0x12020
movlpd %xmm0, 0x18(%r14)
jmp 0x2ddc