// File: /workspace/github_c_makefile_star2_O3/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 0x4482
movq 0x8(%r14), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x46db
movq 0x10(%r14), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x443d
movq 0x18(%r14), %r14
testq %r14, %r14
jne 0x444e
jmp 0x4561
cmpl $0x5, %edi
ja 0x4673
movl %edi, %eax
leaq 0x333c(%rip), %rcx      # 0x77d0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x34b4(%rip), %rdi      # 0x7958
callq 0x1070
movl $0x28, %edi
callq 0x1160
movq %rax, %r12
movq %r15, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
leaq -0x191(%rip), %rsi      # 0x4336
movl $0x8, %edi
callq 0x5ebe
movq %rax, 0x20(%r12)
movl $0x0, 0x18(%r12)
movq 0x8(%r14), %r14
movq %r14, %rdi
callq 0x2f0b
testq %rax, %rax
je 0x4660
xorl %r15d, %r15d
movq %r14, %rdi
movq %r15, %rsi
callq 0x2ef6
movq (%rax), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x443d
incq %r15
movq %r14, %rdi
callq 0x2f0b
cmpq %rax, %r15
jb 0x44f7
jmp 0x4660
leaq 0x3233(%rip), %rdi      # 0x775f
callq 0x1070
cmpl $0x19, 0x8(%r14)
jne 0x4678
movq 0x10(%r14), %rsi
jmp 0x454b
movq 0x8(%r14), %rsi
testq %rsi, %rsi
je 0x4561
movq %rbx, %rdi
movq %r15, %rdx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x46db
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x31d9(%rip), %rdi      # 0x774d
callq 0x1070
movq 0x6a58(%rip), %rax      # 0xafd8
movq (%rax), %rdi
movq 0x10(%r14), %rsi
callq 0x2f4c
movq 0x10(%r14), %rdi
cmpl $0xc, (%rdi)
jne 0x4697
callq 0x3509
testq %rax, %rax
je 0x46b6
movq %rax, %rdi
movq %r15, %rsi
callq 0x42e4
movq %rax, %r12
movl $0x1, 0x18(%rax)
movq 0x18(%r14), %rsi
movq %rbx, %rdi
movq %rax, %rdx
callq 0x443d
movq %r15, %rdi
movq %r12, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4362
leaq 0x319f(%rip), %rdi      # 0x7787
callq 0x1070
movl $0x28, %edi
callq 0x1160
movq %rax, %r12
movq %r15, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
leaq -0x2d5(%rip), %rsi      # 0x4336
movl $0x8, %edi
callq 0x5ebe
movq %rax, 0x20(%r12)
movl $0x2, 0x18(%r12)
movq 0x8(%r14), %r14
movq %r14, %rdi
callq 0x2f0b
testq %rax, %rax
je 0x4660
xorl %r15d, %r15d
movq %r14, %rdi
movq %r15, %rsi
callq 0x2ef6
movq (%rax), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x443d
incq %r15
movq %r14, %rdi
callq 0x2f0b
cmpq %rax, %r15
jb 0x4637
movq %r12, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x433e
callq 0x1315
leaq 0x31bf(%rip), %rdi      # 0x783e
leaq 0x3186(%rip), %rsi      # 0x780c
leaq 0x31e6(%rip), %rcx      # 0x7873
movl $0xba, %edx
callq 0x10d0
leaq 0x31a2(%rip), %rdi      # 0x7840
leaq 0x3167(%rip), %rsi      # 0x780c
leaq 0x31c7(%rip), %rcx      # 0x7873
movl $0x7c, %edx
callq 0x10d0
leaq 0x2f4b(%rip), %rdi      # 0x7608
leaq 0x3148(%rip), %rsi      # 0x780c
leaq 0x31a8(%rip), %rcx      # 0x7873
movl $0x7e, %edx
callq 0x10d0