// File: kram[P]kram/src/main.cpp
// Function: main
int main(int argc, char** argv) {

	bool debug = false;
	std::string file = "";

	// Parse arguments
	// This probable needs to become way more advanced in the future, but it is enough for now...
	if (argc > 1) {
		for (int i = 1; i < argc; i++) {
			std::string arg(argv[i]);

			if (arg.substr(0, 2) == "--") {

				if (arg == "--debug") {
					debug = true;
				} else if (arg == "--help") {
					kr_print_help();
					exit(0);
				} else if (arg == "--version") {
					kr_print_version();
					exit(0);
				}

			} else {
				file = arg;
			}
		}
	} else {
		kr_print_help();
		exit(0);
	}

	// Define output stream
	kram_output_stream = new Output(std::cout);

	lexer::Lexer lexer;
	std::vector<lexer::Token*> tokens = lexer.parse_file(file);

	if (debug) {
		lexer::Lexer::print(tokens);
	}

	Parser parser (tokens);
	std::vector<Instruction*> instructions = parser.run();

	if (debug) {
		std::cout << "Printing ins:\n";

		for (Instruction* ins : instructions) {
			ins->print();
			std::cout << "--------\n";
		}
	}

	VM vm;
	vm.boot(instructions);

	return 0;
}

// Assembly:
subq $0xb48, %rsp            # imm = 0xB48
movl $0x0, 0xb44(%rsp)
movl %edi, 0xb40(%rsp)
movq %rsi, 0xb38(%rsp)
movb $0x0, 0xb37(%rsp)
leaq 0xb0f(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x34a0
movq 0x28(%rsp), %rdx
leaq 0x27e8b(%rip), %rsi     # 0x2b862
leaq 0xb10(%rsp), %rdi
callq 0x3390
jmp 0x39e6
leaq 0xb0f(%rsp), %rdi
callq 0x3310
cmpl $0x1, 0xb40(%rsp)
jle 0x3c3e
movl $0x1, 0xaf8(%rsp)
movl 0xaf8(%rsp), %eax
cmpl 0xb40(%rsp), %eax
jge 0x3c3c
movq 0xb38(%rsp), %rax
movslq 0xaf8(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x18(%rsp)
leaq 0xad7(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x34a0
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rdx
leaq 0xad8(%rsp), %rdi
callq 0x3390
jmp 0x3a64
leaq 0xad7(%rsp), %rdi
callq 0x3310
xorl %eax, %eax
movl %eax, %edx
leaq 0xab0(%rsp), %rdi
leaq 0xad8(%rsp), %rsi
movl $0x2, %ecx
callq 0x32f0
jmp 0x3a91
leaq 0x2765c(%rip), %rsi     # 0x2b0f4
leaq 0xab0(%rsp), %rdi
callq 0x4070
movb %al, 0x17(%rsp)
jmp 0x3aab
leaq 0xab0(%rsp), %rdi
callq 0x31f0
movb 0x17(%rsp), %al
testb $0x1, %al
jne 0x3ac5
jmp 0x3bee
leaq 0x2762b(%rip), %rsi     # 0x2b0f7
leaq 0xad8(%rsp), %rdi
callq 0x4070
movb %al, 0x16(%rsp)
jmp 0x3adf
movb 0x16(%rsp), %al
testb $0x1, %al
jne 0x3aec
jmp 0x3b84
movb $0x1, 0xb37(%rsp)
jmp 0x3bec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
leaq 0xb0f(%rsp), %rdi
callq 0x3310
jmp 0x4061
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
leaq 0xad7(%rsp), %rdi
callq 0x3310
jmp 0x4054
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
jmp 0x3c2a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
leaq 0xab0(%rsp), %rdi
callq 0x31f0
jmp 0x3c2a
leaq 0x27574(%rip), %rsi     # 0x2b0ff
leaq 0xad8(%rsp), %rdi
callq 0x4070
movb %al, 0x15(%rsp)
jmp 0x3b9e
movb 0x15(%rsp), %al
testb $0x1, %al
jne 0x3ba8
jmp 0x3bb6
callq 0x38a0
jmp 0x3baf
xorl %edi, %edi
callq 0x3330
leaq 0x27549(%rip), %rsi     # 0x2b106
leaq 0xad8(%rsp), %rdi
callq 0x4070
movb %al, 0x14(%rsp)
jmp 0x3bd0
movb 0x14(%rsp), %al
testb $0x1, %al
jne 0x3bda
jmp 0x3be8
callq 0x3910
jmp 0x3be1
xorl %edi, %edi
callq 0x3330
jmp 0x3bea
jmp 0x3bec
jmp 0x3c07
leaq 0xb10(%rsp), %rdi
leaq 0xad8(%rsp), %rsi
callq 0x3040
jmp 0x3c05
jmp 0x3c07
leaq 0xad8(%rsp), %rdi
callq 0x31f0
movl 0xaf8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xaf8(%rsp)
jmp 0x3a0c
leaq 0xad8(%rsp), %rdi
callq 0x31f0
jmp 0x4054
jmp 0x3c65
callq 0x38a0
jmp 0x3c45
xorl %edi, %edi
callq 0x3330
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
jmp 0x4054
movl $0x110, %edi            # imm = 0x110
callq 0x32e0
movq %rax, 0x8(%rsp)
jmp 0x3c76
movq 0x8(%rsp), %rdi
movq 0x36356(%rip), %rsi     # 0x39fd8
callq 0x40a0
jmp 0x3c89
movq 0x8(%rsp), %rax
movq %rax, 0x3661b(%rip)     # 0x3a2b0
leaq 0xa48(%rsp), %rdi
callq 0x75b0
jmp 0x3ca4
leaq 0xa10(%rsp), %rdi
leaq 0xb10(%rsp), %rsi
callq 0x3140
jmp 0x3cbb
leaq 0xa30(%rsp), %rdi
leaq 0xa48(%rsp), %rsi
leaq 0xa10(%rsp), %rdx
callq 0x7b70
jmp 0x3cda
leaq 0xa10(%rsp), %rdi
callq 0x31f0
testb $0x1, 0xb37(%rsp)
je 0x3dce
leaq 0x9f8(%rsp), %rdi
leaq 0xa30(%rsp), %rsi
callq 0x40e0
jmp 0x3d0c
leaq 0x9f8(%rsp), %rdi
callq 0x8e70
jmp 0x3d1b
leaq 0x9f8(%rsp), %rdi
callq 0x41e0
jmp 0x3dce
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
callq 0x32b0
jmp 0x4054
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
jmp 0x4047
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
leaq 0xa10(%rsp), %rdi
callq 0x31f0
jmp 0x4047
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
jmp 0x403a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
leaq 0x9f8(%rsp), %rdi
callq 0x41e0
jmp 0x403a
leaq 0x8d8(%rsp), %rdi
leaq 0xa30(%rsp), %rsi
callq 0x40e0
jmp 0x3de5
leaq 0x8f0(%rsp), %rdi
leaq 0x8d8(%rsp), %rsi
callq 0x201b0
jmp 0x3dfc
leaq 0x8d8(%rsp), %rdi
callq 0x41e0
leaq 0x8c0(%rsp), %rdi
leaq 0x8f0(%rsp), %rsi
callq 0x20920
jmp 0x3e20
testb $0x1, 0xb37(%rsp)
je 0x3f44
movq 0x361a3(%rip), %rdi     # 0x39fd8
leaq 0x272d4(%rip), %rsi     # 0x2b110
callq 0x32d0
jmp 0x3e43
leaq 0x8c0(%rsp), %rax
movq %rax, 0x8b8(%rsp)
movq 0x8b8(%rsp), %rdi
callq 0x4240
movq %rax, 0x8b0(%rsp)
movq 0x8b8(%rsp), %rdi
callq 0x4270
movq %rax, 0x8a8(%rsp)
leaq 0x8b0(%rsp), %rdi
leaq 0x8a8(%rsp), %rsi
callq 0x42a0
testb $0x1, %al
jne 0x3e9b
jmp 0x3f42
leaq 0x8b0(%rsp), %rdi
callq 0x42e0
movq (%rax), %rax
movq %rax, 0x8a0(%rsp)
movq 0x8a0(%rsp), %rdi
xorl %esi, %esi
callq 0x42f0
jmp 0x3ec4
movq 0x3610d(%rip), %rdi     # 0x39fd8
leaq 0x2724d(%rip), %rsi     # 0x2b11f
callq 0x32d0
jmp 0x3ed9
jmp 0x3edb
leaq 0x8b0(%rsp), %rdi
callq 0x5410
jmp 0x3e7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
leaq 0x8d8(%rsp), %rdi
callq 0x41e0
jmp 0x403a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
jmp 0x402d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
jmp 0x4020
jmp 0x3f44
leaq 0x48(%rsp), %rdi
callq 0x5430
leaq 0x30(%rsp), %rdi
leaq 0x8c0(%rsp), %rsi
callq 0x5460
jmp 0x3f62
leaq 0x48(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x12bc0
jmp 0x3f73
leaq 0x30(%rsp), %rdi
callq 0x5560
movl $0x0, 0xb44(%rsp)
leaq 0x48(%rsp), %rdi
callq 0x55c0
leaq 0x8c0(%rsp), %rdi
callq 0x5560
leaq 0x8f0(%rsp), %rdi
callq 0x55f0
leaq 0xa30(%rsp), %rdi
callq 0x41e0
leaq 0xa48(%rsp), %rdi
callq 0x5650
leaq 0xb10(%rsp), %rdi
callq 0x31f0
movl 0xb44(%rsp), %eax
addq $0xb48, %rsp            # imm = 0xB48
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
jmp 0x4016
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb00(%rsp)
movl %eax, 0xafc(%rsp)
leaq 0x30(%rsp), %rdi
callq 0x5560
leaq 0x48(%rsp), %rdi
callq 0x55c0
leaq 0x8c0(%rsp), %rdi
callq 0x5560
leaq 0x8f0(%rsp), %rdi
callq 0x55f0
leaq 0xa30(%rsp), %rdi
callq 0x41e0
leaq 0xa48(%rsp), %rdi
callq 0x5650
leaq 0xb10(%rsp), %rdi
callq 0x31f0
movq 0xb00(%rsp), %rdi
callq 0x3490
nop