// File: /workspace/github_c_makefile_star2_O3/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
cmpb $0x0, 0x156f8(%rip)     # 0x1b2f1
je 0x5c22
movq %rbx, %rdi
callq 0x1029f
movb $0x0, 0x156e7(%rip)     # 0x1b2f1
leaq 0xc9cf(%rip), %rdi      # 0x125e0
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0xfe6b
movq %rdi, %r14
xorl %ebp, %ebp
movl (%rbx), %edi
cmpl $0xb, %edi
jne 0x5c9b
movq %r14, %rdi
movq %rbx, %rsi
callq 0x5d48
movq %rax, %rbx
cmpl $0x8, (%rax)
jne 0x5c7b
cmpb $0x1, 0x30(%rbx)
jne 0x5c7b
testb $0x1, %bpl
je 0x5c55
movq %r14, %rdi
callq 0x1032e
movq 0x18(%rbx), %rdi
callq 0x10b56
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0x10597
movq %rax, %r15
movq %rbx, %rdi
callq 0x1029f
movb $0x1, %bpl
movq %r15, %rbx
cmpb $0x0, 0x1566f(%rip)     # 0x1b2f1
je 0x5c27
testb $0x1, %bpl
je 0x5bfb
movq %r14, %rdi
callq 0x1032e
jmp 0x5bfb
leal -0xd(%rdi), %eax
cmpl $0x2, %eax
jb 0x5cc5
cmpl $0xc, %edi
je 0x5d0b
cmpl $0x3, %edi
jne 0x5d29
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1140c
movq %rax, %r15
movq %rbx, %rdi
callq 0x1029f
jmp 0x5d19
testb $0x1, %bpl
je 0x5cd5
movq %r14, %rdi
callq 0x1032e
movl (%rbx), %edi
callq 0xfc74
movq %rax, %r14
movl $0xc, %edi
callq 0xfc74
leaq 0xc8ff(%rip), %rdi      # 0x125ed
movq %r14, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0xfe6b
movq %rax, %r14
movq %rbx, %rdi
callq 0x1029f
movq %r14, %rax
jmp 0x5d3d
movq %r14, %rdi
movq %rbx, %rsi
callq 0x5e07
movq %rax, %r15
testb $0x1, %bpl
je 0x5d3a
movq %r14, %rdi
callq 0x1032e
jmp 0x5d3a
testb $0x1, %bpl
je 0x5d37
movq %r14, %rdi
callq 0x1032e
movq %rbx, %r15
movq %r15, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq