// File: /workspace/github_c_makefile_star2_O0/johnvtan[P]ccccc/parse.c
// Function: new_fn_call
static expr_t *new_fn_call(fn_def_t *fn_def, list_t *tokens, env_t *env) {
    expr_t *expr = malloc(sizeof(expr_t));
    expr->type = PRIMARY;

    expr->primary = malloc(sizeof(primary_t));
    expr->primary->type = PRIMARY_FN_CALL;

    expr->primary->fn_call = malloc(sizeof(fn_call_t));
    expr->primary->fn_call->fn_name = fn_def->name;
    expr->primary->fn_call->param_exprs = NULL;
    expr->c_type = fn_def->ret_type;

    // Parse parameter expressions
    expect_next(tokens, TOK_OPEN_PAREN);
    
    // Handle functions without parameters.
    if (!fn_def->params || fn_def->params->len == 0) {
        if (match(tokens, TOK_CLOSE_PAREN)) {
            return expr;
        } else {
            UNREACHABLE("new_fn_call: Mismatching function call - declaration has no params, but call has some\n");
        }
    }

    expr->primary->fn_call->param_exprs = list_new();

    string_t *param_name;
    list_for_each(fn_def->params, param_name) {
        expr_t *param_expr = parse_expr(tokens, env); 
        var_info_t *param_info = map_get(fn_def->env->homes, param_name); 
        debug("parsing param %s\n", string_get(param_name));
        debug("declared type %u, expr type %u\n", param_info->type, param_expr->c_type);
        if (param_expr->c_type != param_info->type) {
            UNREACHABLE("new_fn_call: param expr type doesn't match declaration\n");
        }
        list_push(expr->primary->fn_call->param_exprs, param_expr);
        if (match(tokens, TOK_CLOSE_PAREN)) {
            break;
        }
        expect_next(tokens, TOK_COMMA);
    }

    if (fn_def->params->len != expr->primary->fn_call->param_exprs->len) {
        UNREACHABLE("new_fn_call: number of parsed param exprs doesn't match number in declaration\n");
    }

    debug("new_fn_call: done\n");
    return expr;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl $0x10, %edi
callq 0x10e0
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movl $0x0, (%rax)
movl $0x10, %edi
callq 0x10e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movl $0x4, (%rax)
movl $0x10, %edi
callq 0x10e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movq $0x0, 0x8(%rax)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x18(%rbp), %rdi
movl $0xe, %esi
callq 0x5800
movq -0x10(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x7757
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
cmpl $0x0, 0x18(%rax)
jne 0x77a5
movq -0x18(%rbp), %rdi
movl $0xf, %esi
callq 0x56a0
testb $0x1, %al
jne 0x776b
jmp 0x7778
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x78fc
jmp 0x777a
leaq 0x1883(%rip), %rdi      # 0x9004
leaq 0x2059(%rip), %rsi      # 0x97e1
movl $0xd7, %edx
leaq 0x2310(%rip), %rcx      # 0x9aa4
movb $0x0, %al
callq 0x1070
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x1110
callq 0x45f0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rax
movq 0x8(%rax), %rcx
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rcx, 0x10(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
addq $0x10, %rdi
leaq -0x30(%rbp), %rsi
callq 0x49c0
testb $0x1, %al
jne 0x77f6
jmp 0x78a3
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x6180
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq (%rax), %rdi
movq -0x30(%rbp), %rsi
callq 0x4ba0
movq %rax, -0x40(%rbp)
jmp 0x7821
jmp 0x7823
jmp 0x7825
movq -0x38(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x40(%rbp), %rcx
cmpl (%rcx), %eax
je 0x7861
jmp 0x7836
leaq 0x17c7(%rip), %rdi      # 0x9004
leaq 0x1f9d(%rip), %rsi      # 0x97e1
movl $0xe4, %edx
leaq 0x22ab(%rip), %rcx      # 0x9afb
movb $0x0, %al
callq 0x1070
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x1110
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rdi
movq -0x38(%rbp), %rsi
callq 0x46a0
movq -0x18(%rbp), %rdi
movl $0xf, %esi
callq 0x56a0
testb $0x1, %al
jne 0x788e
jmp 0x7890
jmp 0x78a3
movq -0x18(%rbp), %rdi
movl $0x13, %esi
callq 0x5800
jmp 0x77d8
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movl 0x18(%rax), %eax
movq -0x28(%rbp), %rcx
movq 0x8(%rcx), %rcx
movq 0x8(%rcx), %rcx
movq 0x8(%rcx), %rcx
cmpl 0x18(%rcx), %eax
je 0x78f0
jmp 0x78c5
leaq 0x1738(%rip), %rdi      # 0x9004
leaq 0x1f0e(%rip), %rsi      # 0x97e1
movl $0xee, %edx
leaq 0x2254(%rip), %rcx      # 0x9b33
movb $0x0, %al
callq 0x1070
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x1110
jmp 0x78f2
jmp 0x78f4
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)