// File: pfnet-research[P]pml/src/evaluator.cpp
// Function: calc_int_binop(ast::expr_t const&, ast::expr_t const&, ast::expr_kind_t)
ptr<ast::expr_t> calc_int_binop(
        ast::expr_t const& lhs,
        ast::expr_t const& rhs,
        ast::expr_kind_t kind) {
    using namespace ast;
    assert(is_value(lhs));
    assert(is_value(rhs));
    switch (kind) {
    case expr_kind_t::Eq:
        return make<bool_expr_t>(lhs == rhs);
    case expr_kind_t::Neq:
        return make<bool_expr_t>(lhs != rhs);
    case expr_kind_t::Leq:
        return make<bool_expr_t>(cast<int_expr_t>(lhs).n <= cast<int_expr_t>(rhs).n);
    case expr_kind_t::Geq:
        return make<bool_expr_t>(cast<int_expr_t>(lhs).n >= cast<int_expr_t>(rhs).n);
    case expr_kind_t::Add:
        return make<int_expr_t>(cast<int_expr_t>(lhs).n + cast<int_expr_t>(rhs).n);
    case expr_kind_t::Sub:
        return make<int_expr_t>(cast<int_expr_t>(lhs).n - cast<int_expr_t>(rhs).n);
    case expr_kind_t::Mul:
        return make<int_expr_t>(cast<int_expr_t>(lhs).n * cast<int_expr_t>(rhs).n);
    case expr_kind_t::Div:
        return make<int_expr_t>(cast<int_expr_t>(lhs).n / cast<int_expr_t>(rhs).n);
    case expr_kind_t::And:
        return make<bool_expr_t>(cast<bool_expr_t>(lhs).b && cast<bool_expr_t>(rhs).b);
    case expr_kind_t::Or:
        return make<bool_expr_t>(cast<bool_expr_t>(lhs).b || cast<bool_expr_t>(rhs).b);
    default:
        throw std::logic_error{"invalid binop : " + to_string(kind)};
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdi, -0x170(%rbp)
movq %rdi, %rax
movq %rax, -0x168(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x10(%rbp), %rdi
callq 0x11bc0
testb $0x1, %al
jne 0x1168a
jmp 0x1168c
jmp 0x116ab
leaq 0x87c12(%rip), %rdi     # 0x992a5
leaq 0x87c19(%rip), %rsi     # 0x992b3
movl $0xe, %edx
leaq 0x87c1f(%rip), %rcx     # 0x992c5
callq 0xa260
movq -0x18(%rbp), %rdi
callq 0x11bc0
testb $0x1, %al
jne 0x116ba
jmp 0x116bc
jmp 0x116db
leaq 0x87c5e(%rip), %rdi     # 0x99321
leaq 0x87be9(%rip), %rsi     # 0x992b3
movl $0xf, %edx
leaq 0x87bef(%rip), %rcx     # 0x992c5
callq 0xa260
movl -0x1c(%rbp), %eax
addl $-0x6, %eax
movl %eax, %ecx
movq %rcx, -0x178(%rbp)
subl $0xa, %eax
ja 0x11aac
movq -0x178(%rbp), %rax
leaq 0x87b23(%rip), %rcx     # 0x99224
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x1b530
andb $0x1, %al
movb %al, -0x31(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x31(%rbp), %rsi
callq 0x11c10
movq -0x170(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x12f10
leaq -0x30(%rbp), %rdi
callq 0x12f40
jmp 0x11b97
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x11c40
andb $0x1, %al
movb %al, -0x49(%rbp)
leaq -0x48(%rbp), %rdi
leaq -0x49(%rbp), %rsi
callq 0x11c10
movq -0x170(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x12f10
leaq -0x48(%rbp), %rdi
callq 0x12f40
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11c70
movl 0x8(%rax), %eax
movl %eax, -0x17c(%rbp)
movq -0x18(%rbp), %rdi
callq 0x11c70
movq %rax, %rcx
movl -0x17c(%rbp), %eax
cmpl 0x8(%rcx), %eax
setle %al
andb $0x1, %al
movb %al, -0x61(%rbp)
leaq -0x60(%rbp), %rdi
leaq -0x61(%rbp), %rsi
callq 0x11c10
movq -0x170(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x12f10
leaq -0x60(%rbp), %rdi
callq 0x12f40
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11c70
movl 0x8(%rax), %eax
movl %eax, -0x180(%rbp)
movq -0x18(%rbp), %rdi
callq 0x11c70
movq %rax, %rcx
movl -0x180(%rbp), %eax
cmpl 0x8(%rcx), %eax
setge %al
andb $0x1, %al
movb %al, -0x79(%rbp)
leaq -0x78(%rbp), %rdi
leaq -0x79(%rbp), %rsi
callq 0x11c10
movq -0x170(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x12f10
leaq -0x78(%rbp), %rdi
callq 0x12f40
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11c70
movl 0x8(%rax), %eax
movl %eax, -0x184(%rbp)
movq -0x18(%rbp), %rdi
callq 0x11c70
movq %rax, %rcx
movl -0x184(%rbp), %eax
addl 0x8(%rcx), %eax
movl %eax, -0x94(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x94(%rbp), %rsi
callq 0x11cb0
movq -0x170(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x12f60
leaq -0x90(%rbp), %rdi
callq 0x12f90
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11c70
movl 0x8(%rax), %eax
movl %eax, -0x188(%rbp)
movq -0x18(%rbp), %rdi
callq 0x11c70
movq %rax, %rcx
movl -0x188(%rbp), %eax
subl 0x8(%rcx), %eax
movl %eax, -0xac(%rbp)
leaq -0xa8(%rbp), %rdi
leaq -0xac(%rbp), %rsi
callq 0x11cb0
movq -0x170(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x12f60
leaq -0xa8(%rbp), %rdi
callq 0x12f90
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11c70
movl 0x8(%rax), %eax
movl %eax, -0x18c(%rbp)
movq -0x18(%rbp), %rdi
callq 0x11c70
movq %rax, %rcx
movl -0x18c(%rbp), %eax
imull 0x8(%rcx), %eax
movl %eax, -0xc4(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xc4(%rbp), %rsi
callq 0x11cb0
movq -0x170(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x12f60
leaq -0xc0(%rbp), %rdi
callq 0x12f90
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11c70
movl 0x8(%rax), %eax
movl %eax, -0x190(%rbp)
movq -0x18(%rbp), %rdi
callq 0x11c70
movq %rax, %rcx
movl -0x190(%rbp), %eax
cltd
idivl 0x8(%rcx)
movl %eax, -0xdc(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0xdc(%rbp), %rsi
callq 0x11cb0
movq -0x170(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0x12f60
leaq -0xd8(%rbp), %rdi
callq 0x12f90
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11ce0
movq %rax, %rcx
xorl %eax, %eax
testb $0x1, 0x8(%rcx)
movb %al, -0x191(%rbp)
je 0x119f6
movq -0x18(%rbp), %rdi
callq 0x11ce0
movb 0x8(%rax), %al
movb %al, -0x191(%rbp)
movb -0x191(%rbp), %al
andb $0x1, %al
movb %al, -0xf1(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0xf1(%rbp), %rsi
callq 0x11c10
movq -0x170(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x12f10
leaq -0xf0(%rbp), %rdi
callq 0x12f40
jmp 0x11b97
movq -0x10(%rbp), %rdi
callq 0x11ce0
movq %rax, %rcx
movb $0x1, %al
testb $0x1, 0x8(%rcx)
movb %al, -0x192(%rbp)
jne 0x11a67
movq -0x18(%rbp), %rdi
callq 0x11ce0
movb 0x8(%rax), %al
movb %al, -0x192(%rbp)
movb -0x192(%rbp), %al
andb $0x1, %al
movb %al, -0x109(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x109(%rbp), %rsi
callq 0x11c10
movq -0x170(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x12f10
leaq -0x108(%rbp), %rdi
callq 0x12f40
jmp 0x11b97
movb $0x1, -0x15d(%rbp)
movl $0x10, %edi
callq 0xa1d0
movq %rax, -0x1a0(%rbp)
movl -0x1c(%rbp), %esi
leaq -0x150(%rbp), %rdi
callq 0x1ae60
jmp 0x11ad5
leaq 0x87853(%rip), %rsi     # 0x9932f
leaq -0x130(%rbp), %rdi
leaq -0x150(%rbp), %rdx
callq 0x12fb0
jmp 0x11af1
movq -0x1a0(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0xa570
jmp 0x11b06
movq -0x1a0(%rbp), %rdi
movb $0x0, -0x15d(%rbp)
movq 0xd54b5(%rip), %rsi     # 0xe6fd0
movq 0xd546e(%rip), %rdx     # 0xe6f90
callq 0xa610
jmp 0x11bb3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x158(%rbp)
movl %eax, -0x15c(%rbp)
jmp 0x11b7e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x158(%rbp)
movl %eax, -0x15c(%rbp)
jmp 0x11b72
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x158(%rbp)
movl %eax, -0x15c(%rbp)
leaq -0x130(%rbp), %rdi
callq 0xa240
leaq -0x150(%rbp), %rdi
callq 0xa240
testb $0x1, -0x15d(%rbp)
jne 0x11b89
jmp 0x11b95
movq -0x1a0(%rbp), %rdi
callq 0xa2c0
jmp 0x11ba7
movq -0x168(%rbp), %rax
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
movq -0x158(%rbp), %rdi
callq 0xa650
nopw %cs:(%rax,%rax)