// File: /workspace/github_c_makefile_star2_O0/johnvtan[P]ccccc/parse.c
// Function: parse_fn_declaration
static fn_def_t *parse_fn_declaration(list_t *tokens) {
    fn_def_t *fn = malloc(sizeof(fn_def_t));

    // TODO The only difference between a function declaration and definition
    // is that stmts will be NULL in a declaration
    fn->stmts = NULL; 
    fn->params = NULL;

    fn->env = env_new(global_env);

    // first token should be a type
    token_t *curr = list_pop(tokens);
    if (!curr) {
        UNREACHABLE("parse_fn_declaration: No more tokens but there should be more?\n");
    }

    fn->ret_type = token_to_builtin_type(curr->type);

    // next should be an identifier
    curr = expect_next(tokens, TOK_IDENT);
    fn->name = curr->ident;

    debug("parse_fn_declaration: Parsing function %s\n", string_get(fn->name));

    // parsing parameters
    expect_next(tokens, TOK_OPEN_PAREN);

    if (match(tokens, TOK_CLOSE_PAREN)) {
        return fn;
    }

    if (match(tokens, TOK_VOID_TYPE)) {
        expect_next(tokens, TOK_CLOSE_PAREN);
        return fn;
    }

    // Parse parameter list
    fn->params = list_new();
    while (tokens->len) {
        list_push(fn->params, parse_param(tokens, fn->env));
        if (match(tokens, TOK_CLOSE_PAREN)) {
            break;
        }
        expect_next(tokens, TOK_COMMA);
    }
    return fn;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x10(%rbp)
movl $0x30, %edi
callq 0x10e0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq $0x0, 0x10(%rax)
movq -0x18(%rbp), %rax
movq $0x0, 0x18(%rax)
movq 0x7d17(%rip), %rdi      # 0xd0b0
callq 0x4430
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x10(%rbp), %rdi
callq 0x47d0
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x53ea
jmp 0x53bf
leaq 0x3c3e(%rip), %rdi      # 0x9004
leaq 0x4414(%rip), %rsi      # 0x97e1
movl $0x33f, %edx            # imm = 0x33F
leaq 0x446d(%rip), %rcx      # 0x9846
movb $0x0, %al
callq 0x1070
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x1110
movq -0x20(%rbp), %rax
movl (%rax), %edi
callq 0x5790
movl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x10(%rbp), %rdi
movl $0x3, %esi
callq 0x5800
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
jmp 0x5421
movq -0x10(%rbp), %rdi
movl $0xe, %esi
callq 0x5800
movq -0x10(%rbp), %rdi
movl $0xf, %esi
callq 0x56a0
testb $0x1, %al
jne 0x5443
jmp 0x5450
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x54ed
movq -0x10(%rbp), %rdi
movl $0x7, %esi
callq 0x56a0
testb $0x1, %al
jne 0x5464
jmp 0x547c
movq -0x10(%rbp), %rdi
movl $0xf, %esi
callq 0x5800
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x54ed
callq 0x45f0
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x18(%rax)
je 0x54e5
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rsi
callq 0x5870
movq -0x28(%rbp), %rdi
movq %rax, %rsi
callq 0x46a0
movq -0x10(%rbp), %rdi
movl $0xf, %esi
callq 0x56a0
testb $0x1, %al
jne 0x54d3
jmp 0x54d5
jmp 0x54e5
movq -0x10(%rbp), %rdi
movl $0x13, %esi
callq 0x5800
jmp 0x548c
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nopw (%rax,%rax)