// File: /workspace/github_cpp_makefile_star2_O2/baziotis[P]minijava-cpp/typecheck.cpp
// Function: track_while_assignment_for_stmt(Statement*, Array<WhileAssign, (MEM)4>)
bool track_while_assignment_for_stmt(Statement *stmt, FuncArr<WhileAssign> track_buf) {
    // IMPORTANT: Be sure to first visit the usage, then
    // the assignment in assigments. For example, in
    // AssignmentStatement, we first want to visit the RHS,
    // then track the assignment because if we have say:
    // a = a + 1;
    // then, it counts as a usage before an assignment.
    switch (stmt->kind) {
    case STMT::UNDEFINED: assert(0);
    case STMT::BLOCK:
    {
        BlockStatement *block = (BlockStatement *)stmt;
        for (Statement *s : block->block) {
            track_while_assignment_for_stmt(s, track_buf);
        }
    } break;
    case STMT::ASGN:
    {
        AssignmentStatement *asgn = (AssignmentStatement *)stmt;
        track_while_assignment_for_expr(asgn->rhs, track_buf);
        for (WhileAssign& wa : track_buf) {
            Local *local = wa.local;
            if (asgn->id == local->id) {
                if (!wa.assigned) {
                    if (!wa.used) {
                        wa.assigned = 1;
                    } else {
                        wa.assigned = 2;
                    }
                }
                break;
            }
        }
    } break;
    case STMT::ARR_ASGN:
    {
        ArrayAssignmentStatement *arr_asgn = (ArrayAssignmentStatement *)stmt;
        track_while_assignment_for_expr(arr_asgn->index, track_buf);
        track_while_assignment_for_expr(arr_asgn->rhs, track_buf);

        for (WhileAssign& wa : track_buf) {
            Local *local = wa.local;
            if (arr_asgn->id == local->id) {
                if (!wa.assigned) {
                    if (!wa.used) {
                        wa.assigned = 1;
                    } else {
                        wa.assigned = 2;
                    }
                }
                break;
            }
        }
    } break;
    case STMT::IF:
    {
        IfStatement *if_stmt = (IfStatement *)stmt;
        track_while_assignment_for_expr(if_stmt->cond, track_buf);
        track_while_assignment_for_stmt(if_stmt->then, track_buf);
        track_while_assignment_for_stmt(if_stmt->else_, track_buf);
    } break;
    case STMT::WHILE:
    {
        WhileStatement *while_stmt = (WhileStatement *)stmt;
        track_while_assignment_for_expr(while_stmt->cond, track_buf);
        track_while_assignment_for_stmt(while_stmt->body, track_buf);
    } break;
    case STMT::PRINT:
    {
        PrintStatement *print_stmt = (PrintStatement *)stmt;
        track_while_assignment_for_expr(print_stmt->to_print, track_buf);
    } break;
    }
    return false;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdi, %rbx
leaq 0x80(%rsp), %r14
leaq 0x4756(%rip), %r15      # 0x1038c
pushq $0x20
popq %r13
leaq 0x30(%rsp), %rbp
pushq $0x18
popq %r12
movl 0x8(%rbx), %eax
cmpq $0x6, %rax
ja 0xbddb
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
movq 0x10(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbaec
movq 0x18(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbc16
movq %r13, %rcx
leaq 0x18(%rsp), %rax
jmp 0xbcb7
movq 0x10(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbaec
movq %r12, %rcx
movq %rbp, %rax
movq (%rbx,%rcx), %rbx
movq 0x10(%r14), %rcx
movq %rcx, 0x10(%rax)
movups (%r14), %xmm0
movups %xmm0, (%rax)
jmp 0xbc43
movq 0x18(%rbx), %r15
movq 0x20(%rbx), %rbx
shlq $0x3, %r15
xorl %r12d, %r12d
cmpq %r12, %r15
je 0xbddb
movq (%rbx,%r12), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbc16
addq $0x8, %r12
jmp 0xbcde
movq 0x18(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbaec
movq 0x8(%r14), %rdx
movq 0x10(%r14), %rax
shlq $0x4, %rdx
xorl %ecx, %ecx
cmpq %rcx, %rdx
je 0xbddb
movq (%rax,%rcx), %rsi
movq 0x10(%rbx), %rdi
cmpq (%rsi), %rdi
je 0xbdc1
addq $0x10, %rcx
jmp 0xbd2f
movq 0x10(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbaec
jmp 0xbddb
movq 0x18(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbaec
movq 0x20(%rbx), %rdi
movq 0x10(%r14), %rax
movq %rax, 0x10(%rsp)
movups (%r14), %xmm0
movups %xmm0, (%rsp)
callq 0xbaec
movq 0x8(%r14), %rdx
movq 0x10(%r14), %rax
shlq $0x4, %rdx
xorl %ecx, %ecx
cmpq %rcx, %rdx
je 0xbddb
movq (%rax,%rcx), %rsi
movq 0x10(%rbx), %rdi
cmpq (%rsi), %rdi
je 0xbdc1
addq $0x10, %rcx
jmp 0xbda9
movb 0x8(%rax,%rcx), %dl
testb $0x3, %dl
jne 0xbddb
testb $0xc, %dl
je 0xbdd4
orb $0x2, %dl
jmp 0xbdd7
orb $0x1, %dl
movb %dl, 0x8(%rax,%rcx)
xorl %eax, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x481f(%rip), %rdi      # 0x10612
leaq 0x45f4(%rip), %rsi      # 0x103ee
leaq 0x5694(%rip), %rcx      # 0x11495
movl $0x796, %edx            # imm = 0x796
callq 0x20b0