// File: /workspace/github_c_makefile_star2_O0/alexj136[P]minijit/src/main.c
// Function: main
int main(int argc, char *argv[]) {

    /* =========================================================================
     * Check that an argument file was supplied. Quit if not.
     */
    if(argc < 2) {
        puts("No arguments provided.");
        exit(EXIT_FAILURE);
    }

    /* =========================================================================
     * We now know a file argument was supplied - try to open it, and quit if it
     * fails.
     */
	FILE *file = fopen(argv[1], "r");

	if (!file) {
        printf("Could not open file: '%s'.\n", argv[1]);
        exit(EXIT_FAILURE);
	}

    /* =========================================================================
     * We now know that the file opened successfully, so perform lexical
     * analysis on its contents.
     */
    LexerResult *lr = lex_file(file);

    /* =========================================================================
     * Close the file now that lexical analysis has concluded. Print a warning
     * if closing fails, but continue with the pipeline anyway.
     */
    int close_status = fclose(file);
    if(close_status != 0) {
        printf("Warning: file '%s' did not close properly.\n", argv[1]);
    }

    /* =========================================================================
     * Do the parse. We don't need to check if the lexer failed because the
     * parser can deal with token lists that contain errors, and return any
     * lexical errors along with parse errors.
     *     If parsing fails, print the errors and exit.
     */
    ParseResult *pr = parse(lr);

    if(pr->type == parseFail) {
        ParseErrorVector_print(pr->errors);
        ParseResult_free(pr);
        exit(EXIT_FAILURE);
    }

    /* =========================================================================
     * We got the correct number of arguments, so now parse the command-line
     * arguments. If parsing fails, quit with an appropriate error message.
     */
    IntRefVector *prog_args = IntRefVector_init();
    int argv_idx      = 2;
    bool no_errors    = true;
    while((argv_idx < argc) && no_errors) {

        IntRef *arg_result = str_to_int(argv[argv_idx]);

        if(arg_result == NULL) {
            no_errors = false;
        }
        else {
            IntRefVector_append(prog_args, arg_result);
        }

        argv_idx++;
    }

    if(!no_errors) {
        IntRefVector_free_elems(prog_args);
        ParseResult_free(pr);
        printf("Could not parse command line arguments.\n");
        exit(EXIT_FAILURE);
    }

    /* =========================================================================
     * We now have everything we need to run the program, so run the program and
     * print the result.
     */
    InterpretResult *res = interpret_Prog(pr->prog, prog_args);
    if(res->type == iFailIncorrectNumArgs) {
        puts("Runtime Error: Function call with incorrect number of "
                "arguments.");
    }
    else if(res->type == iFailFunctionNotFound) {
        puts("Runtime Error: Call to an undefined function.");
    }
    else if(res->type == iFailEndWithoutReturn) {
        puts("Runtime Error: Reached end of function without return.");
    }
    else if(res->type == iSuccess) {
        printf("INTERPRETER RESULT = %d\n", res->result);
    }
    else {
        free(res);
        ParseResult_free(pr);
        IntRefVector_free_elems(prog_args);
        ERROR("InterpretResult type not recognised");
    }
    free(res);

    /* =========================================================================
     * Generate and run icode and vmcode for the given program, with the given
     * args.
     */
    int next_label = 0;
    ICodeOperationVector *icodevec = icodegen_Prog(pr->prog, &next_label);
    int icode_result = ICodeOperationVector_execute(icodevec, prog_args);
    printf("ICODE RESULT = %d\n", icode_result);
    int vmcode_result = VMCode_execute(icodevec, prog_args);
    printf("VMCODE RESULT = %d\n", vmcode_result);
    ICodeOperationVector_free_elems(icodevec);

    /* =========================================================================
     * Deallocate the remaining heap objects.
     */
    ParseResult_free(pr);
    IntRefVector_free_elems(prog_args);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1fc0, %rsp           # imm = 0x1FC0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x2, -0x8(%rbp)
jge 0x23595
leaq 0x294f(%rip), %rdi      # 0x25ed5
callq 0x6060
movl $0x1, %edi
callq 0x61a0
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0x24cc(%rip), %rsi      # 0x25a70
callq 0x6180
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x235d4
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x2929(%rip), %rdi      # 0x25eec
movb $0x0, %al
callq 0x60f0
movl $0x1, %edi
callq 0x61a0
movq -0x18(%rbp), %rdi
callq 0x12240
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x60b0
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x23609
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x2906(%rip), %rdi      # 0x25f08
movb $0x0, %al
callq 0x60f0
movq -0x20(%rbp), %rdi
callq 0x14f30
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x2363f
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x13910
movq -0x30(%rbp), %rdi
callq 0x13a40
movl $0x1, %edi
callq 0x61a0
movb $0x0, %al
callq 0x7dd0
movq %rax, -0x38(%rbp)
movl $0x2, -0x3c(%rbp)
movl $0x1, -0x40(%rbp)
movl -0x3c(%rbp), %ecx
xorl %eax, %eax
cmpl -0x8(%rbp), %ecx
movb %al, -0x1fb9(%rbp)
jge 0x23675
cmpl $0x0, -0x40(%rbp)
setne %al
movb %al, -0x1fb9(%rbp)
movb -0x1fb9(%rbp), %al
testb $0x1, %al
jne 0x23681
jmp 0x236be
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x66f0
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
jne 0x236a6
movl $0x0, -0x40(%rbp)
jmp 0x236b3
movq -0x38(%rbp), %rdi
movq -0x48(%rbp), %rsi
callq 0x7f20
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x23658
cmpl $0x0, -0x40(%rbp)
jne 0x236ee
movq -0x38(%rbp), %rdi
callq 0x88c0
movq -0x30(%rbp), %rdi
callq 0x13a40
leaq 0x2857(%rip), %rdi      # 0x25f34
movb $0x0, %al
callq 0x60f0
movl $0x1, %edi
callq 0x61a0
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x38(%rbp), %rsi
callq 0x19450
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x2371d
leaq 0x284a(%rip), %rdi      # 0x25f5d
callq 0x6060
jmp 0x2385c
movq -0x50(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x23737
leaq 0x2871(%rip), %rdi      # 0x25f9e
callq 0x6060
jmp 0x2385a
movq -0x50(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x23751
leaq 0x2885(%rip), %rdi      # 0x25fcc
callq 0x6060
jmp 0x23858
movq -0x50(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x23774
movq -0x50(%rbp), %rax
movl 0x4(%rax), %esi
leaq 0x289b(%rip), %rdi      # 0x26003
movb $0x0, %al
callq 0x60f0
jmp 0x23856
movq -0x50(%rbp), %rdi
callq 0x6030
movq -0x30(%rbp), %rdi
callq 0x13a40
movq -0x38(%rbp), %rdi
callq 0x88c0
leaq 0x86e(%rip), %rdi       # 0x24004
leaq 0x287f(%rip), %rsi      # 0x2601c
movl $0x76, %edx
leaq 0x241c(%rip), %rcx      # 0x25bc5
movb $0x0, %al
callq 0x60f0
leaq 0x875(%rip), %rdi       # 0x2402c
leaq 0x2869(%rip), %rsi      # 0x26027
movb $0x0, %al
callq 0x60f0
leaq -0x1f90(%rbp), %rdi
movl $0x3e8, %esi            # imm = 0x3E8
callq 0x60d0
movl %eax, -0x1f94(%rbp)
leaq -0x1f90(%rbp), %rdi
movl -0x1f94(%rbp), %esi
callq 0x60a0
movq %rax, -0x1fa0(%rbp)
leaq 0x84f(%rip), %rdi       # 0x2404b
movb $0x0, %al
callq 0x60f0
movl $0x0, -0x1fa4(%rbp)
movl -0x1fa4(%rbp), %eax
cmpl -0x1f94(%rbp), %eax
jge 0x2384c
movq -0x1fa0(%rbp), %rax
movslq -0x1fa4(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x7f8(%rip), %rdi       # 0x2402c
movb $0x0, %al
callq 0x60f0
movl -0x1fa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1fa4(%rbp)
jmp 0x2380d
movl $0x1, %edi
callq 0x61a0
jmp 0x23858
jmp 0x2385a
jmp 0x2385c
movq -0x50(%rbp), %rdi
callq 0x6030
movl $0x0, -0x1fa8(%rbp)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
leaq -0x1fa8(%rbp), %rsi
callq 0x1bac0
movq %rax, -0x1fb0(%rbp)
movq -0x1fb0(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x1ca00
movl %eax, -0x1fb4(%rbp)
movl -0x1fb4(%rbp), %esi
leaq 0x279e(%rip), %rdi      # 0x2604b
movb $0x0, %al
callq 0x60f0
movq -0x1fb0(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x1d7c0
movl %eax, -0x1fb8(%rbp)
movl -0x1fb8(%rbp), %esi
leaq 0x2787(%rip), %rdi      # 0x2605e
movb $0x0, %al
callq 0x60f0
movq -0x1fb0(%rbp), %rdi
callq 0x1afe0
movq -0x30(%rbp), %rdi
callq 0x13a40
movq -0x38(%rbp), %rdi
callq 0x88c0
xorl %eax, %eax
addq $0x1fc0, %rsp           # imm = 0x1FC0
popq %rbp
retq