// File: /workspace/github_c_makefile_star2_O1/naleksiev[P]fin/src/fin_mod.c
// Function: fin_mod_resolve_type
static fin_str_t* fin_mod_resolve_type(fin_ctx_t* ctx, fin_mod_compiler_t* cmp, fin_ast_expr_t* expr) {
    switch (expr->type) {
        case fin_ast_expr_type_init:
        case fin_ast_expr_type_assign:
            return NULL;
        case fin_ast_expr_type_bool:
            return fin_str_create(ctx, "bool", -1);
        case fin_ast_expr_type_int:
            return fin_str_create(ctx, "int", -1);
        case fin_ast_expr_type_float:
            return fin_str_create(ctx, "float", -1);
        case fin_ast_expr_type_str:
        case fin_ast_expr_type_str_interp:
            return fin_str_create(ctx, "string", -1);
        case fin_ast_expr_type_id: {
            fin_ast_id_expr_t* id_expr = (fin_ast_id_expr_t*)expr;
            if (id_expr->primary) {
                fin_str_t* type_name = fin_mod_resolve_type(ctx, cmp, id_expr->primary);
                fin_mod_type_t* type = fin_mod_find_type(ctx, cmp->mod, type_name);
                fin_str_destroy(ctx, type_name);
                for (int32_t i=0; i<type->fields_count; i++) {
                    if (type->fields[i].name == id_expr->name)
                        return fin_str_clone(type->fields[i].type);
                }
                printf("Unresolved field %s\n", fin_str_cstr(id_expr->name));
                assert(0);
            }
            else {
                fin_mod_local_t* local = fin_mod_resolve_local(cmp, id_expr->name);
                assert(local);
                return fin_str_clone(local->type);
            }
        }
        case fin_ast_expr_type_unary: {
            fin_ast_unary_expr_t* unary_expr = (fin_ast_unary_expr_t*)expr;
            fin_str_t* sign = fin_mod_unary_get_signature(ctx, cmp, unary_expr);
            fin_mod_func_t* func = fin_mod_find_func(ctx, cmp->mod, sign);
            fin_str_destroy(ctx, sign);
            return fin_str_clone(func->ret_type);
        }
        case fin_ast_expr_type_binary: {
            fin_ast_binary_expr_t* bin_expr = (fin_ast_binary_expr_t*)expr;
            fin_str_t* sign = fin_mod_binary_get_signature(ctx, cmp, bin_expr);
            fin_mod_func_t* func = fin_mod_find_func(ctx, cmp->mod, sign);
            fin_str_destroy(ctx, sign);
            return fin_str_clone(func->ret_type);
        }
        case fin_ast_expr_type_cond: {
            fin_ast_cond_expr_t* cond_expr = (fin_ast_cond_expr_t*)expr;
            fin_str_t* true_type = fin_mod_resolve_type(ctx, cmp, cond_expr->true_expr);
            fin_str_t* false_type = fin_mod_resolve_type(ctx, cmp, cond_expr->false_expr);
            assert(true_type == false_type);
            fin_str_destroy(ctx, false_type);
            return true_type;
        }
        case fin_ast_expr_type_arg: {
            fin_ast_arg_expr_t* arg_expr = (fin_ast_arg_expr_t*)expr;
            return fin_mod_resolve_type(ctx, cmp, arg_expr->expr);
        }
        case fin_ast_expr_type_invoke: {
            fin_ast_invoke_expr_t* invoke_expr = (fin_ast_invoke_expr_t*)expr;
            fin_str_t* sign = fin_mod_invoke_get_signature(ctx, cmp, invoke_expr);
            fin_mod_func_t* func = fin_mod_find_func(ctx, cmp->mod, sign);
            fin_str_destroy(ctx, sign);
            return fin_str_clone(func->ret_type);
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rdx, %rbx
movq %rsi, %r15
movq %rdi, %r14
movl (%rbx), %eax
cmpl $0x9, %eax
jne 0x74e6
movq 0x8(%rbx), %rbx
jmp 0x74d9
cmpl $0xa, %eax
ja 0x765f
movl %eax, %eax
leaq 0x2e9c(%rip), %rcx      # 0xa394
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x3059(%rip), %rsi      # 0xa561
jmp 0x760c
movq %r14, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x785e
jmp 0x762f
leaq 0x309e(%rip), %rsi      # 0xa5c5
jmp 0x760c
movq 0x8(%rbx), %rdx
testq %rdx, %rdx
je 0x7664
movq %r14, %rdi
movq %r15, %rsi
callq 0x74c5
movq %rax, %r12
movq (%r15), %rsi
movq %r14, %rdi
movq %rax, %rdx
callq 0x7e00
movq %rax, %r15
movq %r14, %rdi
movq %r12, %rsi
callq 0x82ed
movslq 0x10(%r15), %rax
testq %rax, %rax
setg %r14b
jle 0x76c6
movq 0x8(%r15), %rcx
movq 0x10(%rbx), %rdx
cmpq %rdx, (%rcx)
je 0x76b1
movl $0x1, %esi
cmpq %rsi, %rax
je 0x76c2
leaq 0x10(%rcx), %rdi
incq %rsi
cmpq %rdx, 0x10(%rcx)
movq %rdi, %rcx
jne 0x758a
decq %rsi
cmpq %rax, %rsi
setb %r14b
jmp 0x76b4
leaq 0x3011(%rip), %rsi      # 0xa5ca
jmp 0x760c
movq %r14, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x7ccb
jmp 0x762f
movq 0x10(%rbx), %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x74c5
movq %rax, %r12
movq 0x18(%rbx), %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x74c5
cmpq %rax, %r12
jne 0x76d7
movq %r14, %rdi
movq %rax, %rsi
callq 0x82ed
jmp 0x76cb
leaq 0x2fc2(%rip), %rsi      # 0xa5ce
movq %r14, %rdi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x80e4
movq %r14, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x79bd
movq %rax, %rbx
movq (%r15), %rsi
movq %r14, %rdi
movq %rax, %rdx
callq 0x6306
movq %rax, %r15
movq %r14, %rdi
movq %rbx, %rsi
callq 0x82ed
movq 0x8(%r15), %rdi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x8322
xorl %r12d, %r12d
jmp 0x76cb
movzbl 0x1a30(%r15), %eax
testq %rax, %rax
je 0x768a
movq 0x10(%rbx), %rcx
addq $0x130, %r15            # imm = 0x130
cmpq %rcx, (%r15)
je 0x768d
addq $0x18, %r15
decq %rax
jne 0x767c
xorl %r15d, %r15d
testq %r15, %r15
jne 0x764e
leaq 0x2e73(%rip), %rdi      # 0xa50c
leaq 0x2db2(%rip), %rsi      # 0xa452
leaq 0x2f42(%rip), %rcx      # 0xa5e9
movl $0x121, %edx            # imm = 0x121
callq 0x3120
movq %rcx, %rdi
movq 0x8(%rdi), %rdi
callq 0x8322
movq %rax, %r12
jmp 0x76c6
seta %r14b
testb %r14b, %r14b
je 0x76f6
movq %r12, %rax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2f60(%rip), %rdi      # 0xa63e
leaq 0x2d6d(%rip), %rsi      # 0xa452
leaq 0x2efd(%rip), %rcx      # 0xa5e9
movl $0x137, %edx            # imm = 0x137
callq 0x3120
movq 0x10(%rbx), %rdi
callq 0x8477
leaq 0x2ece(%rip), %rdi      # 0xa5d4
movq %rax, %rsi
xorl %eax, %eax
callq 0x3110
leaq 0x29aa(%rip), %rdi      # 0xa0c1
leaq 0x2d34(%rip), %rsi      # 0xa452
leaq 0x2ec4(%rip), %rcx      # 0xa5e9
movl $0x11d, %edx            # imm = 0x11D
callq 0x3120