// File: /workspace/github_c_makefile_star2_O2/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, %r14
movq %rsi, %r15
movq %rdi, %rbx
leaq 0x26b6(%rip), %rax      # 0x9394
movl (%r14), %ecx
cmpq $0xa, %rcx
ja 0x6d79
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x8(%r14), %r14
jmp 0x6cde
leaq 0x2860(%rip), %rsi      # 0x9561
jmp 0x6d66
movq 0x10(%r14), %rdx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x6cc3
movq %rax, %r12
movq 0x18(%r14), %rdx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x6cc3
cmpq %rax, %r12
jne 0x6e91
movq %rbx, %rdi
movq %rax, %rsi
callq 0x79ab
jmp 0x6d7c
leaq 0x288d(%rip), %rsi      # 0x95ce
jmp 0x6d66
movq %rbx, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x6fa7
jmp 0x6e11
leaq 0x2868(%rip), %rsi      # 0x95c5
jmp 0x6d66
leaq 0x2864(%rip), %rsi      # 0x95ca
pushq $-0x1
popq %rdx
movq %rbx, %rdi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x781e
xorl %r12d, %r12d
movq %r12, %rax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%r14), %rdx
testq %rdx, %rdx
je 0x6e41
movq %rbx, %rdi
movq %r15, %rsi
callq 0x6cc3
movq %rax, %r12
movq (%r15), %rsi
movq %rbx, %rdi
movq %rax, %rdx
callq 0x7541
movq %rax, %r15
movq %rbx, %rdi
movq %r12, %rsi
callq 0x79ab
movl 0x10(%r15), %eax
xorl %ecx, %ecx
testl %eax, %eax
cmovlel %ecx, %eax
shlq $0x4, %rax
addq $0x10, %rax
leaq 0x10(%rcx), %rdx
cmpq %rdx, %rax
je 0x6e58
movq 0x8(%r15), %rsi
movq (%rsi,%rcx), %rdi
movq %rdx, %rcx
cmpq 0x10(%r14), %rdi
jne 0x6dd2
movq -0x8(%rsi,%rdx), %rdi
jmp 0x6e34
movq %rbx, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x7410
jmp 0x6e11
movq %rbx, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x7104
movq %rax, %r14
movq (%r15), %rsi
movq %rbx, %rdi
movq %rax, %rdx
callq 0x5eae
movq %rax, %r15
movq %rbx, %rdi
movq %r14, %rsi
callq 0x79ab
movq 0x8(%r15), %rdi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x79dd
movq 0x10(%r14), %rsi
movq %r15, %rdi
callq 0x6c96
testq %rax, %rax
je 0x6eb0
movq 0x8(%rax), %rdi
jmp 0x6e34
movq 0x10(%r14), %rdi
callq 0x7b28
leaq 0x276c(%rip), %rdi      # 0x95d4
movq %rax, %rsi
xorl %eax, %eax
callq 0x3110
leaq 0x2248(%rip), %rdi      # 0x90c1
leaq 0x25d2(%rip), %rsi      # 0x9452
leaq 0x2762(%rip), %rcx      # 0x95e9
movl $0x11d, %edx            # imm = 0x11D
callq 0x3120
leaq 0x27a6(%rip), %rdi      # 0x963e
leaq 0x25b3(%rip), %rsi      # 0x9452
leaq 0x2743(%rip), %rcx      # 0x95e9
movl $0x137, %edx            # imm = 0x137
callq 0x3120
leaq 0x2655(%rip), %rdi      # 0x950c
leaq 0x2594(%rip), %rsi      # 0x9452
leaq 0x2724(%rip), %rcx      # 0x95e9
movl $0x121, %edx            # imm = 0x121
callq 0x3120