// File: /workspace/github_c_makefile_star2_O1/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, %r15
movq %rsi, %r14
movq %rdi, %rbx
movl (%r14), %edi
cmpl $0x4, %edi
jne 0x47b5
movq 0x8(%r14), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4a0e
movq 0x10(%r14), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4770
movq 0x18(%r14), %r14
testq %r14, %r14
jne 0x4781
jmp 0x4894
cmpl $0x5, %edi
ja 0x49a6
movl %edi, %eax
leaq 0x2ff9(%rip), %rcx      # 0x77c0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x3171(%rip), %rdi      # 0x7948
callq 0x1070
movl $0x28, %edi
callq 0x1150
movq %rax, %r12
movq %r15, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
leaq -0x194(%rip), %rsi      # 0x4666
movl $0x8, %edi
callq 0x61c5
movq %rax, 0x20(%r12)
movl $0x0, 0x18(%r12)
movq 0x8(%r14), %r14
movq %r14, %rdi
callq 0x322b
testq %rax, %rax
je 0x4993
xorl %r15d, %r15d
movq %r14, %rdi
movq %r15, %rsi
callq 0x3216
movq (%rax), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x4770
incq %r15
movq %r14, %rdi
callq 0x322b
cmpq %rax, %r15
jb 0x482a
jmp 0x4993
leaq 0x2ef0(%rip), %rdi      # 0x774f
callq 0x1070
cmpl $0x19, 0x8(%r14)
jne 0x49ab
movq 0x10(%r14), %rsi
jmp 0x487e
movq 0x8(%r14), %rsi
testq %rsi, %rsi
je 0x4894
movq %rbx, %rdi
movq %r15, %rdx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4a0e
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x2e96(%rip), %rdi      # 0x773d
callq 0x1070
movq 0x6725(%rip), %rax      # 0xafd8
movq (%rax), %rdi
movq 0x10(%r14), %rsi
callq 0x326c
movq 0x10(%r14), %rdi
cmpl $0xc, (%rdi)
jne 0x49ca
callq 0x383a
testq %rax, %rax
je 0x49e9
movq %rax, %rdi
movq %r15, %rsi
callq 0x4614
movq %rax, %r12
movl $0x1, 0x18(%rax)
movq 0x18(%r14), %rsi
movq %rbx, %rdi
movq %rax, %rdx
callq 0x4770
movq %r15, %rdi
movq %r12, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4692
leaq 0x2e5c(%rip), %rdi      # 0x7777
callq 0x1070
movl $0x28, %edi
callq 0x1150
movq %rax, %r12
movq %r15, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
leaq -0x2d8(%rip), %rsi      # 0x4666
movl $0x8, %edi
callq 0x61c5
movq %rax, 0x20(%r12)
movl $0x2, 0x18(%r12)
movq 0x8(%r14), %r14
movq %r14, %rdi
callq 0x322b
testq %rax, %rax
je 0x4993
xorl %r15d, %r15d
movq %r14, %rdi
movq %r15, %rsi
callq 0x3216
movq (%rax), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x4770
incq %r15
movq %r14, %rdi
callq 0x322b
cmpq %rax, %r15
jb 0x496a
movq %r12, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x466e
callq 0x1305
leaq 0x2e7c(%rip), %rdi      # 0x782e
leaq 0x2e43(%rip), %rsi      # 0x77fc
leaq 0x2ea3(%rip), %rcx      # 0x7863
movl $0xba, %edx
callq 0x10d0
leaq 0x2e5f(%rip), %rdi      # 0x7830
leaq 0x2e24(%rip), %rsi      # 0x77fc
leaq 0x2e84(%rip), %rcx      # 0x7863
movl $0x7c, %edx
callq 0x10d0
leaq 0x2c08(%rip), %rdi      # 0x75f8
leaq 0x2e05(%rip), %rsi      # 0x77fc
leaq 0x2e65(%rip), %rcx      # 0x7863
movl $0x7e, %edx
callq 0x10d0