// File: /workspace/github_c_makefile_star2_O2/yutopp[P]cc/analyzer.c
// Function: analyze
void analyze(Analyzer* a, Node* node, Env* env) {
    switch(node->kind) {
    case NODE_TRANS_UNIT:
    {
        printf("LOG: translation unit\n");
        Env* t_env = env_new(NULL, env); // TODO: Set a name of the translation unit
        t_env->kind = ENV_KIND_TRANS;

        Vector* decls = node->value.trans_unit.decls;
        for(size_t i=0; i<vector_len(decls); ++i) {
            Node** n = (Node**)vector_at(decls, i);
            analyze(a, *n, t_env);
        }

        env_drop(t_env);
        break;
    }

    case NODE_FUNC_DEF:
    {
        printf("LOG: function def\n");

        node_fprint(stdout, node->value.func_def.decl);
        assert(node->value.func_def.decl->kind == NODE_DECLARATOR);
        Token* id_tok = node_declarator_extract_id_token(node->value.func_def.decl);
        assert(id_tok); // TODO: error handling

        // TODO: Lookup a decl

        Env* f_env = env_new(id_tok, env);
        f_env->kind = ENV_KIND_FUNC;

        // fprint_impl(fp, node->value.func_def.decl_spec, 0);
        // fprint_impl(fp, node->value.func_def.decl, 0);
        analyze(a, node->value.func_def.block, f_env);

        env_insert(env, f_env);

        break;
    }

    case NODE_STMT_COMPOUND:
    {
        printf("LOG: statement compound\n");

        Env* b_env = env_new(NULL, env);
        b_env->kind = ENV_KIND_BLOCK;

        Vector* stmts = node->value.stmt_compound.stmts;
        for(size_t i=0; i<vector_len(stmts); ++i) {
            Node** n = (Node**)vector_at(stmts, i);
            analyze(a, *n, b_env);
        }

        env_drop(b_env);
        break;
    }

    case NODE_STMT_EXPR:
        if (node->value.stmt_expr.expr) {
            analyze_expr(a, node->value.stmt_expr.expr, env);
        }
        break;

    case NODE_STMT_IF:
        // TODO: Dig a scope
        analyze_expr(a, node->value.stmt_if.cond, env);

        analyze(a, node->value.stmt_if.then_b, env);

        if (node->value.stmt_if.else_b) {
            analyze(a, node->value.stmt_if.else_b, env);
        }
        break;

    case NODE_STMT_JUMP:
        printf("LOG: statement jump\n");

        switch(node->value.stmt_jump.kind) {
        case TOK_KIND_RETURN:
            analyze_expr(a, node->value.stmt_jump.expr, env);
            break;

        default:
            // TODO: error handling...
            assert(0);
            break;
        }
        break;

    default:
        // TODO: error handling...
        fprintf(stderr, "Unknown kind: %d\n", node->kind);
        assert(0);
        break;
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
leaq 0x296e(%rip), %r12      # 0x67d0
movl (%r15), %edx
cmpq $0x5, %rdx
ja 0x4012
movslq (%r12,%rdx,4), %rax
addq %r12, %rax
jmpq *%rax
movq 0x8(%r15), %rsi
movq %rbx, %rdi
movq %r14, %rdx
callq 0x40a2
movq 0x10(%r15), %rsi
movq %rbx, %rdi
movq %r14, %rdx
callq 0x3e4a
movq 0x18(%r15), %r15
testq %r15, %r15
jne 0x3e62
jmp 0x3f65
leaq 0x28dc(%rip), %rdi      # 0x6787
callq 0x1070
xorl %r12d, %r12d
xorl %edi, %edi
movq %r14, %rsi
callq 0x3d04
movq %rax, %r14
movl $0x2, 0x18(%rax)
movq 0x8(%r15), %r15
movq %r15, %rdi
callq 0x29db
cmpq %rax, %r12
jae 0x3f45
movq %r15, %rdi
movq %r12, %rsi
callq 0x29c6
movq (%rax), %rsi
movq %rbx, %rdi
movq %r14, %rdx
callq 0x3e4a
incq %r12
jmp 0x3ecb
leaq 0x2a5b(%rip), %rdi      # 0x6958
callq 0x1070
xorl %r12d, %r12d
xorl %edi, %edi
movq %r14, %rsi
callq 0x3d04
movq %rax, %r14
andl $0x0, 0x18(%rax)
movq 0x8(%r15), %r15
movq %r15, %rdi
callq 0x29db
cmpq %rax, %r12
jae 0x3f45
movq %r15, %rdi
movq %r12, %rsi
callq 0x29c6
movq (%rax), %rsi
movq %rbx, %rdi
movq %r14, %rdx
callq 0x3e4a
incq %r12
jmp 0x3f1a
movq %r14, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x3d5a
movq 0x8(%r15), %rsi
testq %rsi, %rsi
jne 0x3ffc
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x27d5(%rip), %rdi      # 0x674d
callq 0x1070
movq 0x7054(%rip), %rax      # 0xafd8
movq (%rax), %rdi
movq 0x10(%r15), %rsi
callq 0x2a15
movq 0x10(%r15), %rdi
cmpl $0xc, (%rdi)
jne 0x4049
callq 0x2ede
testq %rax, %rax
je 0x4081
movq %rax, %rdi
movq %r14, %rsi
callq 0x3d04
movq %rax, %r12
movl $0x1, 0x18(%rax)
movq 0x18(%r15), %rsi
movq %rbx, %rdi
movq %rax, %rdx
callq 0x3e4a
movq %r14, %rdi
movq %r12, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x3d79
leaq 0x2773(%rip), %rdi      # 0x675f
callq 0x1070
cmpl $0x19, 0x8(%r15)
jne 0x4062
movq 0x10(%r15), %rsi
movq %rbx, %rdi
movq %r14, %rdx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x40a2
movq 0x6fdf(%rip), %rax      # 0xaff8
movq (%rax), %rdi
leaq 0x244b(%rip), %rsi      # 0x646e
xorl %eax, %eax
callq 0x1120
leaq 0x280d(%rip), %rdi      # 0x683e
leaq 0x27d4(%rip), %rsi      # 0x680c
leaq 0x2834(%rip), %rcx      # 0x6873
movl $0xc2, %edx
callq 0x10d0
leaq 0x27f0(%rip), %rdi      # 0x6840
leaq 0x27b5(%rip), %rsi      # 0x680c
leaq 0x2815(%rip), %rcx      # 0x6873
pushq $0x7c
jmp 0x4098
leaq 0x27d5(%rip), %rdi      # 0x683e
leaq 0x279c(%rip), %rsi      # 0x680c
leaq 0x27fc(%rip), %rcx      # 0x6873
movl $0xba, %edx
callq 0x10d0
leaq 0x2580(%rip), %rdi      # 0x6608
leaq 0x277d(%rip), %rsi      # 0x680c
leaq 0x27dd(%rip), %rcx      # 0x6873
pushq $0x7e
popq %rdx
callq 0x10d0