// File: pfnet-research[P]pml/src/test.cpp
// Function: letfun_test::letfun_test()
PML_CUSTOM_TEST(letfun_test, lang_feature_test) {
    using namespace ast;
    parse_test("letfun plus4 (a:int, b:int) -> int = a+4 in plus4 (1+3) 0", "LetFun(plus4, [a, b], Add(a, 4), App(plus4, [Add(1, 3), 0]))");
    eval_test(
            make<letfun_expr_t>("plus4",
                dependent_type_t {
                    {
                        refinement_type_t{"a",
                            logic::domain_kind_t::Int,
                            make<logic::top_formula_t>()},
                        refinement_type_t{"b",
                            logic::domain_kind_t::Int,
                            make<logic::top_formula_t>()}
                    },
                    refinement_type_t {"@blah",
                        logic::domain_kind_t::Int,
                        make<logic::top_formula_t>()
                    }
                },
                make<add_expr_t>(
                    make<var_expr_t>("a"),
                    make<int_expr_t>(4)),
                make<app_expr_t>(
                    make<var_expr_t>("plus4"),
                    std::vector<ptr<expr_t>>{
                        make<add_expr_t>(
                                make<int_expr_t>(1),
                                make<int_expr_t>(3)),
                        make<int_expr_t>(0)
                        })),
            make<int_expr_t>(8));
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3f0, %rsp            # imm = 0x3F0
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x2e8(%rbp)
callq 0x71b80
movq -0x2e8(%rbp), %rax
leaq 0x7bb0b(%rip), %rcx     # 0xe6678
movq %rcx, (%rax)
leaq -0x29(%rbp), %rdi
movq %rdi, -0x2e0(%rbp)
callq 0xa660
movq -0x2e0(%rbp), %rdx
leaq 0x34edc(%rip), %rsi     # 0x9fa6a
leaq -0x28(%rbp), %rdi
callq 0x1dd10
jmp 0x6ab99
leaq -0x61(%rbp), %rdi
movq %rdi, -0x2f0(%rbp)
callq 0xa660
movq -0x2f0(%rbp), %rdx
leaq 0x34eed(%rip), %rsi     # 0x9faa4
leaq -0x60(%rbp), %rdi
callq 0x1dd10
jmp 0x6abc2
movq -0x2e8(%rbp), %rdi
leaq -0x28(%rbp), %rsi
leaq -0x60(%rbp), %rdx
callq 0x71bc0
jmp 0x6abd8
leaq -0x60(%rbp), %rdi
callq 0xa240
leaq -0x61(%rbp), %rdi
callq 0xa420
leaq -0x28(%rbp), %rdi
callq 0xa240
leaq -0x29(%rbp), %rdi
callq 0xa420
leaq -0xd8(%rbp), %rax
movq %rax, -0x308(%rbp)
movb $0x1, -0x192(%rbp)
leaq -0x158(%rbp), %rax
movq %rax, -0x300(%rbp)
movq %rax, -0x160(%rbp)
leaq -0x161(%rbp), %rdi
movq %rdi, -0x2f8(%rbp)
callq 0xa660
movq -0x300(%rbp), %rdi
movq -0x2f8(%rbp), %rdx
leaq 0x34e11(%rip), %rsi     # 0x9fa5f
callq 0x1dd10
jmp 0x6ac55
movb $0x1, -0x179(%rbp)
movl $0x0, -0x138(%rbp)
leaq -0x130(%rbp), %rax
movq %rax, -0x310(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x681c0
jmp 0x6ac82
movq -0x310(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x40d40
movb $0x0, -0x179(%rbp)
leaq -0x120(%rbp), %rax
movq %rax, -0x320(%rbp)
movq %rax, %rcx
movq %rcx, -0x328(%rbp)
movq %rax, -0x160(%rbp)
leaq -0x17a(%rbp), %rdi
movq %rdi, -0x318(%rbp)
callq 0xa660
movq -0x320(%rbp), %rdi
movq -0x318(%rbp), %rdx
leaq 0x31d43(%rip), %rsi     # 0x9ca26
callq 0x1dd10
jmp 0x6acea
movq -0x328(%rbp), %rax
movb $0x1, -0x191(%rbp)
movl $0x0, 0x20(%rax)
addq $0x28, %rax
movq %rax, -0x330(%rbp)
leaq -0x190(%rbp), %rdi
callq 0x681c0
jmp 0x6ad18
movq -0x330(%rbp), %rdi
leaq -0x190(%rbp), %rsi
callq 0x40d40
movb $0x0, -0x191(%rbp)
movb $0x0, -0x192(%rbp)
leaq -0x158(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq $0x2, -0xe0(%rbp)
leaq -0x193(%rbp), %rdi
movq %rdi, -0x338(%rbp)
callq 0x49b90
movq -0x308(%rbp), %rdi
movq -0x338(%rbp), %rcx
movq -0xe8(%rbp), %rsi
movq -0xe0(%rbp), %rdx
callq 0x76560
jmp 0x6ad88
movb $0x1, -0x1aa(%rbp)
leaq -0xc0(%rbp), %rax
movq %rax, -0x348(%rbp)
movq %rax, -0x350(%rbp)
leaq -0x194(%rbp), %rdi
movq %rdi, -0x340(%rbp)
callq 0xa660
movq -0x348(%rbp), %rdi
movq -0x340(%rbp), %rdx
leaq 0x31d20(%rip), %rsi     # 0x9caec
callq 0x1dd10
jmp 0x6add3
movq -0x350(%rbp), %rax
movb $0x1, -0x1a9(%rbp)
movl $0x0, 0x20(%rax)
addq $0x28, %rax
movq %rax, -0x358(%rbp)
leaq -0x1a8(%rbp), %rdi
callq 0x681c0
jmp 0x6ae01
movq -0x358(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x40d40
movb $0x0, -0x1a9(%rbp)
movb $0x0, -0x1aa(%rbp)
leaq 0x34c36(%rip), %rsi     # 0x9fa5f
leaq -0x1d0(%rbp), %rdi
callq 0x68140
jmp 0x6ae37
movl $0x4, -0x1e4(%rbp)
leaq -0x1e0(%rbp), %rdi
leaq -0x1e4(%rbp), %rsi
callq 0x67db0
jmp 0x6ae56
leaq -0x1c0(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
leaq -0x1e0(%rbp), %rdx
callq 0x68100
jmp 0x6ae72
leaq 0x34c68(%rip), %rsi     # 0x9fae1
leaq -0x208(%rbp), %rdi
callq 0x68230
jmp 0x6ae87
movb $0x1, -0x2ad(%rbp)
leaq -0x250(%rbp), %rax
movq %rax, -0x258(%rbp)
movl $0x1, -0x27c(%rbp)
leaq -0x278(%rbp), %rdi
leaq -0x27c(%rbp), %rsi
callq 0x67db0
jmp 0x6aebb
movl $0x3, -0x294(%rbp)
leaq -0x290(%rbp), %rdi
leaq -0x294(%rbp), %rsi
callq 0x67db0
jmp 0x6aeda
leaq -0x268(%rbp), %rdi
leaq -0x278(%rbp), %rsi
leaq -0x290(%rbp), %rdx
callq 0x67f90
jmp 0x6aef6
leaq -0x250(%rbp), %rdi
leaq -0x268(%rbp), %rsi
callq 0x72f10
leaq -0x240(%rbp), %rax
movq %rax, -0x360(%rbp)
movq %rax, -0x258(%rbp)
movl $0x0, -0x2ac(%rbp)
leaq -0x2a8(%rbp), %rdi
leaq -0x2ac(%rbp), %rsi
callq 0x67db0
jmp 0x6af3d
movq -0x360(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
callq 0x12f60
movb $0x0, -0x2ad(%rbp)
leaq -0x250(%rbp), %rax
movq %rax, -0x230(%rbp)
movq $0x2, -0x228(%rbp)
leaq -0x2ae(%rbp), %rdi
movq %rdi, -0x368(%rbp)
callq 0x4ecd0
movq -0x368(%rbp), %rcx
movq -0x230(%rbp), %rsi
movq -0x228(%rbp), %rdx
leaq -0x220(%rbp), %rdi
callq 0x765e0
jmp 0x6afa6
leaq -0x1f8(%rbp), %rdi
leaq -0x208(%rbp), %rsi
leaq -0x220(%rbp), %rdx
callq 0x681f0
jmp 0x6afc2
leaq 0x34b18(%rip), %rsi     # 0x9fae1
leaq -0x88(%rbp), %rdi
leaq -0xd8(%rbp), %rdx
leaq -0x1c0(%rbp), %rcx
leaq -0x1f8(%rbp), %r8
callq 0x68170
jmp 0x6afec
leaq -0x78(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x41bf0
movl $0x8, -0x2d4(%rbp)
leaq -0x2d0(%rbp), %rdi
leaq -0x2d4(%rbp), %rsi
callq 0x67db0
jmp 0x6b01b
leaq -0x2c0(%rbp), %rdi
movq %rdi, -0x370(%rbp)
leaq -0x2d0(%rbp), %rsi
callq 0x12f60
movq -0x2e8(%rbp), %rdi
movq -0x370(%rbp), %rdx
leaq -0x78(%rbp), %rsi
callq 0x71cb0
jmp 0x6b04e
leaq -0x2c0(%rbp), %rdi
callq 0x13080
leaq -0x2d0(%rbp), %rdi
callq 0x12f90
leaq -0x78(%rbp), %rdi
callq 0x13080
leaq -0x88(%rbp), %rdi
callq 0x41c20
leaq -0x1f8(%rbp), %rdi
callq 0x41ff0
leaq -0x220(%rbp), %rdi
callq 0x42010
leaq -0x2ae(%rbp), %rdi
callq 0x4f870
leaq -0x250(%rbp), %rax
movq %rax, -0x380(%rbp)
addq $0x20, %rax
movq %rax, -0x378(%rbp)
movq -0x378(%rbp), %rdi
addq $-0x10, %rdi
movq %rdi, -0x388(%rbp)
callq 0x13080
movq -0x380(%rbp), %rcx
movq -0x388(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x378(%rbp)
jne 0x6b0b8
leaq -0x2a8(%rbp), %rdi
callq 0x12f90
leaq -0x268(%rbp), %rdi
callq 0x42140
leaq -0x290(%rbp), %rdi
callq 0x12f90
leaq -0x278(%rbp), %rdi
callq 0x12f90
leaq -0x208(%rbp), %rdi
callq 0x41d40
leaq -0x1c0(%rbp), %rdi
callq 0x42140
leaq -0x1e0(%rbp), %rdi
callq 0x12f90
leaq -0x1d0(%rbp), %rdi
callq 0x41d40
leaq -0xd8(%rbp), %rdi
callq 0x17e50
leaq -0x1a8(%rbp), %rdi
callq 0x40d70
leaq -0x194(%rbp), %rdi
callq 0xa420
leaq -0x193(%rbp), %rdi
callq 0x15b50
leaq -0x158(%rbp), %rax
movq %rax, -0x398(%rbp)
addq $0x70, %rax
movq %rax, -0x390(%rbp)
movq -0x390(%rbp), %rdi
addq $-0x38, %rdi
movq %rdi, -0x3a0(%rbp)
callq 0x16120
movq -0x398(%rbp), %rcx
movq -0x3a0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x390(%rbp)
jne 0x6b192
leaq -0x190(%rbp), %rdi
callq 0x40d70
leaq -0x17a(%rbp), %rdi
callq 0xa420
leaq -0x178(%rbp), %rdi
callq 0x40d70
leaq -0x161(%rbp), %rdi
callq 0xa420
addq $0x3f0, %rsp            # imm = 0x3F0
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b23f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b22d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x60(%rbp), %rdi
callq 0xa240
leaq -0x61(%rbp), %rdi
callq 0xa420
leaq -0x28(%rbp), %rdi
callq 0xa240
leaq -0x29(%rbp), %rdi
callq 0xa420
jmp 0x6b64b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b5e5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b5cc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b5b4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b59b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b539
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b514
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b4fb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b4e3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b4d7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b4cb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b4bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b45b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b44f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b443
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b437
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b3d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b3c9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b3bd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x6b3a8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x2c0(%rbp), %rdi
callq 0x13080
leaq -0x2d0(%rbp), %rdi
callq 0x12f90
leaq -0x78(%rbp), %rdi
callq 0x13080
leaq -0x88(%rbp), %rdi
callq 0x41c20
leaq -0x1f8(%rbp), %rdi
callq 0x41ff0
leaq -0x220(%rbp), %rdi
callq 0x42010
leaq -0x2ae(%rbp), %rdi
callq 0x4f870
leaq -0x250(%rbp), %rax
movq %rax, -0x3b0(%rbp)
addq $0x20, %rax
movq %rax, -0x3a8(%rbp)
movq -0x3a8(%rbp), %rdi
addq $-0x10, %rdi
movq %rdi, -0x3b8(%rbp)
callq 0x13080
movq -0x3b0(%rbp), %rcx
movq -0x3b8(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x3a8(%rbp)
jne 0x6b3fa
leaq -0x2a8(%rbp), %rdi
callq 0x12f90
leaq -0x268(%rbp), %rdi
callq 0x42140
leaq -0x290(%rbp), %rdi
callq 0x12f90
leaq -0x278(%rbp), %rdi
callq 0x12f90
testb $0x1, -0x2ad(%rbp)
jne 0x6b466
jmp 0x6b4b3
movq -0x258(%rbp), %rax
leaq -0x250(%rbp), %rcx
cmpq %rax, %rcx
movq %rax, -0x3c0(%rbp)
je 0x6b4b1
movq -0x3c0(%rbp), %rdi
addq $-0x10, %rdi
movq %rdi, -0x3c8(%rbp)
callq 0x13080
movq -0x3c8(%rbp), %rax
leaq -0x250(%rbp), %rcx
cmpq %rcx, %rax
movq %rax, -0x3c0(%rbp)
jne 0x6b480
jmp 0x6b4b3
leaq -0x208(%rbp), %rdi
callq 0x41d40
leaq -0x1c0(%rbp), %rdi
callq 0x42140
leaq -0x1e0(%rbp), %rdi
callq 0x12f90
leaq -0x1d0(%rbp), %rdi
callq 0x41d40
leaq -0xd8(%rbp), %rdi
callq 0x17e50
leaq -0x1a8(%rbp), %rdi
callq 0x40d70
testb $0x1, -0x1a9(%rbp)
jne 0x6b506
jmp 0x6b512
movq -0x348(%rbp), %rdi
callq 0xa240
jmp 0x6b514
leaq -0x194(%rbp), %rdi
callq 0xa420
testb $0x1, -0x1aa(%rbp)
jne 0x6b52b
jmp 0x6b537
movq -0x308(%rbp), %rdi
callq 0x15a50
jmp 0x6b539
leaq -0x193(%rbp), %rdi
callq 0x15b50
leaq -0x158(%rbp), %rax
movq %rax, -0x3d8(%rbp)
addq $0x70, %rax
movq %rax, -0x3d0(%rbp)
movq -0x3d0(%rbp), %rdi
addq $-0x38, %rdi
movq %rdi, -0x3e0(%rbp)
callq 0x16120
movq -0x3d8(%rbp), %rcx
movq -0x3e0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x3d0(%rbp)
jne 0x6b55e
leaq -0x190(%rbp), %rdi
callq 0x40d70
testb $0x1, -0x191(%rbp)
jne 0x6b5a6
jmp 0x6b5b2
movq -0x320(%rbp), %rdi
callq 0xa240
jmp 0x6b5b4
leaq -0x17a(%rbp), %rdi
callq 0xa420
leaq -0x178(%rbp), %rdi
callq 0x40d70
testb $0x1, -0x179(%rbp)
jne 0x6b5d7
jmp 0x6b5e3
movq -0x300(%rbp), %rdi
callq 0xa240
jmp 0x6b5e5
leaq -0x161(%rbp), %rdi
callq 0xa420
testb $0x1, -0x192(%rbp)
jne 0x6b5fc
jmp 0x6b649
movq -0x160(%rbp), %rax
leaq -0x158(%rbp), %rcx
cmpq %rax, %rcx
movq %rax, -0x3e8(%rbp)
je 0x6b647
movq -0x3e8(%rbp), %rdi
addq $-0x38, %rdi
movq %rdi, -0x3f0(%rbp)
callq 0x16120
movq -0x3f0(%rbp), %rax
leaq -0x158(%rbp), %rcx
cmpq %rcx, %rax
movq %rax, -0x3e8(%rbp)
jne 0x6b616
jmp 0x6b649
jmp 0x6b64b
movq -0x2e8(%rbp), %rdi
callq 0x71f50
movq -0x38(%rbp), %rdi
callq 0xa650