// File: /workspace/github_c_makefile_star2_O2/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 %r12
pushq %rbx
movq %rsi, %rbx
movq %rdi, %r14
xorl %ebp, %ebp
leaq 0xb321(%rip), %r12      # 0x105e0
cmpb $0x1, 0x1402b(%rip)     # 0x192f1
je 0x5376
movl (%rbx), %edi
leal -0x3(%rdi), %eax
cmpl $0xb, %eax
ja 0x53df
movslq (%r12,%rax,4), %rax
addq %r12, %rax
jmpq *%rax
movq %r14, %rdi
movq %rbx, %rsi
callq 0x53fc
movq %rax, %rbx
cmpl $0x8, (%rax)
jne 0x52bf
cmpb $0x1, 0x30(%rbx)
jne 0x52bf
testb $0x1, %bpl
je 0x530a
movq %r14, %rdi
callq 0xdf56
movq 0x18(%rbx), %rdi
callq 0xe5f3
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0xe16d
movq %rax, %r15
movq %rbx, %rdi
callq 0xded1
movb $0x1, %bpl
movq %r15, %rbx
jmp 0x52bf
testb $0x1, %bpl
je 0x5342
movq %r14, %rdi
callq 0xdf56
movl (%rbx), %edi
callq 0xd97c
movq %rax, %r14
pushq $0xc
popq %rdi
callq 0xd97c
leaq 0xb2c4(%rip), %rdi      # 0x1061d
movq %r14, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0xdb45
movq %rax, %r14
movq %rbx, %rdi
callq 0xded1
movq %r14, %rax
jmp 0x53f3
testb $0x1, %bpl
je 0x5384
movq %r14, %rdi
callq 0xdf56
movq %rbx, %rdi
callq 0xded1
movb $0x0, 0x13f5e(%rip)     # 0x192f1
leaq 0xb276(%rip), %rdi      # 0x10610
xorl %eax, %eax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0xdb45
movq %r14, %rdi
movq %rbx, %rsi
callq 0x54b7
movq %rax, %r15
jmp 0x53cf
movq %r14, %rdi
movq %rbx, %rsi
callq 0xee6a
movq %rax, %r15
movq %rbx, %rdi
callq 0xded1
testb $0x1, %bpl
je 0x53f0
movq %r14, %rdi
callq 0xdf56
jmp 0x53f0
testb $0x1, %bpl
je 0x53ed
movq %r14, %rdi
callq 0xdf56
movq %rbx, %r15
movq %r15, %rax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq