// File: SunriseFox[P]very-simple-c-compiler/./src/main.cpp
// Function: showTree(TreeNode*)
void showTree(TreeNode* root) {

    if (root == nullptr) return;

    auto children = root -> child;
    while (children) {
        showTree(children);
        children = children -> sibling;
    }
    Symbol* ownSymbol = nullptr;

    cout << "(Line " << root -> lineno << ") " << root->nodeID << ": ";
    switch (root->nodeType) {
    case TreeNode::NODE_NONE:
        cout << "[Unknown] ";
        break;
    case TreeNode::NODE_STATMENT:
        cout << "[Statement ";
        switch (static_cast<StatementNode*>(root)->type) {
        case StatementNode::ST_NONE:
            cout << "Unknown";
            break;
        case StatementNode::ST_EMPTY:
            cout << "Empty";
            break;
        case StatementNode::ST_SCOPE:
            cout << "Scope";
            break;
        case StatementNode::ST_RET:
            cout << "Return";
            break;
        case StatementNode::ST_DO_WHILE:
            cout << "Do-While";
            break;
        case StatementNode::ST_WHILE:
            cout << "While";
            break;
        case StatementNode::ST_FOR:
            cout << "For";
            break;
        case StatementNode::ST_FUNCTION:
            cout << "Function<";
            cout << static_cast<FuncStatementNode*>(root)->symbol->value << ">";
            break;
        case StatementNode::ST_IF:
            cout << "If";
            break;
        case StatementNode::ST_IF_ELSE:
            cout << "If-Else";
            break;
        case StatementNode::ST_BREAK:
            cout << "Break";
            break;
        case StatementNode::ST_CONTINUE:
            cout << "Continue";
            break;
        case StatementNode::ST_GOTO:
            cout << "Goto";
            break;
        }
        cout << "]";
        break;

    case TreeNode::NODE_FUNCCALL:
        cout << "[FuncCall<";
        ownSymbol = static_cast<DeclarationNode*>(root)->symbol;
        cout << Symbol::getSymbolName(ownSymbol);
        cout << "> " <<static_cast<DeclarationNode*>(root)->symbol->value << "] ";
        break;

    case TreeNode::NODE_DECLARATION:
        cout << "[Declaration<";
        // fall through
        [[clang::fallthrough]];
    case TreeNode::NODE_EXPRESSION:
        if(root->nodeType == TreeNode::NODE_EXPRESSION)
            cout << "[Expression<";

        ownSymbol = static_cast<DeclarationNode*>(root)->symbol;

        cout << Symbol::getSymbolName(ownSymbol);

        cout << "> " <<static_cast<DeclarationNode*>(root)->symbol->value << "] ";
        break;

    case TreeNode::NODE_OPERATOR:
        ownSymbol = root->symbol = new OpNode(root->child->symbol->type, "");
        cout << "[Operator ";
        cout << OperatorNode::getTypeStr(static_cast<OperatorNode*>(root)->type);
        cout << " <";
        cout << Symbol::getSymbolName(ownSymbol);
        cout << ">]";
        switch (static_cast<OperatorNode*>(root)->type) {
        case OperatorNode::OP_ASSIGN:
        case OperatorNode::OP_ADDAS:
        case OperatorNode::OP_SUBAS:
        case OperatorNode::OP_MULAS:
        case OperatorNode::OP_DIVAS:
        case OperatorNode::OP_BORAS:
        case OperatorNode::OP_BANDAS:
        case OperatorNode::OP_BXORAS:
        case OperatorNode::OP_LSHFTAS:
        case OperatorNode::OP_RSHFTAS:
        default: break;
        }
        break;
    }
    children = root -> child;
    if(children) {
        cout << endl << "\tChildren: ";
    }
    while (children) {
        cout << children->nodeID << " ";
        children = children -> sibling;
    }
    cout << endl;
    children = root -> child;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x140, %rsp            # imm = 0x140
movq %rdi, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
jne 0xbe2b
jmp 0xc4bc
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0xbe55
movq -0x10(%rbp), %rdi
callq 0xbe10
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0xbe37
movq $0x0, -0x18(%rbp)
movq 0x1515c(%rip), %rdi     # 0x20fc0
leaq 0xb80d(%rip), %rsi      # 0x17678
callq 0x3240
movq %rax, %rdi
movq -0x8(%rbp), %rax
movl 0xc(%rax), %esi
callq 0x3460
movq %rax, %rdi
leaq 0xb7f6(%rip), %rsi      # 0x1767f
callq 0x3240
movq %rax, %rdi
movq -0x8(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x3460
movq %rax, %rdi
leaq 0xb89c(%rip), %rsi      # 0x17743
callq 0x3240
movq -0x8(%rbp), %rax
movl 0x10(%rax), %eax
movq %rax, -0xd8(%rbp)
subq $0x5, %rax
ja 0xc42f
movq -0xd8(%rbp), %rax
leaq 0xb75a(%rip), %rcx      # 0x1762c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x150de(%rip), %rdi     # 0x20fc0
leaq 0xb799(%rip), %rsi      # 0x17682
callq 0x3240
jmp 0xc42f
movq 0x150c6(%rip), %rdi     # 0x20fc0
leaq 0xb78c(%rip), %rsi      # 0x1768d
callq 0x3240
movq -0x8(%rbp), %rax
movl 0x30(%rax), %eax
movq %rax, -0xe0(%rbp)
subq $0xc, %rax
ja 0xc080
movq -0xe0(%rbp), %rax
leaq 0xb718(%rip), %rcx      # 0x17644
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x15084(%rip), %rdi     # 0x20fc0
leaq 0xb756(%rip), %rsi      # 0x17699
callq 0x3240
jmp 0xc080
movq 0x1506c(%rip), %rdi     # 0x20fc0
leaq 0xb746(%rip), %rsi      # 0x176a1
callq 0x3240
jmp 0xc080
movq 0x15054(%rip), %rdi     # 0x20fc0
leaq 0xb734(%rip), %rsi      # 0x176a7
callq 0x3240
jmp 0xc080
movq 0x1503c(%rip), %rdi     # 0x20fc0
leaq 0xb722(%rip), %rsi      # 0x176ad
callq 0x3240
jmp 0xc080
movq 0x15024(%rip), %rdi     # 0x20fc0
leaq 0xb711(%rip), %rsi      # 0x176b4
callq 0x3240
jmp 0xc080
movq 0x1500c(%rip), %rdi     # 0x20fc0
leaq 0xb6fc(%rip), %rsi      # 0x176b7
callq 0x3240
jmp 0xc080
movq 0x14ff4(%rip), %rdi     # 0x20fc0
leaq 0xb6ea(%rip), %rsi      # 0x176bd
callq 0x3240
jmp 0xc080
movq 0x14fdc(%rip), %rdi     # 0x20fc0
leaq 0xb6d6(%rip), %rsi      # 0x176c1
callq 0x3240
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rsi
addq $0x8, %rsi
movq 0x14fbd(%rip), %rdi     # 0x20fc0
callq 0x3230
movq %rax, %rdi
leaq 0xd5a7(%rip), %rsi      # 0x195b9
callq 0x3240
jmp 0xc080
movq 0x14fa0(%rip), %rdi     # 0x20fc0
leaq 0xb6a4(%rip), %rsi      # 0x176cb
callq 0x3240
jmp 0xc080
movq 0x14f8b(%rip), %rdi     # 0x20fc0
leaq 0xb692(%rip), %rsi      # 0x176ce
callq 0x3240
jmp 0xc080
movq 0x14f76(%rip), %rdi     # 0x20fc0
leaq 0xb685(%rip), %rsi      # 0x176d6
callq 0x3240
jmp 0xc080
movq 0x14f61(%rip), %rdi     # 0x20fc0
leaq 0xb676(%rip), %rsi      # 0x176dc
callq 0x3240
jmp 0xc080
movq 0x14f4c(%rip), %rdi     # 0x20fc0
leaq 0xb66a(%rip), %rsi      # 0x176e5
callq 0x3240
movq 0x14f39(%rip), %rdi     # 0x20fc0
leaq 0xb694(%rip), %rsi      # 0x17722
callq 0x3240
jmp 0xc42f
movq 0x14f21(%rip), %rdi     # 0x20fc0
movq %rdi, -0xf0(%rbp)
leaq 0xb63d(%rip), %rsi      # 0x176ea
callq 0x3240
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rsi
leaq -0x38(%rbp), %rdi
movq %rdi, -0xe8(%rbp)
callq 0x151b0
movq -0xf0(%rbp), %rdi
movq -0xe8(%rbp), %rsi
callq 0x3230
jmp 0xc0e7
leaq -0x38(%rbp), %rdi
callq 0x3180
movq 0x14ec9(%rip), %rdi     # 0x20fc0
leaq 0xb5f7(%rip), %rsi      # 0x176f5
callq 0x3240
movq %rax, %rdi
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rsi
addq $0x8, %rsi
callq 0x3230
movq %rax, %rdi
leaq 0xb569(%rip), %rsi      # 0x1768a
callq 0x3240
jmp 0xc42f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x3180
jmp 0xc4c5
movq 0x14e74(%rip), %rdi     # 0x20fc0
leaq 0xb5a5(%rip), %rsi      # 0x176f8
callq 0x3240
movq -0x8(%rbp), %rax
cmpl $0x3, 0x10(%rax)
jne 0xc175
movq 0x14e57(%rip), %rdi     # 0x20fc0
leaq 0xb596(%rip), %rsi      # 0x17706
callq 0x3240
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rsi
leaq -0x68(%rbp), %rdi
movq %rdi, -0xf8(%rbp)
callq 0x151b0
movq -0xf8(%rbp), %rsi
movq 0x14e1d(%rip), %rdi     # 0x20fc0
callq 0x3230
jmp 0xc1aa
leaq -0x68(%rbp), %rdi
callq 0x3180
movq 0x14e06(%rip), %rdi     # 0x20fc0
leaq 0xb534(%rip), %rsi      # 0x176f5
callq 0x3240
movq %rax, %rdi
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rsi
addq $0x8, %rsi
callq 0x3230
movq %rax, %rdi
leaq 0xb4a6(%rip), %rsi      # 0x1768a
callq 0x3240
jmp 0xc42f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x3180
jmp 0xc4c5
movl $0x30, %edi
callq 0x3250
movq %rax, -0x110(%rbp)
movb $0x1, -0x8a(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x28(%rax), %rax
movl (%rax), %eax
movl %eax, -0x104(%rbp)
leaq -0x89(%rbp), %rdi
movq %rdi, -0x100(%rbp)
callq 0x3490
movq -0x100(%rbp), %rdx
leaq 0xb125(%rip), %rsi      # 0x1737a
leaq -0x88(%rbp), %rdi
callq 0x8910
jmp 0xc263
movl -0x104(%rbp), %esi
movq -0x110(%rbp), %rdi
leaq -0x88(%rbp), %rdx
callq 0x15630
jmp 0xc27e
movq -0x110(%rbp), %rax
movb $0x0, -0x8a(%rbp)
movq -0x8(%rbp), %rcx
movq %rax, 0x28(%rcx)
movq %rax, -0x18(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x3180
leaq -0x89(%rbp), %rdi
callq 0x32c0
movq 0x14d09(%rip), %rdi     # 0x20fc0
movq %rdi, -0x120(%rbp)
leaq 0xb44e(%rip), %rsi      # 0x17713
callq 0x3240
movq -0x8(%rbp), %rax
movl 0x30(%rax), %esi
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x118(%rbp)
callq 0x15bc0
movq -0x120(%rbp), %rdi
movq -0x118(%rbp), %rsi
callq 0x3230
jmp 0xc2f9
leaq -0xb0(%rbp), %rdi
callq 0x3180
movq 0x14cb4(%rip), %rdi     # 0x20fc0
movq %rdi, -0x130(%rbp)
leaq 0xb404(%rip), %rsi      # 0x1771e
callq 0x3240
movq -0x18(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0x151b0
movq -0x130(%rbp), %rdi
movq -0x128(%rbp), %rsi
callq 0x3230
jmp 0xc34b
leaq -0xd0(%rbp), %rdi
callq 0x3180
movq 0x14c62(%rip), %rdi     # 0x20fc0
leaq 0xb3bc(%rip), %rsi      # 0x17721
callq 0x3240
movq -0x8(%rbp), %rax
movl 0x30(%rax), %eax
movl %eax, -0x134(%rbp)
addl $-0x19, %eax
subl $0x4, %eax
jb 0xc429
jmp 0xc385
movl -0x134(%rbp), %eax
addl $-0x1e, %eax
subl $0x6, %eax
jb 0xc429
jmp 0xc42b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xc3c2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x3180
leaq -0x89(%rbp), %rdi
callq 0x32c0
testb $0x1, -0x8a(%rbp)
jne 0xc3d9
jmp 0xc3ea
movq -0x110(%rbp), %rdi
movl $0x30, %esi
callq 0x3260
jmp 0xc4c5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x3180
jmp 0xc4c5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0x3180
jmp 0xc4c5
jmp 0xc42b
jmp 0xc42d
jmp 0xc42f
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0xc464
movq 0x14b77(%rip), %rdi     # 0x20fc0
movq 0x14b58(%rip), %rsi     # 0x20fa8
callq 0x3290
movq %rax, %rdi
leaq 0xb2c5(%rip), %rsi      # 0x17724
callq 0x3240
jmp 0xc466
cmpq $0x0, -0x10(%rbp)
je 0xc49d
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq 0x14b45(%rip), %rdi     # 0x20fc0
callq 0x3460
movq %rax, %rdi
leaq 0xb1f6(%rip), %rsi      # 0x17680
callq 0x3240
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0xc466
movq 0x14b1c(%rip), %rdi     # 0x20fc0
movq 0x14afd(%rip), %rsi     # 0x20fa8
callq 0x3290
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x10(%rbp)
addq $0x140, %rsp            # imm = 0x140
popq %rbp
retq
movq -0x40(%rbp), %rdi
callq 0x3480
nop