// File: pfnet-research[P]pml/src/main.cpp
// Function: main
int main(int argc, const char* argv[]) {
    std::srand((unsigned int)time(NULL));
#ifdef PML_TEST_BUILD
    test::run(argc, argv);
    return 0;
#endif

    using namespace ast;
    if (argc != 2) {
        std::cout << "[filename] required!" << std::endl;
        return -1;
    }

    std::ifstream input{argv[1]};
    if (input.fail()) {
        std::cout << "file open error : " << argv[1] << std::endl;
        return -1;
    }

    std::istreambuf_iterator<char> it{input}, last;
    std::string input_str{it, last};
    // TODO: be more elegant
    std::cout << "parsing .. " << std::flush;
    parser::parse(input_str).case_of(
        ok >> [](ptr<ast::expr_t> const& expr){
            std::cout << "passed!" << std::endl;
            std::cout << "type checking .. " << std::endl;
            auto const& simty_result = simty::simple_typing(*expr);
            if (simty_result.is_error()) {
                std::cout << "failed at simple typing : " << simty_result.error() << std::endl;
                return;
            }
            if (!typechecker::typecheck(*expr)) {
                std::cout << "failed" << std::endl;
                return;
            }
            std::cout << "passed!" << std::endl;
            std::cout << "=> " << evaluator::eval(expr) << std::endl;
        },
        error >> [&](parser::error_t err) {
            std::cout <<
                "fail error at " << err.pos << " : " <<
                err.message << std::endl;
            output_parse_error(input_str, err.pos);
        }
    );
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x330, %rsp            # imm = 0x330
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
xorl %eax, %eax
movl %eax, %edi
callq 0xa360
movl %eax, %edi
callq 0xa390
cmpl $0x2, -0x8(%rbp)
je 0x2f71d
movq 0xb78aa(%rip), %rdi     # 0xe6fa0
leaq 0x6cc26(%rip), %rsi     # 0x9c323
callq 0xa3b0
movq %rax, %rdi
movq 0xb784c(%rip), %rsi     # 0xe6f58
callq 0xa400
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2f959
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq -0x218(%rbp), %rdi
movl $0x8, %edx
callq 0xa690
movq -0x218(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x218(%rbp,%rax), %rdi
callq 0xa030
movb %al, -0x2f1(%rbp)
jmp 0x2f756
movb -0x2f1(%rbp), %al
testb $0x1, %al
jne 0x2f762
jmp 0x2f7dd
movq 0xb7837(%rip), %rdi     # 0xe6fa0
leaq 0x6cbc8(%rip), %rsi     # 0x9c338
callq 0xa3b0
movq %rax, -0x300(%rbp)
jmp 0x2f77e
movq -0x300(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0xa3b0
movq %rax, -0x308(%rbp)
jmp 0x2f79b
movq -0x308(%rbp), %rdi
movq 0xb77af(%rip), %rsi     # 0xe6f58
callq 0xa400
jmp 0x2f7b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x228(%rbp)
jmp 0x2f94d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0x2f9c3
leaq -0x238(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0x2fe80
leaq -0x248(%rbp), %rdi
callq 0x2fee0
movups -0x238(%rbp), %xmm0
movaps %xmm0, -0x280(%rbp)
movups -0x248(%rbp), %xmm0
movaps %xmm0, -0x290(%rbp)
leaq -0x291(%rbp), %rdi
movq %rdi, -0x310(%rbp)
callq 0xa660
movq -0x310(%rbp), %r9
movq -0x280(%rbp), %rsi
movl -0x278(%rbp), %edx
movq -0x290(%rbp), %rcx
movl -0x288(%rbp), %r8d
leaq -0x268(%rbp), %rdi
callq 0x2ff10
jmp 0x2f85b
leaq -0x291(%rbp), %rdi
callq 0xa420
movq 0xb7732(%rip), %rdi     # 0xe6fa0
leaq 0x6cad6(%rip), %rsi     # 0x9c34b
callq 0xa3b0
movq %rax, -0x318(%rbp)
jmp 0x2f883
movq -0x318(%rbp), %rdi
movq 0xb771f(%rip), %rsi     # 0xe6fb0
callq 0xa400
jmp 0x2f898
leaq -0x2d0(%rbp), %rdi
leaq -0x268(%rbp), %rsi
callq 0x3fba0
jmp 0x2f8ad
leaq 0x6cb18(%rip), %rdi     # 0x9c3cc
leaq -0x2d9(%rbp), %rsi
callq 0x2fa70
movq %rax, -0x320(%rbp)
jmp 0x2f8c9
movq -0x320(%rbp), %rax
movq %rax, -0x2d8(%rbp)
leaq -0x268(%rbp), %rax
movq %rax, -0x2f0(%rbp)
leaq 0x6cae1(%rip), %rdi     # 0x9c3cd
leaq -0x2f0(%rbp), %rsi
callq 0x2fa90
movq %rax, -0x328(%rbp)
jmp 0x2f901
movq -0x328(%rbp), %rax
movq %rax, -0x2e8(%rbp)
leaq -0x2d0(%rbp), %rdi
leaq -0x2d8(%rbp), %rsi
leaq -0x2e8(%rbp), %rdx
callq 0x2f9e0
jmp 0x2f92b
leaq -0x2d0(%rbp), %rdi
callq 0x2ffa0
leaq -0x268(%rbp), %rdi
callq 0xa240
movl $0x0, -0x228(%rbp)
leaq -0x218(%rbp), %rdi
callq 0xa0f0
movl -0x4(%rbp), %eax
addq $0x330, %rsp            # imm = 0x330
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
leaq -0x291(%rbp), %rdi
callq 0xa420
jmp 0x2f9c3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0x2f9b7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x2ffa0
leaq -0x268(%rbp), %rdi
callq 0xa240
leaq -0x218(%rbp), %rdi
callq 0xa0f0
movq -0x220(%rbp), %rdi
callq 0xa650
nopl (%rax,%rax)