// File: /workspace/github_c_makefile_star2_O0/samsonjs[P]lake/src/eval.c
// Function: apply
LakeVal *apply(LakeCtx *ctx, LakeVal *fnVal, LakeList *args)
{
    LakeVal *result = NULL;
    if (lake_is_type(TYPE_PRIM, fnVal))
    {
        LakePrimitive *prim = PRIM(fnVal);
        int arity = prim->arity;
        if (arity == ARITY_VARARGS || LIST_N(args) == arity)
        {
            result = prim->fn(ctx, args);
        }
        else
        {
            ERR("%s expects %d params but got %zu", prim->name, arity,
                LIST_N(args));
            result = NULL;
        }
    }
    else if (lake_is_type(TYPE_FN, fnVal))
    {
        LakeFn *fn = FN(fnVal);

        /* Check # of params */
        size_t nparams = LIST_N(fn->params);
        if (!fn->varargs && LIST_N(args) != nparams)
        {
            ERR("expected %zu params but got %zu", nparams, LIST_N(args));
            return NULL;
        }
        else if (fn->varargs && LIST_N(args) < nparams)
        {
            ERR("expected at least %zu params but got %zu", nparams,
                LIST_N(args));
            return NULL;
        }

        Env *env = env_make(fn->closure);

        /* bind each (param,arg) pair in env */
        size_t i;
        for (i = 0; i < nparams; ++i)
        {
            env_define(env, SYM(LIST_VAL(fn->params, i)), LIST_VAL(args, i));
        }

        /* bind varargs */
        if (fn->varargs)
        {
            LakeList *remainingArgs =
                list_make_with_capacity(LIST_N(args) - nparams);
            for (; i < LIST_N(args); ++i)
            {
                list_append(remainingArgs, LIST_VAL(args, i));
            }
            env_define(env, fn->varargs, VAL(remainingArgs));
        }

        /* evaluate body */
        result = eval_exprs1(ctx, env, fn->body);
    }
    else
    {
        ERR("not a function: %s", lake_repr(fnVal));
    }
    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x18(%rbp), %rsi
movl $0x7, %edi
callq 0x40d0
cmpl $0x0, %eax
je 0x2dc1
movq -0x18(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movl 0x18(%rax), %eax
movl %eax, -0x34(%rbp)
cmpl $-0x1, -0x34(%rbp)
je 0x2d3f
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rax
movslq -0x34(%rbp), %rcx
cmpq %rcx, %rax
jne 0x2d57
movq -0x30(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq *%rax
movq %rax, -0x28(%rbp)
jmp 0x2dbc
jmp 0x2d59
movq 0xa298(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x62f4(%rip), %rsi      # 0x905e
movb $0x0, %al
callq 0x1160
movq 0xa280(%rip), %rax      # 0xcff8
movq (%rax), %rdi
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rdx
movl -0x34(%rbp), %ecx
movq -0x20(%rbp), %rax
movq 0x18(%rax), %r8
leaq 0x6320(%rip), %rsi      # 0x90b5
movb $0x0, %al
callq 0x1160
movq 0xa255(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x6633(%rip), %rsi      # 0x93e0
movb $0x0, %al
callq 0x1160
movq $0x0, -0x28(%rbp)
jmp 0x30e0
movq -0x18(%rbp), %rsi
movl $0x8, %edi
callq 0x40d0
cmpl $0x0, %eax
je 0x3078
movq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x18(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rax
cmpq $0x0, 0x18(%rax)
jne 0x2e6c
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rax
cmpq -0x48(%rbp), %rax
je 0x2e6c
jmp 0x2e0b
movq 0xa1e6(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x6242(%rip), %rsi      # 0x905e
movb $0x0, %al
callq 0x1160
movq 0xa1ce(%rip), %rax      # 0xcff8
movq (%rax), %rdi
movq -0x48(%rbp), %rdx
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rcx
leaq 0x6296(%rip), %rsi      # 0x90d6
movb $0x0, %al
callq 0x1160
movq 0xa1aa(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x6588(%rip), %rsi      # 0x93e0
movb $0x0, %al
callq 0x1160
movq $0x0, -0x8(%rbp)
jmp 0x30e8
movq -0x40(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x2ee8
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rax
cmpq -0x48(%rbp), %rax
jae 0x2ee8
jmp 0x2e87
movq 0xa16a(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x61c6(%rip), %rsi      # 0x905e
movb $0x0, %al
callq 0x1160
movq 0xa152(%rip), %rax      # 0xcff8
movq (%rax), %rdi
movq -0x48(%rbp), %rdx
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rcx
leaq 0x623a(%rip), %rsi      # 0x90f6
movb $0x0, %al
callq 0x1160
movq 0xa12e(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x650c(%rip), %rsi      # 0x93e0
movb $0x0, %al
callq 0x1160
movq $0x0, -0x8(%rbp)
jmp 0x30e8
jmp 0x2eea
movq -0x40(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x1960
movq %rax, -0x50(%rbp)
movq $0x0, -0x58(%rbp)
movq -0x58(%rbp), %rax
cmpq -0x48(%rbp), %rax
jae 0x2fb1
movq -0x50(%rbp), %rax
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x58(%rbp)
jb 0x2f4c
movq -0x58(%rbp), %rax
movq -0x40(%rbp), %rcx
movq 0x10(%rcx), %rcx
cmpq 0x18(%rcx), %rax
jae 0x2f4c
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x20(%rax), %rax
movq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x70(%rbp)
jmp 0x2f54
xorl %eax, %eax
movq %rax, -0x70(%rbp)
jmp 0x2f54
movq -0x70(%rbp), %rax
movq %rax, -0x78(%rbp)
cmpq $0x0, -0x58(%rbp)
jb 0x2f87
movq -0x58(%rbp), %rax
movq -0x20(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jae 0x2f87
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x80(%rbp)
jmp 0x2f8f
xorl %eax, %eax
movq %rax, -0x80(%rbp)
jmp 0x2f8f
movq -0x78(%rbp), %rsi
movq -0x68(%rbp), %rdi
movq -0x80(%rbp), %rdx
callq 0x1a10
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x2f03
movq -0x40(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x305d
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rdi
subq -0x48(%rbp), %rdi
callq 0x4680
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rax
movq -0x20(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jae 0x3048
movq -0x60(%rbp), %rax
movq %rax, -0x88(%rbp)
cmpq $0x0, -0x58(%rbp)
jb 0x301c
movq -0x58(%rbp), %rax
movq -0x20(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jae 0x301c
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x90(%rbp)
jmp 0x3027
xorl %eax, %eax
movq %rax, -0x90(%rbp)
jmp 0x3027
movq -0x88(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x47f0
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x2fd5
movq -0x50(%rbp), %rdi
movq -0x40(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x60(%rbp), %rdx
callq 0x1a10
movq -0x10(%rbp), %rdi
movq -0x50(%rbp), %rsi
movq -0x40(%rbp), %rax
movq 0x20(%rax), %rdx
callq 0x31c0
movq %rax, -0x28(%rbp)
jmp 0x30de
jmp 0x307a
movq 0x9f77(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x5fd3(%rip), %rsi      # 0x905e
movb $0x0, %al
callq 0x1160
movq 0x9f5f(%rip), %rax      # 0xcff8
movq (%rax), %rax
movq %rax, -0x98(%rbp)
movq -0x18(%rbp), %rdi
callq 0x40f0
movq -0x98(%rbp), %rdi
movq %rax, %rdx
leaq 0x6062(%rip), %rsi      # 0x911f
movb $0x0, %al
callq 0x1160
movq 0x9f2d(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x630b(%rip), %rsi      # 0x93e0
movb $0x0, %al
callq 0x1160
jmp 0x30de
jmp 0x30e0
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)