// File: pfnet-research[P]pml/src/translate_to_mdp.cpp
// Function: create_let_case(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, ast::expr_t const&, ast::expr_t const&, environment_t<value_info_t> const&)
mdp_with_info_t create_let_case(
        std::string const& name,
        ast::expr_t const& init,
        ast::expr_t const& body,
        var_env_t const& var_env) {

    // TODO: resolve name conflict case
    // e.g) let a = 1 in let a = 3 in ...

    auto init_ = trans_impl(init, var_env);
    auto new_env = var_env.append(name, make<value_info_t>(init_.value));
    auto body_ = trans_impl(body, new_env);

    // concat accept location of init to init location of body,
    // and subst value of init to variable `name`.
    //
    // [] location=accept-of-init -> 1:(location'=init-of-body)&(name'=value_name-of-init)
    auto concat = make_concat(
            init_.accept, body_.init,
            make<mdp::binop_expr_t>(
                make<mdp::var_expr_t>(name+"'"),
                make<mdp::var_expr_t>(init_.value.name),
                mdp::binop_kind_t::Eq));

    auto result_mdp = mdp::mdp_t::merge(std::move(init_.mdp), std::move(body_.mdp));
    result_mdp.commands.push_back(concat);

    if (init_.value.bound) { // integer
        result_mdp.variables.push_back(mdp::variable_t {
                name, *init_.value.bound, 0
                });
    } else { // boolean
        result_mdp.variables.push_back(mdp::variable_t {
                name, true
                });
    }

    return mdp_with_info_t {
        result_mdp, init_.init, body_.accept,
        body_.value
    };
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x350, %rsp            # imm = 0x350
movq %rdi, -0x318(%rbp)
movq %rdi, %rax
movq %rax, -0x310(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0xc8(%rbp), %rdi
callq 0x881e0
movq -0x28(%rbp), %rax
movq %rax, -0x308(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x300(%rbp)
leaq -0x58(%rbp), %rsi
leaq -0xf0(%rbp), %rdi
callq 0x88490
jmp 0x87d2c
movq -0x300(%rbp), %rdx
movq -0x308(%rbp), %rsi
leaq -0xe0(%rbp), %rdi
leaq -0xf0(%rbp), %rcx
callq 0x8b7f0
jmp 0x87d4f
leaq -0xf0(%rbp), %rdi
callq 0x8b8c0
movq -0x20(%rbp), %rsi
leaq -0x1a0(%rbp), %rdi
leaq -0xe0(%rbp), %rdx
callq 0x881e0
jmp 0x87d74
movl -0x5c(%rbp), %eax
movl %eax, -0x320(%rbp)
movl -0x138(%rbp), %eax
movl %eax, -0x31c(%rbp)
movq -0x10(%rbp), %rsi
leaq 0x17eeb(%rip), %rdx     # 0x9fc7f
leaq -0x218(%rbp), %rdi
callq 0x8b610
jmp 0x87da2
leaq -0x1f8(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0x86fb0
jmp 0x87db7
leaq -0x58(%rbp), %rsi
leaq -0x228(%rbp), %rdi
callq 0x88500
jmp 0x87dc9
movl $0x8, -0x22c(%rbp)
leaq -0x1e8(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
leaq -0x228(%rbp), %rdx
leaq -0x22c(%rbp), %rcx
callq 0x884c0
jmp 0x87df6
leaq -0x1d8(%rbp), %rdi
movq %rdi, -0x328(%rbp)
leaq -0x1e8(%rbp), %rsi
callq 0x7a500
movl -0x320(%rbp), %esi
movl -0x31c(%rbp), %edx
movq -0x328(%rbp), %rcx
leaq -0x1c8(%rbp), %rdi
callq 0x873d0
jmp 0x87e31
leaq -0x1d8(%rbp), %rdi
callq 0xceb0
leaq -0x1e8(%rbp), %rdi
callq 0x7a670
leaq -0x228(%rbp), %rdi
callq 0x7a6b0
leaq -0x1f8(%rbp), %rdi
callq 0x7a6b0
leaq -0x218(%rbp), %rdi
callq 0xa240
leaq -0x298(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
leaq -0x1a0(%rbp), %rdx
callq 0xa960
jmp 0x87e89
leaq -0x248(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0x8b8e0
jmp 0x87e9e
leaq -0xc8(%rbp), %rdi
addq $0x70, %rdi
addq $0x20, %rdi
callq 0x8b950
testb $0x1, %al
jne 0x87ebb
jmp 0x88072
leaq -0x278(%rbp), %rax
movq %rax, -0x340(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x338(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x8b9a0
movq %rax, -0x330(%rbp)
jmp 0x87ee6
movq -0x330(%rbp), %rdx
movq -0x338(%rbp), %rsi
leaq -0x2c8(%rbp), %rdi
xorl %ecx, %ecx
callq 0x7a3c0
jmp 0x87f04
movq -0x340(%rbp), %rdi
leaq -0x2c8(%rbp), %rsi
callq 0x8b970
jmp 0x87f19
leaq -0x2c8(%rbp), %rdi
callq 0xdda0
jmp 0x880dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x881be
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x8b8c0
jmp 0x881be
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x881b2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x881a6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x88010
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x88004
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x87ff8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
leaq -0x1d8(%rbp), %rdi
callq 0xceb0
leaq -0x1e8(%rbp), %rdi
callq 0x7a670
leaq -0x228(%rbp), %rdi
callq 0x7a6b0
leaq -0x1f8(%rbp), %rdi
callq 0x7a6b0
leaq -0x218(%rbp), %rdi
callq 0xa240
jmp 0x881a6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x8819a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x8818e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
leaq -0x2c8(%rbp), %rdi
callq 0xdda0
jmp 0x8818e
leaq -0x278(%rbp), %rax
movq %rax, -0x348(%rbp)
movq -0x10(%rbp), %rsi
leaq -0x2f8(%rbp), %rdi
movl $0x1, %edx
callq 0x8b9c0
jmp 0x88097
movq -0x348(%rbp), %rdi
leaq -0x2f8(%rbp), %rsi
callq 0x8b970
jmp 0x880ac
leaq -0x2f8(%rbp), %rdi
callq 0xdda0
jmp 0x880dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0xdda0
jmp 0x8818e
movq -0x318(%rbp), %rdi
movq %rdi, %rax
movq %rax, -0x350(%rbp)
leaq -0x298(%rbp), %rsi
callq 0x8b6f0
jmp 0x880fc
movq -0x318(%rbp), %rdi
movl -0x60(%rbp), %eax
movl %eax, 0x68(%rdi)
movl -0x134(%rbp), %eax
movl %eax, 0x6c(%rdi)
addq $0x70, %rdi
leaq -0x130(%rbp), %rsi
callq 0x8ba30
jmp 0x88124
leaq -0x298(%rbp), %rdi
callq 0xc340
leaq -0x1c8(%rbp), %rdi
callq 0xce20
leaq -0x1a0(%rbp), %rdi
callq 0x79690
leaq -0xe0(%rbp), %rdi
callq 0x8ba90
leaq -0xc8(%rbp), %rdi
callq 0x79690
movq -0x310(%rbp), %rax
addq $0x350, %rsp            # imm = 0x350
popq %rbp
retq
movq -0x350(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
callq 0xc340
leaq -0x298(%rbp), %rdi
callq 0xc340
leaq -0x1c8(%rbp), %rdi
callq 0xce20
leaq -0x1a0(%rbp), %rdi
callq 0x79690
leaq -0xe0(%rbp), %rdi
callq 0x8ba90
leaq -0xc8(%rbp), %rdi
callq 0x79690
movq -0xf8(%rbp), %rdi
callq 0xa650
nopw %cs:(%rax,%rax)