// File: /workspace/github_cpp_makefile_star2_O3/pfnet-research[P]pml/src/expr_ast.cpp
// Function: ast::operator==(ast::expr_t const&, ast::expr_t const&)
bool operator==(expr_t const& lhs, expr_t const& rhs) {
    if (lhs.kind() != rhs.kind())
        return false;

    if (lhs.kind() == expr_kind_t::Let) {
        auto const& l = cast<let_expr_t>(lhs);
        auto const& r = cast<let_expr_t>(rhs);
        return l.name == r.name && *l.init == *r.init && *l.body == *r.body;
    }
    if (lhs.kind() == expr_kind_t::LetFun) {
        auto const& l = cast<letfun_expr_t>(lhs);
        auto const& r = cast<letfun_expr_t>(rhs);
        return
            l.name == r.name && l.type == r.type &&
            *l.init == *r.init && *l.body == *r.body;
    }
    if (lhs.kind() == expr_kind_t::If) {
        auto const& l = cast<if_expr_t>(lhs);
        auto const& r = cast<if_expr_t>(rhs);
        return
            *l.cond_expr == *r.cond_expr &&
            *l.true_expr == *r.true_expr && *l.false_expr == *r.false_expr;
    }
    if (lhs.kind() == expr_kind_t::App) {
        auto const& l = cast<app_expr_t>(lhs);
        auto const& r = cast<app_expr_t>(rhs);
        if (*l.f != *r.f || l.args.size() != r.args.size())
            return false;
        for (size_t i=0; i<l.args.size(); ++i) {
            if (*l.args[i] != *r.args[i])
                return false;
        }
        return true;
    }
    if (lhs.kind() == expr_kind_t::Rand) {
        auto const& l = cast<rand_expr_t>(lhs);
        auto const& r = cast<rand_expr_t>(rhs);
        return l.start == r.start && l.end == r.end;
    }
    if (lhs.kind() == expr_kind_t::Eq ||
            lhs.kind() == expr_kind_t::Neq ||
            lhs.kind() == expr_kind_t::Leq ||
            lhs.kind() == expr_kind_t::Geq ||
            lhs.kind() == expr_kind_t::Add ||
            lhs.kind() == expr_kind_t::Sub ||
            lhs.kind() == expr_kind_t::Mul ||
            lhs.kind() == expr_kind_t::Div ||
            lhs.kind() == expr_kind_t::And ||
            lhs.kind() == expr_kind_t::Or) {
        auto const& l = cast<binop_expr_t>(lhs);
        auto const& r = cast<binop_expr_t>(rhs);
        return *l.lhs == *r.lhs && *l.rhs == *r.rhs;
    }
    if (lhs.kind() == expr_kind_t::Neg)
        return *cast<neg_expr_t>(lhs).inner == *cast<neg_expr_t>(rhs).inner;
    if (lhs.kind() == expr_kind_t::Typed) {
        auto const& l = cast<typed_expr_t>(lhs);
        auto const& r = cast<typed_expr_t>(rhs);
        return *l.expr == *r.expr && l.type == r.type;
    }
    if (lhs.kind() == expr_kind_t::Int) {
        return cast<int_expr_t>(lhs) == cast<int_expr_t>(rhs);
    }
    if (lhs.kind() == expr_kind_t::Bool)
        return cast<bool_expr_t>(lhs) == cast<bool_expr_t>(rhs);
    throw std::logic_error{"unreachable!!"};
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbp
movq %rdi, %r13
movq (%rdi), %rax
callq *(%rax)
movl %eax, %ebx
movq (%rbp), %rax
movq %rbp, %rdi
callq *(%rax)
cmpl %eax, %ebx
jne 0xe821
leaq 0x51740(%rip), %rbx     # 0x5fa98
leaq 0x517f1(%rip), %r14     # 0x5fb50
leaq 0x518aa(%rip), %r12     # 0x5fc10
movq %r12, %r15
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
testl %eax, %eax
je 0xe433
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x1, %eax
jne 0xe4b5
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x517cf(%rip), %r12     # 0x5fb68
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %r13
movq %rbp, %rdi
movq %rbx, %rsi
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %rbp
movq 0x10(%r13), %rdx
cmpq 0x10(%rax), %rdx
jne 0xe821
testq %rdx, %rdx
je 0xe3f3
movq 0x8(%rbp), %rsi
movq 0x8(%r13), %rdi
callq 0x9300
testl %eax, %eax
jne 0xe821
movq %r13, %rdi
addq $0x28, %rdi
leaq 0x28(%rbp), %rsi
callq 0x42ef6
testb %al, %al
je 0xe821
movq 0x78(%r13), %rdi
movq 0x78(%rbp), %rsi
callq 0xe328
testb %al, %al
je 0xe821
movq 0x88(%r13), %r13
addq $0x88, %rbp
jmp 0xe646
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %r13
movq %rbp, %rdi
movq %rbx, %rsi
movq %r14, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %rbp
movq 0x10(%r13), %rdx
cmpq 0x10(%rax), %rdx
jne 0xe821
testq %rdx, %rdx
je 0xe493
movq 0x8(%rbp), %rsi
movq 0x8(%r13), %rdi
callq 0x9300
testl %eax, %eax
jne 0xe821
movq 0x28(%r13), %rdi
movq 0x28(%rbp), %rsi
callq 0xe328
testb %al, %al
je 0xe821
movq 0x38(%r13), %r13
addq $0x38, %rbp
jmp 0xe646
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x2, %eax
jne 0xe532
movq %r13, %rdi
movq %rbx, %rsi
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %r13
movq %rbp, %rdi
movq %rbx, %rsi
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %rbp
movq 0x8(%r13), %rdi
movq 0x8(%rax), %rsi
callq 0xe328
testb %al, %al
je 0xe821
movq 0x18(%r13), %rdi
movq 0x18(%rbp), %rsi
callq 0xe328
testb %al, %al
je 0xe821
movq 0x28(%r13), %r13
addq $0x28, %rbp
jmp 0xe646
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x3, %eax
je 0xe69f
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x4, %eax
je 0xe763
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0xb, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0xc, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0xd, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0xe, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x6, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x7, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x8, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x9, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0xf, %eax
je 0xe5ea
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x10, %eax
jne 0xe670
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x51631(%rip), %r12     # 0x5fc28
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %r13
movq %rbp, %rdi
movq %rbx, %rsi
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %rbp
movq 0x8(%r13), %rdi
movq 0x8(%rax), %rsi
callq 0xe328
testb %al, %al
je 0xe821
movq 0x18(%r13), %r13
addq $0x18, %rbp
movq (%rbp), %rbp
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
movl %eax, %r12d
movq (%rbp), %rax
movq %rbp, %rdi
callq *(%rax)
cmpl %eax, %r12d
movq %r15, %r12
je 0xe369
jmp 0xe821
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0xa, %eax
jne 0xe7cb
movq %r13, %rdi
callq 0xe8d4
movq 0x8(%rax), %r13
movq %rbp, %rdi
callq 0xe8d4
movq %rax, %rbp
addq $0x8, %rbp
jmp 0xe646
leaq 0x513f2(%rip), %rsi     # 0x5fa98
leaq 0x515c3(%rip), %rdx     # 0x5fc70
movq %r13, %rdi
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %rbx
leaq 0x513ce(%rip), %rsi     # 0x5fa98
leaq 0x5159f(%rip), %rdx     # 0x5fc70
movq %rbp, %rdi
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %r14
movq 0x8(%rbx), %rdi
movq 0x8(%rax), %rsi
callq 0xe328
testb %al, %al
je 0xe821
movq 0x18(%rbx), %rcx
movq 0x20(%rbx), %rax
movq %rax, %rdx
subq %rcx, %rdx
movq 0x20(%r14), %rsi
subq 0x18(%r14), %rsi
cmpq %rsi, %rdx
jne 0xe821
cmpq %rcx, %rax
je 0xe7c7
xorl %r15d, %r15d
xorl %r12d, %r12d
movq (%rcx,%r15), %rdi
movq 0x18(%r14), %rax
movq (%rax,%r15), %rsi
callq 0xe328
testb %al, %al
je 0xe823
incq %r12
movq 0x18(%rbx), %rcx
movq 0x20(%rbx), %rdx
subq %rcx, %rdx
sarq $0x4, %rdx
addq $0x10, %r15
cmpq %rdx, %r12
jb 0xe72a
jmp 0xe823
leaq 0x5132e(%rip), %rsi     # 0x5fa98
leaq 0x51517(%rip), %rdx     # 0x5fc88
movq %r13, %rdi
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq %rax, %rbx
leaq 0x5130a(%rip), %rsi     # 0x5fa98
leaq 0x514f3(%rip), %rdx     # 0x5fc88
movq %rbp, %rdi
xorl %ecx, %ecx
callq 0x9340
testq %rax, %rax
je 0xe85e
movq 0x8(%rbx), %xmm0
movq 0x8(%rax), %xmm1
pcmpeqd %xmm0, %xmm1
pshufd $0x50, %xmm1, %xmm0     # xmm0 = xmm1[0,0,1,1]
movmskpd %xmm0, %eax
cmpl $0x3, %eax
sete %al
jmp 0xe823
movb $0x1, %al
jmp 0xe823
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x5, %eax
jne 0xe832
movq %r13, %rdi
callq 0xe8f6
movq %rax, %rbx
movq %rbp, %rdi
callq 0xe8f6
movq %rax, %r14
movq 0x8(%rbx), %rdi
movq 0x8(%rax), %rsi
callq 0xe328
testb %al, %al
je 0xe821
addq $0x18, %rbx
addq $0x18, %r14
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x429b8
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x11, %eax
jne 0xe863
movq %r13, %rdi
callq 0xe918
movq %rax, %rbx
movq %rbp, %rdi
callq 0xe918
movl 0x8(%rbx), %ecx
cmpl 0x8(%rax), %ecx
jmp 0xe7c2
callq 0x9530
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
cmpl $0x12, %eax
jne 0xe88f
movq %r13, %rdi
callq 0xe93a
movq %rax, %rbx
movq %rbp, %rdi
callq 0xe93a
movb 0x8(%rbx), %cl
cmpb 0x8(%rax), %cl
jmp 0xe7c2
movl $0x10, %edi
callq 0x9150
movq %rax, %rbx
leaq 0x388e9(%rip), %rsi     # 0x4718c
movq %rax, %rdi
callq 0x93c0
movq 0x5371e(%rip), %rsi     # 0x61fd0
movq 0x536ef(%rip), %rdx     # 0x61fa8
movq %rbx, %rdi
callq 0x94b0
movq %rax, %r14
movq %rbx, %rdi
callq 0x9200
movq %r14, %rdi
callq 0x94e0