// File: pfnet-research[P]pml/src/translate_to_mdp.cpp
// Function: calc_binop_bound(value_info_t const&, value_info_t const&, ast::expr_kind_t)
value_info_t calc_binop_bound(
        value_info_t const& lhs,
        value_info_t const& rhs,
        ast::expr_kind_t op) {
    switch (op) {
    case ast::expr_kind_t::Add:
        return value_info_t {
            format("({}+{})", lhs.name, rhs.name),
            *lhs.bound + *rhs.bound
        };
    case ast::expr_kind_t::Sub:
        return value_info_t {
            format("({}-{})", lhs.name, rhs.name),
            *lhs.bound - *rhs.bound
        };
    case ast::expr_kind_t::Mul:
        return value_info_t {
            format("({}*{})", lhs.name, rhs.name),
            *lhs.bound * *rhs.bound
        };
    case ast::expr_kind_t::Div:
        return value_info_t {
            format("({}/{})", lhs.name, rhs.name),
            *lhs.bound / *rhs.bound
        };
    case ast::expr_kind_t::Eq:
        return value_info_t {
            format("{}={}", lhs.name, rhs.name),
            util::nullopt
        };
    case ast::expr_kind_t::Neq:
        return value_info_t {
            format("({}!={})", lhs.name, rhs.name),
            util::nullopt
        };
    case ast::expr_kind_t::Leq:
        return value_info_t {
            format("({}<={})", lhs.name, rhs.name),
            util::nullopt
        };
    case ast::expr_kind_t::Geq:
        return value_info_t {
            format("({}>={})", lhs.name, rhs.name),
            util::nullopt
        };
    case ast::expr_kind_t::And:
        return value_info_t {
            format("({}&{})", lhs.name, rhs.name),
            util::nullopt
        };
    case ast::expr_kind_t::Or:
        return value_info_t {
            format("({}|{})", lhs.name, rhs.name),
            util::nullopt
        };
    default:
        throw std::logic_error{"invalid binop"};
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x320, %rsp            # imm = 0x320
movq %rdi, -0x1f8(%rbp)
movq %rdi, %rax
movq %rax, -0x1f0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
addl $-0x6, %eax
movl %eax, %ecx
movq %rcx, -0x1e8(%rbp)
subl $0xa, %eax
ja 0x89a08
movq -0x1e8(%rbp), %rax
leaq 0x17197(%rip), %rcx     # 0xa0238
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x1f8(%rbp), %rax
movq %rax, -0x208(%rbp)
leaq -0x41(%rbp), %rdi
movq %rdi, -0x200(%rbp)
callq 0xa660
movq -0x200(%rbp), %rdx
leaq 0x17248(%rip), %rsi     # 0xa031e
leaq -0x40(%rbp), %rdi
callq 0x1dd10
jmp 0x890e1
movq -0x208(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x40(%rbp), %rsi
callq 0x89a80
jmp 0x890fb
movq -0x1f8(%rbp), %rax
addq $0x20, %rax
movq %rax, -0x218(%rbp)
movq -0x10(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x210(%rbp)
jmp 0x89123
movq -0x18(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x220(%rbp)
jmp 0x89139
movq -0x220(%rbp), %rsi
movq -0x210(%rbp), %rdi
callq 0x89d00
movq %rax, -0x228(%rbp)
jmp 0x89155
movq -0x218(%rbp), %rdi
movq -0x228(%rbp), %rax
movq %rax, -0x5c(%rbp)
leaq -0x5c(%rbp), %rsi
callq 0x8b7c0
jmp 0x89172
leaq -0x40(%rbp), %rdi
callq 0xa240
leaq -0x41(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x891c6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x891bd
movq -0x208(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
callq 0xa240
leaq -0x40(%rbp), %rdi
callq 0xa240
leaq -0x41(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x238(%rbp)
leaq -0x81(%rbp), %rdi
movq %rdi, -0x230(%rbp)
callq 0xa660
movq -0x230(%rbp), %rdx
leaq 0x17123(%rip), %rsi     # 0xa0326
leaq -0x80(%rbp), %rdi
callq 0x1dd10
jmp 0x8920e
movq -0x238(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x80(%rbp), %rsi
callq 0x89a80
jmp 0x89228
movq -0x1f8(%rbp), %rax
addq $0x20, %rax
movq %rax, -0x248(%rbp)
movq -0x10(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x240(%rbp)
jmp 0x89250
movq -0x18(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x250(%rbp)
jmp 0x89266
movq -0x250(%rbp), %rsi
movq -0x240(%rbp), %rdi
callq 0x89d40
movq %rax, -0x258(%rbp)
jmp 0x89282
movq -0x248(%rbp), %rdi
movq -0x258(%rbp), %rax
movq %rax, -0x8c(%rbp)
leaq -0x8c(%rbp), %rsi
callq 0x8b7c0
jmp 0x892a5
leaq -0x80(%rbp), %rdi
callq 0xa240
leaq -0x81(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x892fc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x892f3
movq -0x238(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
callq 0xa240
leaq -0x80(%rbp), %rdi
callq 0xa240
leaq -0x81(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x268(%rbp)
leaq -0xb1(%rbp), %rdi
movq %rdi, -0x260(%rbp)
callq 0xa660
movq -0x260(%rbp), %rdx
leaq 0x16ff2(%rip), %rsi     # 0xa032e
leaq -0xb0(%rbp), %rdi
callq 0x1dd10
jmp 0x8934a
movq -0x268(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0xb0(%rbp), %rsi
callq 0x89a80
jmp 0x89367
movq -0x1f8(%rbp), %rax
addq $0x20, %rax
movq %rax, -0x278(%rbp)
movq -0x10(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x270(%rbp)
jmp 0x8938f
movq -0x18(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x280(%rbp)
jmp 0x893a5
movq -0x280(%rbp), %rsi
movq -0x270(%rbp), %rdi
callq 0x89d80
movq %rax, -0x288(%rbp)
jmp 0x893c1
movq -0x278(%rbp), %rdi
movq -0x288(%rbp), %rax
movq %rax, -0xbc(%rbp)
leaq -0xbc(%rbp), %rsi
callq 0x8b7c0
jmp 0x893e4
leaq -0xb0(%rbp), %rdi
callq 0xa240
leaq -0xb1(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x89441
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x89435
movq -0x268(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
callq 0xa240
leaq -0xb0(%rbp), %rdi
callq 0xa240
leaq -0xb1(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x298(%rbp)
leaq -0xe1(%rbp), %rdi
movq %rdi, -0x290(%rbp)
callq 0xa660
movq -0x290(%rbp), %rdx
leaq 0x16eb5(%rip), %rsi     # 0xa0336
leaq -0xe0(%rbp), %rdi
callq 0x1dd10
jmp 0x8948f
movq -0x298(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0xe0(%rbp), %rsi
callq 0x89a80
jmp 0x894ac
movq -0x1f8(%rbp), %rax
addq $0x20, %rax
movq %rax, -0x2a8(%rbp)
movq -0x10(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x2a0(%rbp)
jmp 0x894d4
movq -0x18(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb90
movq %rax, -0x2b0(%rbp)
jmp 0x894ea
movq -0x2b0(%rbp), %rsi
movq -0x2a0(%rbp), %rdi
callq 0x89dc0
movq %rax, -0x2b8(%rbp)
jmp 0x89506
movq -0x2a8(%rbp), %rdi
movq -0x2b8(%rbp), %rax
movq %rax, -0xec(%rbp)
leaq -0xec(%rbp), %rsi
callq 0x8b7c0
jmp 0x89529
leaq -0xe0(%rbp), %rdi
callq 0xa240
leaq -0xe1(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x89586
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x8957a
movq -0x298(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
callq 0xa240
leaq -0xe0(%rbp), %rdi
callq 0xa240
leaq -0xe1(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x2c8(%rbp)
leaq -0x111(%rbp), %rdi
movq %rdi, -0x2c0(%rbp)
callq 0xa660
movq -0x2c0(%rbp), %rdx
leaq 0x16d78(%rip), %rsi     # 0xa033e
leaq -0x110(%rbp), %rdi
callq 0x1dd10
jmp 0x895d4
movq -0x2c8(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x110(%rbp), %rsi
callq 0x89a80
jmp 0x895f1
movq -0x1f8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb70
leaq -0x110(%rbp), %rdi
callq 0xa240
leaq -0x111(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x89644
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x110(%rbp), %rdi
callq 0xa240
leaq -0x111(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x2d8(%rbp)
leaq -0x139(%rbp), %rdi
movq %rdi, -0x2d0(%rbp)
callq 0xa660
movq -0x2d0(%rbp), %rdx
leaq 0x16cc0(%rip), %rsi     # 0xa0344
leaq -0x138(%rbp), %rdi
callq 0x1dd10
jmp 0x89692
movq -0x2d8(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x138(%rbp), %rsi
callq 0x89a80
jmp 0x896af
movq -0x1f8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb70
leaq -0x138(%rbp), %rdi
callq 0xa240
leaq -0x139(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x89702
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x138(%rbp), %rdi
callq 0xa240
leaq -0x139(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x2e8(%rbp)
leaq -0x161(%rbp), %rdi
movq %rdi, -0x2e0(%rbp)
callq 0xa660
movq -0x2e0(%rbp), %rdx
leaq 0x16c0b(%rip), %rsi     # 0xa034d
leaq -0x160(%rbp), %rdi
callq 0x1dd10
jmp 0x89750
movq -0x2e8(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x160(%rbp), %rsi
callq 0x89a80
jmp 0x8976d
movq -0x1f8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb70
leaq -0x160(%rbp), %rdi
callq 0xa240
leaq -0x161(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x897c0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x160(%rbp), %rdi
callq 0xa240
leaq -0x161(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x2f8(%rbp)
leaq -0x189(%rbp), %rdi
movq %rdi, -0x2f0(%rbp)
callq 0xa660
movq -0x2f0(%rbp), %rdx
leaq 0x16b56(%rip), %rsi     # 0xa0356
leaq -0x188(%rbp), %rdi
callq 0x1dd10
jmp 0x8980e
movq -0x2f8(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x188(%rbp), %rsi
callq 0x89a80
jmp 0x8982b
movq -0x1f8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb70
leaq -0x188(%rbp), %rdi
callq 0xa240
leaq -0x189(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x8987e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x188(%rbp), %rdi
callq 0xa240
leaq -0x189(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x308(%rbp)
leaq -0x1b1(%rbp), %rdi
movq %rdi, -0x300(%rbp)
callq 0xa660
movq -0x300(%rbp), %rdx
leaq 0x16aa1(%rip), %rsi     # 0xa035f
leaq -0x1b0(%rbp), %rdi
callq 0x1dd10
jmp 0x898cc
movq -0x308(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x1b0(%rbp), %rsi
callq 0x89a80
jmp 0x898e9
movq -0x1f8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb70
leaq -0x1b0(%rbp), %rdi
callq 0xa240
leaq -0x1b1(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x8993c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0xa240
leaq -0x1b1(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movq -0x1f8(%rbp), %rax
movq %rax, -0x318(%rbp)
leaq -0x1d9(%rbp), %rdi
movq %rdi, -0x310(%rbp)
callq 0xa660
movq -0x310(%rbp), %rdx
leaq 0x169eb(%rip), %rsi     # 0xa0367
leaq -0x1d8(%rbp), %rdi
callq 0x1dd10
jmp 0x8998a
movq -0x318(%rbp), %rdi
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
leaq -0x1d8(%rbp), %rsi
callq 0x89a80
jmp 0x899a7
movq -0x1f8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8bb70
leaq -0x1d8(%rbp), %rdi
callq 0xa240
leaq -0x1d9(%rbp), %rdi
callq 0xa420
jmp 0x89a61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x899fa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x1d8(%rbp), %rdi
callq 0xa240
leaq -0x1d9(%rbp), %rdi
callq 0xa420
jmp 0x89a71
movl $0x10, %edi
callq 0xa1d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x320(%rbp)
leaq 0x16949(%rip), %rsi     # 0xa036f
callq 0xa540
jmp 0x89a2d
movq -0x320(%rbp), %rdi
movq 0x5d595(%rip), %rsi     # 0xe6fd0
movq 0x5d54e(%rip), %rdx     # 0xe6f90
callq 0xa610
movq -0x320(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
callq 0xa2c0
jmp 0x89a71
movq -0x1f0(%rbp), %rax
addq $0x320, %rsp            # imm = 0x320
popq %rbp
retq
movq -0x50(%rbp), %rdi
callq 0xa650
nopw (%rax,%rax)