// File: /workspace/github_cpp_makefile_star2_O1/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 $0x58, %rsp
movq %rdi, %r14
leaq 0x90(%rsp), %r15
xorl %ebx, %ebx
leaq 0x4543(%rip), %r12      # 0x12434
movl 0x8(%r14), %eax
cmpq $0x6, %rax
ja 0xe0d3
movslq (%r12,%rax,4), %rax
addq %r12, %rax
jmpq *%rax
movq 0x10(%r14), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdd81
movq 0x18(%r14), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdecf
movq 0x20(%r14), %r14
movups (%r15), %xmm0
movaps %xmm0, 0x20(%rsp)
movq 0x10(%r15), %rax
movq %rax, 0x30(%rsp)
movaps 0x20(%rsp), %xmm0
movups %xmm0, (%r15)
movq 0x30(%rsp), %rax
jmp 0xdfa0
movq 0x10(%r14), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdd81
movq 0x18(%r14), %r14
movups (%r15), %xmm0
movaps %xmm0, 0x40(%rsp)
movq 0x10(%r15), %rax
movq %rax, 0x50(%rsp)
movaps 0x40(%rsp), %xmm0
movups %xmm0, (%r15)
movq 0x50(%rsp), %rax
movq %rax, 0x10(%r15)
andb %bl, %bpl
movb $0x1, %bl
jmp 0xdef1
movq 0x18(%r14), %r12
testq %r12, %r12
je 0xe0d3
movq 0x20(%r14), %r14
shlq $0x3, %r12
xorl %r13d, %r13d
movq (%r14,%r13), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdecf
addq $0x8, %r13
cmpq %r13, %r12
jne 0xdfc6
jmp 0xe0d3
movq 0x18(%r14), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdd81
movq 0x8(%r15), %rdx
testq %rdx, %rdx
je 0xe0d3
movq 0x10(%r15), %rax
movq 0x10(%r14), %rsi
shlq $0x4, %rdx
xorl %ecx, %ecx
movq (%rax,%rcx), %rdi
cmpq (%rdi), %rsi
je 0xe0b9
addq $0x10, %rcx
cmpq %rcx, %rdx
jne 0xe023
jmp 0xe0d3
movq 0x10(%r14), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdd81
jmp 0xe0d3
movq 0x18(%r14), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdd81
movq 0x20(%r14), %rdi
movq 0x10(%r15), %rax
movq %rax, 0x10(%rsp)
movups (%r15), %xmm0
movups %xmm0, (%rsp)
callq 0xdd81
movq 0x8(%r15), %rdx
testq %rdx, %rdx
je 0xe0d3
movq 0x10(%r15), %rax
movq 0x10(%r14), %rsi
shlq $0x4, %rdx
xorl %ecx, %ecx
movq (%rax,%rcx), %rdi
cmpq (%rdi), %rsi
je 0xe0b9
addq $0x10, %rcx
cmpq %rcx, %rdx
jne 0xe0a5
jmp 0xe0d3
movb 0x8(%rax,%rcx), %dl
testb $0x3, %dl
jne 0xe0d3
testb $0xc, %dl
je 0xe0cc
orb $0x2, %dl
jmp 0xe0cf
orb $0x1, %dl
movb %dl, 0x8(%rax,%rcx)
andb %bpl, %bl
andb $0x1, %bl
movl %ebx, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x45c1(%rip), %rdi      # 0x126b2
leaq 0x4396(%rip), %rsi      # 0x1248e
leaq 0x5435(%rip), %rcx      # 0x13534
movl $0x796, %edx            # imm = 0x796
callq 0x20b0