// File: taurheim[P]AgNES/semanticAnalyzer.cpp
// Function: SemanticAnalyzer::parseNode(ASTNode*)
void SemanticAnalyzer::parseNode(ASTNode * node) {
    switch (node->nodeType) {
        case AST_DECLARATION:
        case AST_FUNCTION:
            {
                VarType varType;
                std::string functionName = "";
                for (auto i = node->children.begin(); i != node->children.end(); i++) {
                    ASTNode * childNode = *i;
                    // Is TypeNode
                    if (i == node->children.begin()) {
                        varType = ((TypeNode *)*i)->varType;
                    } else if(node->nodeType == AST_DECLARATION) {
                        // Is AST_VARDECLARATION 
                        IdentifierNode * idNode = (IdentifierNode *)(*i)->children[0];
                        std::string varName = idNode->name;
                        symbolTable->addVariable(varType, varName);
                    } else if (node->nodeType == AST_FUNCTION && i == node->children.begin() + 1) {
                        // Second child of AST_FUNCTION is an Identifier
                        IdentifierNode * idNode = (IdentifierNode *)(*i);
                        functionName = idNode->name;
                        symbolTable->addFunction(varType, functionName);
                    } else if (node->nodeType == AST_FUNCTION && childNode->nodeType == AST_PARAMETERLIST) {
                        // Open the scope for the body of the function
                        symbolTable->openScope(functionName);
                        parseNode(childNode);
                    } else {
                        parseNode(childNode);
                    }
                }
                break;
            }
        case AST_PARAMETERLIST:
            {
                for (auto i = node->children.begin(); i != node->children.end(); i++) {
                    ASTNode * childNode = *i; // Parameter
                    TypeNode * paramType = (TypeNode*) childNode->children[0];
                    IdentifierNode * paramIdentifier = (IdentifierNode*) childNode->children[1];

                    symbolTable->addParam(paramType->varType, paramIdentifier->name);
                }
                break;
            }
        case AST_FUNCTIONBODY:
            {
                for (auto & n : node->children) {
                    parseNode(n);
                }
                symbolTable->closeScope();
                break;
            }
        case AST_IDENTIFIER:
            {
                IdentifierNode * idNode= (IdentifierNode*) node;
                STEntry * entry = symbolTable->lookup(idNode->name);
                if(entry == nullptr) {
                    std::cout << "Identifier \"" << idNode->name << "\" is undefined." << std::endl;
                }
                break;
            }
        default:
            for (auto & n : node->children) {
                parseNode(n);
            }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x250, %rsp            # imm = 0x250
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x1e8(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
addl $-0x2, %eax
movl %eax, %ecx
movq %rcx, -0x1e0(%rbp)
subl $0xe, %eax
ja 0x18ac1
movq -0x1e0(%rbp), %rax
leaq 0xc255(%rip), %rcx      # 0x246bc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq -0x39(%rbp), %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x3530
movq -0x1f0(%rbp), %rdx
leaq 0xbe5e(%rip), %rsi      # 0x242ec
leaq -0x38(%rbp), %rdi
callq 0x33f0
jmp 0x18499
leaq -0x39(%rbp), %rdi
callq 0x3350
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x14e60
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x14ed0
movq %rax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x14e90
testb $0x1, %al
jne 0x184da
jmp 0x187eb
leaq -0x58(%rbp), %rdi
callq 0x14f70
movq (%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x14e60
movq %rax, -0x70(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x14f00
testb $0x1, %al
jne 0x1850e
jmp 0x1853f
leaq -0x58(%rbp), %rdi
callq 0x14f70
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, -0x14(%rbp)
jmp 0x187d2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x39(%rbp), %rdi
callq 0x3350
jmp 0x18b51
movq -0x10(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x18632
leaq -0x58(%rbp), %rdi
callq 0x14f70
movq (%rax), %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x19310
movq (%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rsi
addq $0x20, %rsi
leaq -0x98(%rbp), %rdi
callq 0x3140
jmp 0x18582
movq -0x1e8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x200(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0x1f4(%rbp)
leaq -0xb8(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x3140
jmp 0x185b2
movl -0x1f4(%rbp), %esi
movq -0x200(%rbp), %rdi
leaq -0xb8(%rbp), %rdx
callq 0x1b7d0
jmp 0x185cd
leaq -0xb8(%rbp), %rdi
callq 0x31d0
leaq -0x98(%rbp), %rdi
callq 0x31d0
jmp 0x187d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x187f9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x18621
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x31d0
leaq -0x98(%rbp), %rdi
callq 0x31d0
jmp 0x187f9
movq -0x10(%rbp), %rcx
xorl %eax, %eax
cmpl $0x2, (%rcx)
movb %al, -0x201(%rbp)
jne 0x18685
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x14e60
movq %rax, -0xc8(%rbp)
leaq -0xc8(%rbp), %rdi
movl $0x1, %esi
callq 0x19330
movq %rax, -0xc0(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x14f00
movb %al, -0x201(%rbp)
movb -0x201(%rbp), %al
testb $0x1, %al
jne 0x18694
jmp 0x18733
leaq -0x58(%rbp), %rdi
callq 0x14f70
movq (%rax), %rax
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rsi
addq $0x20, %rsi
leaq -0x38(%rbp), %rdi
callq 0x3040
jmp 0x186bd
movq -0x1e8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x210(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0x208(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x3140
jmp 0x186ea
movl -0x208(%rbp), %esi
movq -0x210(%rbp), %rdi
leaq -0xf0(%rbp), %rdx
callq 0x1b9b0
jmp 0x18705
leaq -0xf0(%rbp), %rdi
callq 0x31d0
jmp 0x187ce
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x31d0
jmp 0x187f9
movq -0x10(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x187b8
movq -0x68(%rbp), %rax
cmpl $0x7, (%rax)
jne 0x187b8
movq -0x1e8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x218(%rbp)
leaq -0x110(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x3140
jmp 0x18769
movq -0x218(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x1bab0
jmp 0x1877e
leaq -0x110(%rbp), %rdi
callq 0x31d0
movq -0x1e8(%rbp), %rdi
movq -0x68(%rbp), %rsi
callq 0x18420
jmp 0x1879c
jmp 0x187cc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x31d0
jmp 0x187f9
movq -0x1e8(%rbp), %rdi
movq -0x68(%rbp), %rsi
callq 0x18420
jmp 0x187ca
jmp 0x187cc
jmp 0x187ce
jmp 0x187d0
jmp 0x187d2
jmp 0x187d4
leaq -0x58(%rbp), %rdi
xorl %esi, %esi
callq 0x19370
movq %rax, -0x118(%rbp)
jmp 0x184b3
leaq -0x38(%rbp), %rdi
callq 0x31d0
jmp 0x18b48
leaq -0x38(%rbp), %rdi
callq 0x31d0
jmp 0x18b51
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x14e60
movq %rax, -0x120(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x14ed0
movq %rax, -0x128(%rbp)
leaq -0x120(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x14e90
testb $0x1, %al
jne 0x1884b
jmp 0x1893f
leaq -0x120(%rbp), %rdi
callq 0x14f70
movq (%rax), %rax
movq %rax, -0x130(%rbp)
movq -0x130(%rbp), %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x19310
movq (%rax), %rax
movq %rax, -0x138(%rbp)
movq -0x130(%rbp), %rdi
addq $0x8, %rdi
movl $0x1, %esi
callq 0x19310
movq %rax, %rcx
movq -0x1e8(%rbp), %rax
movq (%rcx), %rcx
movq %rcx, -0x140(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x230(%rbp)
movq -0x138(%rbp), %rax
movl 0x20(%rax), %eax
movl %eax, -0x224(%rbp)
movq -0x140(%rbp), %rsi
addq $0x20, %rsi
leaq -0x160(%rbp), %rdi
movq %rdi, -0x220(%rbp)
callq 0x3140
movq -0x230(%rbp), %rdi
movl -0x224(%rbp), %esi
movq -0x220(%rbp), %rdx
callq 0x1ba30
jmp 0x188fc
leaq -0x160(%rbp), %rdi
callq 0x31d0
leaq -0x120(%rbp), %rdi
xorl %esi, %esi
callq 0x19370
movq %rax, -0x168(%rbp)
jmp 0x1881b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x31d0
jmp 0x18b51
jmp 0x18b48
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x170(%rbp)
movq -0x170(%rbp), %rdi
callq 0x14e60
movq %rax, -0x178(%rbp)
movq -0x170(%rbp), %rdi
callq 0x14ed0
movq %rax, -0x180(%rbp)
leaq -0x178(%rbp), %rdi
leaq -0x180(%rbp), %rsi
callq 0x14e90
testb $0x1, %al
jne 0x18992
jmp 0x189c9
leaq -0x178(%rbp), %rdi
callq 0x14f70
movq -0x1e8(%rbp), %rdi
movq %rax, -0x188(%rbp)
movq -0x188(%rbp), %rax
movq (%rax), %rsi
callq 0x18420
leaq -0x178(%rbp), %rdi
callq 0x14f90
jmp 0x18979
movq -0x1e8(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x1bb70
jmp 0x18b48
movq -0x1e8(%rbp), %rax
movq -0x10(%rbp), %rcx
movq %rcx, -0x190(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x248(%rbp)
movq -0x190(%rbp), %rsi
addq $0x20, %rsi
leaq -0x1b8(%rbp), %rdi
movq %rdi, -0x240(%rbp)
callq 0x3140
movq -0x248(%rbp), %rdi
movq -0x240(%rbp), %rsi
callq 0x1bb90
movq %rax, -0x238(%rbp)
jmp 0x18a35
leaq -0x1b8(%rbp), %rdi
callq 0x31d0
movq -0x238(%rbp), %rax
movq %rax, -0x198(%rbp)
cmpq $0x0, -0x198(%rbp)
jne 0x18abc
movq 0x1c568(%rip), %rdi     # 0x34fc8
leaq 0xbca7(%rip), %rsi      # 0x2470e
callq 0x32e0
movq %rax, %rdi
movq -0x190(%rbp), %rsi
addq $0x20, %rsi
callq 0x32a0
movq %rax, %rdi
leaq 0xbc92(%rip), %rsi      # 0x2471b
callq 0x32e0
movq %rax, %rdi
movq 0x1c520(%rip), %rsi     # 0x34fb8
callq 0x3330
jmp 0x18abc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x1b8(%rbp), %rdi
callq 0x31d0
jmp 0x18b51
jmp 0x18b48
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x1c0(%rbp)
movq -0x1c0(%rbp), %rdi
callq 0x14e60
movq %rax, -0x1c8(%rbp)
movq -0x1c0(%rbp), %rdi
callq 0x14ed0
movq %rax, -0x1d0(%rbp)
leaq -0x1c8(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
callq 0x14e90
testb $0x1, %al
jne 0x18b0f
jmp 0x18b46
leaq -0x1c8(%rbp), %rdi
callq 0x14f70
movq -0x1e8(%rbp), %rdi
movq %rax, -0x1d8(%rbp)
movq -0x1d8(%rbp), %rax
movq (%rax), %rsi
callq 0x18420
leaq -0x1c8(%rbp), %rdi
callq 0x14f90
jmp 0x18af6
jmp 0x18b48
addq $0x250, %rsp            # imm = 0x250
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x3520
nopw (%rax,%rax)