// File: /workspace/github_c_makefile_star2_O0/voithos[P]awl/src/builtins.c
// Function: builtin_let
awlval* builtin_let(awlenv* e, awlval* a) {
    /* TODO: maybe fix DEFINE and GLOBAL to work like this too... */
    AWLASSERT_ARGCOUNT(a, 2, "let");
    AWLASSERT_TYPE(a, 0, AWLVAL_SEXPR, "let");

    awlval* bindings = a->cell[0];
    /* verify structure of inner bindings list */
    for (int i = 0; i < bindings->count; i++) {
        AWLASSERT(a, (bindings->cell[i]->type == AWLVAL_SEXPR),
                "function '%s' requires %s in binding list at position %i",
                "let", awlval_type_name(AWLVAL_SEXPR), i);

        AWLASSERT(a, (bindings->cell[i]->count == 2 && bindings->cell[i]->cell[0]->type == AWLVAL_SYM),
                "function '%s' bindings must have two parts: %s and value, at position %i",
                "let", awlval_type_name(AWLVAL_SYM), i);
    }

    for (int i = 0; i < bindings->count; i++) {
        int index = awlenv_index(e, bindings->cell[i]->cell[0]);
        AWLASSERT(a, index == -1,
                "cannot redefine '%s'", bindings->cell[i]->cell[0]->sym);
    }

    // TODO: Because of reference cycles, this causes garbage to build up
    // Need to add GC
    awlenv* lenv = awlenv_new();
    lenv->parent = e;
    lenv->parent->references++;

    /* Evaluate value arguments (but not the symbols) */
    for (int i = 0; i < bindings->count; i++) {
        bindings->cell[i] = awlval_eval_arg(lenv, bindings->cell[i], 1);

        if (bindings->cell[i]->type == AWLVAL_ERR) {
            awlval* err = awlval_pop(bindings, i);
            awlval_del(a);
            lenv->parent = NULL;
            awlenv_del(lenv);
            return err;
        }

        awlval* sym = bindings->cell[i]->cell[0];
        awlval* val = bindings->cell[i]->cell[1];

        awlenv_put(lenv, sym, val);
    }

    awlval* v = awlval_eval(lenv, awlval_take(a, 1));

    awlenv_del(lenv);
    return v;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x2, 0x4(%rax)
je 0x5cc8
movq -0x18(%rbp), %rax
movl 0x4(%rax), %ecx
leaq 0x14447(%rip), %rdi     # 0x1a0e2
leaq 0x14720(%rip), %rsi     # 0x1a3c2
movl $0x2, %edx
movb $0x0, %al
callq 0x16600
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x6014
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
cmpl $0xb, (%rax)
je 0x5d36
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
movl (%rax), %edi
callq 0x161a0
movq %rax, -0x90(%rbp)
movl $0xb, %edi
callq 0x161a0
movq -0x90(%rbp), %rcx
movq %rax, %r8
leaq 0x1441d(%rip), %rdi     # 0x1a129
leaq 0x146af(%rip), %rsi     # 0x1a3c2
xorl %edx, %edx
movb $0x0, %al
callq 0x16600
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x6014
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x5e31
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0xb, (%rax)
je 0x5db0
movl $0xb, %edi
callq 0x161a0
movq %rax, %rdx
movl -0x34(%rbp), %ecx
leaq 0x1463e(%rip), %rdi     # 0x1a3c6
leaq 0x14633(%rip), %rsi     # 0x1a3c2
movb $0x0, %al
callq 0x16600
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x40(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x6014
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x2, 0x4(%rax)
jne 0x5de2
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
cmpl $0x3, (%rax)
je 0x5e21
movl $0x3, %edi
callq 0x161a0
movq %rax, %rdx
movl -0x34(%rbp), %ecx
leaq 0x14606(%rip), %rdi     # 0x1a3ff
leaq 0x145c2(%rip), %rsi     # 0x1a3c2
movb $0x0, %al
callq 0x16600
movq %rax, -0x48(%rbp)
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x48(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x6014
jmp 0x5e23
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x5d4c
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x5ec0
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x4c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rax
movq (%rax), %rsi
callq 0x188d0
movl %eax, -0x50(%rbp)
cmpl $-0x1, -0x50(%rbp)
je 0x5eb0
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x4c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
movq 0x18(%rax), %rsi
leaq 0x14493(%rip), %rdi     # 0x1a322
movb $0x0, %al
callq 0x16600
movq %rax, -0x58(%rbp)
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x58(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x6014
jmp 0x5eb2
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x5e38
callq 0x16a70
movq %rax, -0x60(%rbp)
movq -0x10(%rbp), %rcx
movq -0x60(%rbp), %rax
movq %rcx, (%rax)
movq -0x60(%rbp), %rax
movq (%rax), %rax
movl 0x14(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x14(%rax)
movl $0x0, -0x64(%rbp)
movl -0x64(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x5fd1
movq -0x60(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x64(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movl $0x1, %edx
callq 0x7be0
movq %rax, %rdx
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x64(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x64(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x2, (%rax)
jne 0x5f7b
movq -0x30(%rbp), %rdi
movl -0x64(%rbp), %esi
callq 0x174b0
movq %rax, -0x70(%rbp)
movq -0x18(%rbp), %rdi
callq 0x16cf0
movq -0x60(%rbp), %rax
movq $0x0, (%rax)
movq -0x60(%rbp), %rdi
callq 0x16e00
movq -0x70(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x6014
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x64(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x64(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x60(%rbp), %rdi
movq -0x78(%rbp), %rsi
movq -0x80(%rbp), %rdx
callq 0x189b0
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x5eeb
movq -0x60(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x17560
movq -0x98(%rbp), %rdi
movq %rax, %rsi
callq 0x7770
movq %rax, -0x88(%rbp)
movq -0x60(%rbp), %rdi
callq 0x16e00
movq -0x88(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)