// File: /workspace/github_c_makefile_star2_O2/masyagin1998[P]GCI/src/interpreter.c
// Function: main
int main(int argc, char**argv)
{
    int r = 0;
    
    struct INTERPRETER_PARAMS params;
    lexer_type_t  lexer;
    parser_type_t parser;
    bytecode_generator_type_t bc_gen;
    virtual_machine_type_t vm;

    struct UNIT_AST*unit;
    bytecode_type_t bc;

    parse_args(argc, argv, &params);

    lexer = create_lexer();
    lexer_conf_from_file(lexer, params.in);

    if (params.mode == INTERPRETER_LEX) {
        print_lexer_result(params.out, lexer);
        lexer_free(lexer);
        return 0;
    }

    parser = create_parser();
    parser_conf(parser, lexer);
    r = parser_parse(parser, &unit);
    if (r != PARSER_OK) {
        struct PARSER_ERROR err = parser_get_error(parser);
        print_parser_error(&err);
        lexer_free(lexer);
        parser_free(parser);
        return 1;
    }

    if (params.mode == INTERPRETER_PARSE) {
        print_parser_result(params.out, unit);
        lexer_free(lexer);
        parser_free(parser);
        unit_ast_free(unit);
        return 0;
    }

    lexer_free(lexer);
    parser_free(parser);

    bc_gen = create_bytecode_generator();
    bytecode_generator_conf(bc_gen, unit);
    
    r = bytecode_generator_generate(bc_gen, &bc);
    if (r != BYTECODE_GENERATOR_OK) {
        struct BYTECODE_ERROR err = bytecode_generator_get_error(bc_gen);
        print_bytecode_error(&err);
        unit_ast_free(unit);
        bytecode_generator_free(bc_gen);
        return 2;
    }

    unit_ast_free(unit);

    if (params.mode == INTERPRETER_BC) {
        print_bytecode_result(params.out, bc);
        bytecode_generator_free(bc_gen);
        bytecode_free(bc);
        return 0;
    }
    
    bytecode_generator_free(bc_gen);

    vm = create_virtual_machine();
    virtual_machine_conf(vm, bc, params.stacksize, params.heapsize, params.mode == INTERPRETER_TRACE);
    r = virtual_machine_run(vm);
    bytecode_free(bc);
    virtual_machine_free(vm);

    printf("result: %d\n", r);

    return 0;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x880, %rsp            # imm = 0x880
leaq 0x68(%rsp), %r15
movq %r15, %rdx
callq 0x129c
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x1aa8
movq %rax, %r14
movq %rax, %rdi
movq %r15, %rsi
callq 0x1aed
cmpl $0x0, 0x800(%r15)
je 0x1894
xorl %eax, %eax
callq 0x2bc0
movq %rax, %rbx
movq %rax, %rdi
movq %r14, %rsi
callq 0x2c01
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x2c05
testl %eax, %eax
je 0x18ae
leaq 0x10(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x2ff8
movq %r15, %rdi
callq 0x31de
movq %r14, %rdi
callq 0x23d1
movq %rbx, %rdi
callq 0x2ff3
pushq $0x1
popq %rbx
jmp 0x18e4
leaq 0x468(%rsp), %rdi
movq %r14, %rsi
callq 0x1779
movq %r14, %rdi
callq 0x23d1
jmp 0x18e4
cmpl $0x1, 0x868(%rsp)
jne 0x18f3
leaq 0x468(%rsp), %rdi
movq (%rsp), %rsi
callq 0x17a9
movq %r14, %rdi
callq 0x23d1
movq %rbx, %rdi
callq 0x2ff3
movq (%rsp), %rdi
callq 0x56a2
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x880, %rsp            # imm = 0x880
popq %rbx
popq %r14
popq %r15
retq
movq %r14, %rdi
callq 0x23d1
movq %rbx, %rdi
callq 0x2ff3
xorl %eax, %eax
callq 0x8602
movq %rax, %rbx
movq (%rsp), %rsi
movq %rax, %rdi
callq 0x8643
leaq 0x8(%rsp), %rsi
movq %rbx, %rdi
callq 0x8658
testl %eax, %eax
je 0x195a
leaq 0x10(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x96d2
movq %r14, %rdi
callq 0x96ed
movq (%rsp), %rdi
callq 0x56a2
movq %rbx, %rdi
callq 0x92f9
pushq $0x2
jmp 0x1891
movq (%rsp), %rdi
callq 0x56a2
cmpl $0x2, 0x868(%rsp)
jne 0x1996
leaq 0x468(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x17d9
movq %rbx, %rdi
callq 0x92f9
movq 0x8(%rsp), %rdi
callq 0x92d7
jmp 0x18e2
movq %rbx, %rdi
callq 0x92f9
xorl %ebx, %ebx
xorl %eax, %eax
callq 0xbb70
movq %rax, %r14
movq 0x8(%rsp), %rsi
movq 0x870(%rsp), %rdx
movq 0x878(%rsp), %rcx
xorl %r8d, %r8d
cmpl $0x4, 0x868(%rsp)
sete %r8b
movq %rax, %rdi
callq 0xbbb1
movq %r14, %rdi
callq 0xbd34
movq %rax, %r15
movq 0x8(%rsp), %rdi
callq 0x92d7
movq %r14, %rdi
callq 0xc6c7
leaq 0xc698(%rip), %rdi      # 0xe092
movl %r15d, %esi
xorl %eax, %eax
callq 0x10a0
jmp 0x18e4
nopl (%rax)