// File: /workspace/github_c_makefile_star2_O3/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, %r15
movq %rsi, %r14
movq %rdi, %rbx
movl (%r15), %eax
cmpl $0x9, %eax
jne 0x756e
movq 0x8(%r15), %r15
jmp 0x7560
cmpl $0xa, %eax
ja 0x76f8
movl %eax, %eax
leaq 0x2e14(%rip), %rcx      # 0xa394
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x2fd1(%rip), %rsi      # 0xa561
jmp 0x76a5
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x782a
jmp 0x76c8
leaq 0x3016(%rip), %rsi      # 0xa5c5
jmp 0x76a5
movq 0x8(%r15), %rdx
testq %rdx, %rdx
je 0x770e
movq %rbx, %rdi
movq %r14, %rsi
callq 0x754c
movq %rax, %r12
movq (%r14), %rsi
movq %rbx, %rdi
movq %rax, %rdx
callq 0x7dcc
movq %rax, %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0x8217
movslq 0x10(%r14), %rax
testq %rax, %rax
jle 0x7783
movq 0x8(%r14), %rcx
movq 0x10(%r15), %rdi
shlq $0x4, %rax
xorl %edx, %edx
cmpq %rdi, (%rcx,%rdx)
je 0x7707
addq $0x10, %rdx
cmpq %rdx, %rax
jne 0x7606
callq 0x83b1
leaq 0x2faf(%rip), %rdi      # 0xa5d4
movq %rax, %rsi
xorl %eax, %eax
callq 0x3110
leaq 0x2a8b(%rip), %rdi      # 0xa0c1
leaq 0x2e15(%rip), %rsi      # 0xa452
leaq 0x2fa5(%rip), %rcx      # 0xa5e9
movl $0x11d, %edx            # imm = 0x11D
callq 0x3120
leaq 0x2f75(%rip), %rsi      # 0xa5ca
jmp 0x76a5
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x7c97
jmp 0x76c8
movq 0x10(%r15), %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x754c
movq %rax, %r12
movq 0x18(%r15), %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x754c
cmpq %rax, %r12
jne 0x7764
movq %rbx, %rdi
movq %rax, %rsi
callq 0x8217
jmp 0x76fb
leaq 0x2f29(%rip), %rsi      # 0xa5ce
movq %rbx, %rdi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x8040
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x7989
movq %rax, %r15
movq (%r14), %rsi
movq %rbx, %rdi
movq %rax, %rdx
callq 0x6314
movq %rax, %r14
movq %rbx, %rdi
movq %r15, %rsi
callq 0x8217
movq 0x8(%r14), %rdi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x824c
xorl %r12d, %r12d
movq %r12, %rax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rcx,%rdx), %rdi
jmp 0x76eb
movzbl 0x1a30(%r14), %ecx
testq %rcx, %rcx
je 0x773b
movq 0x10(%r15), %rax
shll $0x3, %ecx
leaq (%rcx,%rcx,2), %rdx
xorl %ecx, %ecx
cmpq %rax, 0x130(%r14,%rcx)
je 0x775a
addq $0x18, %rcx
cmpq %rcx, %rdx
jne 0x7728
leaq 0x2dca(%rip), %rdi      # 0xa50c
leaq 0x2d09(%rip), %rsi      # 0xa452
leaq 0x2e99(%rip), %rcx      # 0xa5e9
movl $0x121, %edx            # imm = 0x121
callq 0x3120
movq 0x138(%r14,%rcx), %rdi
jmp 0x76eb
leaq 0x2ed3(%rip), %rdi      # 0xa63e
leaq 0x2ce0(%rip), %rsi      # 0xa452
leaq 0x2e70(%rip), %rcx      # 0xa5e9
movl $0x137, %edx            # imm = 0x137
callq 0x3120
movq 0x10(%r15), %rdi
jmp 0x7619