// File: /workspace/github_c_makefile_star2_O1/voithos[P]awl/src/eval.c
// Function: awlval_eval
awlval* awlval_eval(awlenv* e, awlval* v) {
    bool recursing = false;

    while (true) {
        // Handle abort
        if (eval_aborted) {
            AWLENV_DEL_RECURSING(e);
            awlval_del(v);

            eval_aborted = false;
            return awlval_err("eval aborted");
        }

        switch (v->type) {
            case AWLVAL_SYM:
            {
                awlval* x = awlenv_get(e, v);
                awlval_del(v);
                AWLENV_DEL_RECURSING(e);
                return x;
                break;
            }

            case AWLVAL_SEXPR:
            {
                awlval* x = awlval_eval_sexpr(e, v);

                /* recursively evaluate results */
                if (x->type == AWLVAL_FN && x->called) {
                    AWLENV_DEL_RECURSING(e);
                    recursing = true;

                    e = awlenv_copy(x->env);
                    v = awlval_copy(x->body);

                    awlval_del(x);
                } else {
                    /* evaluate result in next loop */
                    v = x;
                }
                break;
            }

            case AWLVAL_QEXPR:
            {
                awlval* x = awlval_eval_inside_qexpr(e, v);
                AWLENV_DEL_RECURSING(e);
                return x;
                break;
            }

            case AWLVAL_EEXPR:
            case AWLVAL_CEXPR:
            {
                AWLENV_DEL_RECURSING(e);
                awlval* err = awlval_err("cannot directly evaluate %s; must be contained inside %s",
                        awlval_type_name(v->type), awlval_type_name(AWLVAL_QEXPR));
                awlval_del(v);
                return err;
            }

            default:
                AWLENV_DEL_RECURSING(e);
                return v;
                break;
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
cmpb $0x0, 0x1544d(%rip)     # 0x1b2f1
je 0x5edd
xorl %ebp, %ebp
testb $0x1, %bpl
je 0x5eb6
movq %r14, %rdi
callq 0x107f6
movq %rbx, %rdi
callq 0x10767
movb $0x0, 0x1542c(%rip)     # 0x1b2f1
leaq 0xc728(%rip), %rdi      # 0x125f4
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x1032f
xorl %ebp, %ebp
movl (%rbx), %eax
cmpl $0xb, %eax
jne 0x5f41
movq %r14, %rdi
movq %rbx, %rsi
callq 0x5fee
movq %rax, %rbx
cmpl $0x8, (%rax)
jne 0x5f33
cmpb $0x1, 0x30(%rbx)
jne 0x5f33
testb $0x1, %bpl
je 0x5f0d
movq %r14, %rdi
callq 0x107f6
movq 0x18(%rbx), %rdi
callq 0x1102d
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0x10a5f
movq %rax, %r15
movq %rbx, %rdi
callq 0x10767
movb $0x1, %bpl
movq %r15, %rbx
cmpb $0x0, 0x153b7(%rip)     # 0x1b2f1
je 0x5edf
jmp 0x5ea8
leal -0xd(%rax), %ecx
cmpl $0x2, %ecx
jb 0x5f6b
cmpl $0xc, %eax
je 0x5fb1
cmpl $0x3, %eax
jne 0x5fcf
movq %r14, %rdi
movq %rbx, %rsi
callq 0x11905
movq %rax, %r15
movq %rbx, %rdi
callq 0x10767
jmp 0x5fbf
testb $0x1, %bpl
je 0x5f79
movq %r14, %rdi
callq 0x107f6
movl (%rbx), %edi
callq 0x10138
movq %rax, %r14
movl $0xc, %edi
callq 0x10138
leaq 0xc66d(%rip), %rdi      # 0x12601
movq %r14, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x1032f
movq %rax, %r14
movq %rbx, %rdi
callq 0x10767
movq %r14, %rax
jmp 0x5fe3
movq %r14, %rdi
movq %rbx, %rsi
callq 0x60ad
movq %rax, %r15
testb $0x1, %bpl
je 0x5fe0
movq %r14, %rdi
callq 0x107f6
jmp 0x5fe0
testb $0x1, %bpl
je 0x5fdd
movq %r14, %rdi
callq 0x107f6
movq %rbx, %r15
movq %r15, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq