// File: baziotis[P]minijava-cpp/ast.cpp
// Function: expr_print(Expression*)
void expr_print(Expression *e) {
    LOG_SCOPE;
    if (!e) return;
    switch (e->kind) {
    case EXPR::PLUS:
    case EXPR::MINUS:
    case EXPR::TIMES:
    case EXPR::CMP:
    case EXPR::AND:
    case EXPR::ARR_LOOK:
    {
        BinaryExpression *be = (BinaryExpression*) e;
        debug_print("(");
        printf("%s\n", expr_name(be->kind));
        expr_print(be->e1);
        expr_print(be->e2);
        debug_line(")");
    } break;
    case EXPR::THIS:
    {
        debug_line("(ThisExpression)");
    } break;
    case EXPR::INT_LIT:
    case EXPR::BOOL_LIT:
    {
        debug_print("(");
        printf("%s %d)\n", expr_name(e->kind), e->lit_val);
    } break;
    case EXPR::MSG_SEND:
    {
        BinaryExpression *be = (BinaryExpression*) e;
        debug_print("(MessageSend\n");
        expr_print(be->e1);
        // For some reason, debug_line does not work here
        debug_print("- Id: %s\n", be->msd->id);
        debug_print("- Expression list:\n");
        for (Expression* e2 : be->msd->expr_list) {
            expr_print(e2);
        }
        debug_print(")\n");
    } break;
    case EXPR::ID:
    {
        debug_print("(");
        printf("%s %s)\n", expr_name(e->kind), e->id);
    } break;
    case EXPR::UNDEFINED:
    {
        debug_print("(");
        printf("Undefined ");
        red_on();
        printf("(Error)");
        red_off();
        printf(")\n");
    } break;
    case EXPR::ARR_LEN:
    case EXPR::ARR_ALLOC:
    case EXPR::NOT:
    {
        debug_print("(%s\n", expr_name(e->kind));
        expr_print(e->e1);
        debug_line(")");
    } break;
    default: printf("Expression print error: %s\n", expr_name(e->kind)); assert(0);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
leaq -0x9(%rbp), %rdi
callq 0x3da0
cmpq $0x0, -0x8(%rbp)
jne 0x2798
movl $0x1, -0x10(%rbp)
jmp 0x2a7b
movq -0x8(%rbp), %rax
movl 0x4(%rax), %eax
movq %rax, -0x58(%rbp)
subq $0xe, %rax
ja 0x2a36
movq -0x58(%rbp), %rax
leaq 0x168cc(%rip), %rcx     # 0x19084
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rax
movq %rax, -0x18(%rbp)
leaq 0x190f2(%rip), %rdi     # 0x1b8c2
xorl %eax, %eax
callq 0x3e60
jmp 0x27d9
movq -0x18(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x2670
movq %rax, %rsi
leaq 0x1a8fb(%rip), %rdi     # 0x1d0ea
xorl %eax, %eax
callq 0x2030
jmp 0x27f8
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x2770
jmp 0x2807
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x2770
jmp 0x2816
leaq 0x1945f(%rip), %rdi     # 0x1bc7c
xorl %eax, %eax
callq 0x3f10
jmp 0x2826
jmp 0x2a74
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x9(%rbp), %rdi
callq 0x3dd0
jmp 0x2a8a
leaq 0x16a07(%rip), %rdi     # 0x19253
xorl %eax, %eax
callq 0x3f10
jmp 0x2855
jmp 0x2a74
leaq 0x19061(%rip), %rdi     # 0x1b8c2
xorl %eax, %eax
callq 0x3e60
jmp 0x286a
movq -0x8(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x2670
movq %rax, %rsi
movq -0x8(%rbp), %rax
movl 0x10(%rax), %edx
leaq 0x169dd(%rip), %rdi     # 0x19264
xorl %eax, %eax
callq 0x2030
jmp 0x2890
jmp 0x2a74
movq -0x8(%rbp), %rax
movq %rax, -0x30(%rbp)
leaq 0x169c8(%rip), %rdi     # 0x1926c
xorl %eax, %eax
callq 0x3e60
jmp 0x28ad
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x2770
jmp 0x28bc
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rsi
leaq 0x169ac(%rip), %rdi     # 0x1927a
xorl %eax, %eax
callq 0x3e60
jmp 0x28d7
leaq 0x169a6(%rip), %rdi     # 0x19284
xorl %eax, %eax
callq 0x3e60
jmp 0x28e7
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rax
addq $0x8, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x39b0
movq %rax, -0x60(%rbp)
jmp 0x2906
movq -0x60(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
callq 0x39d0
movq %rax, -0x68(%rbp)
jmp 0x291d
movq -0x68(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rax
cmpq -0x48(%rbp), %rax
je 0x2955
movq -0x40(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
callq 0x2770
jmp 0x2945
jmp 0x2947
movq -0x40(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x40(%rbp)
jmp 0x2925
leaq 0x19ada(%rip), %rdi     # 0x1c436
xorl %eax, %eax
callq 0x3e60
jmp 0x2965
jmp 0x2a74
leaq 0x18f51(%rip), %rdi     # 0x1b8c2
xorl %eax, %eax
callq 0x3e60
jmp 0x297a
movq -0x8(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x2670
movq %rax, %rsi
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdx
leaq 0x16900(%rip), %rdi     # 0x19298
xorl %eax, %eax
callq 0x2030
jmp 0x29a1
jmp 0x2a74
leaq 0x18f15(%rip), %rdi     # 0x1b8c2
xorl %eax, %eax
callq 0x3e60
jmp 0x29b6
leaq 0x168e3(%rip), %rdi     # 0x192a0
xorl %eax, %eax
callq 0x2030
jmp 0x29c6
callq 0x2aa0
jmp 0x29cd
leaq 0x169f4(%rip), %rdi     # 0x193c8
xorl %eax, %eax
callq 0x2030
jmp 0x29dd
callq 0x2ac0
jmp 0x29e4
leaq 0x19a4b(%rip), %rdi     # 0x1c436
xorl %eax, %eax
callq 0x2030
jmp 0x29f4
jmp 0x2a74
movq -0x8(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x2670
movq %rax, %rsi
leaq 0x1689f(%rip), %rdi     # 0x192ab
xorl %eax, %eax
callq 0x3e60
jmp 0x2a15
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x2770
jmp 0x2a24
leaq 0x19251(%rip), %rdi     # 0x1bc7c
xorl %eax, %eax
callq 0x3f10
jmp 0x2a34
jmp 0x2a74
movq -0x8(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x2670
movq %rax, %rsi
leaq 0x16864(%rip), %rdi     # 0x192b0
xorl %eax, %eax
callq 0x2030
jmp 0x2a55
leaq 0x18f26(%rip), %rdi     # 0x1b982
leaq 0x16869(%rip), %rsi     # 0x192cc
movl $0x64, %edx
leaq 0x16865(%rip), %rcx     # 0x192d4
callq 0x20d0
movl $0x0, -0x10(%rbp)
leaq -0x9(%rbp), %rdi
callq 0x3dd0
addq $0x70, %rsp
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x21c0
nopw %cs:(%rax,%rax)