// File: cphinton42[P]hinton-language/src/check.cpp
// Function: typecheck_decl(Context*, unsigned int, Decl_AST*)
internal
bool typecheck_decl(Context *ctx, u32 stage, Decl_AST *decl_ast)
{
    u32 new_stage = 0;
    
    switch(stage)
    {
        case 0: {
            if(decl_ast->decl_type)
            {
                auto job = make_typecheck_job(&type_t_ast, decl_ast->decl_type);
                do_typecheck_job(ctx, job);
            }
        } // fall through
        case 1: {
            new_stage = 1;
            if(decl_ast->decl_type && !type_resolved(decl_ast->decl_type))
            {
                break;
            }
            if(decl_ast->expr)
            {
                Expr_AST *type_to_match = nullptr;
                if(decl_ast->decl_type)
                {
                    assert(type_resolved(decl_ast->decl_type));
                    type_to_match = decl_ast->decl_type;
                }
                auto job = make_typecheck_job(type_to_match, decl_ast->expr);
                do_typecheck_job(ctx, job);
            }
        } // fall through
        case 2: {
            new_stage = 2;
            if(decl_ast->expr && !type_resolved(decl_ast->expr))
            {
                break;
            }
            if(decl_ast->expr)
            {
                ident_set_expr(&decl_ast->ident, decl_ast->expr);
            }
            if(decl_ast->decl_type)
            {
                set_resolved_type(&decl_ast->ident, decl_ast->decl_type);
            }
            else if(decl_ast->expr)
            {
                set_resolved_type(&decl_ast->ident, decl_ast->expr->resolved_type);
            }
            else
            {
                // TODO: this should be an enum value
            }
            new_stage = 3;
        } // fall through
    }
    
    if(new_stage < 3)
    {
        auto job = make_typecheck_job(nullptr, decl_ast, new_stage);
        array_add(ctx->waiting_jobs, job);
    }
    return new_stage != stage;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0xcc(%rbp)
testl %eax, %eax
je 0x566d
jmp 0x564c
movl -0xcc(%rbp), %eax
subl $0x1, %eax
je 0x56d2
jmp 0x5659
movl -0xcc(%rbp), %eax
subl $0x2, %eax
je 0x57b9
jmp 0x5851
movq -0x18(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0x56d0
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rdx
leaq -0x38(%rbp), %rdi
leaq 0x1a865(%rip), %rsi     # 0x1fef0
xorl %ecx, %ecx
callq 0x4a80
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
leaq -0x50(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
jmp 0x56d2
movl $0x1, -0x1c(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0x56fa
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x56fa
jmp 0x5851
movq -0x18(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x57b7
movq $0x0, -0x58(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0x575c
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x572f
jmp 0x5731
jmp 0x5750
leaq 0x15054(%rip), %rdi     # 0x1a78c
leaq 0x147ad(%rip), %rsi     # 0x19eec
movl $0x100, %edx            # imm = 0x100
leaq 0x15064(%rip), %rcx     # 0x1a7af
callq 0x3080
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdx
leaq -0x70(%rbp), %rdi
xorl %ecx, %ecx
callq 0x4a80
movq -0x8(%rbp), %rdi
movq -0x70(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x88(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x4b40
jmp 0x57b9
movl $0x2, -0x1c(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x57de
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x5600
testb $0x1, %al
jne 0x57de
jmp 0x5851
movq -0x18(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x57fe
movq -0x18(%rbp), %rdi
addq $0x10, %rdi
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rsi
callq 0x17c00
movq -0x18(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0x5820
movq -0x18(%rbp), %rdi
addq $0x10, %rdi
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x3be0
jmp 0x584a
movq -0x18(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x5846
movq -0x18(%rbp), %rdi
addq $0x10, %rdi
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rax
movq 0x18(%rax), %rsi
callq 0x3be0
jmp 0x5848
jmp 0x5848
jmp 0x584a
movl $0x3, -0x1c(%rbp)
cmpl $0x3, -0x1c(%rbp)
jae 0x58f3
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
leaq -0xa0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4a80
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0xa0(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq 0x1a3d5(%rip), %rax     # 0x1fc80
movq %rax, -0xc8(%rbp)
movq 0x1a3cf(%rip), %rax     # 0x1fc88
movq %rax, -0xc0(%rbp)
movq -0xc8(%rbp), %rsi
movq -0xc0(%rbp), %rdx
leaq -0xb8(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0x17c30
movl -0x1c(%rbp), %eax
cmpl -0xc(%rbp), %eax
setne %al
andb $0x1, %al
addq $0xf0, %rsp
popq %rbp
retq
nopw (%rax,%rax)