// File: tsoding[P]wcc/src/./wcc_wat_compiler.cpp
// Function: Wat_Compiler::compile_statement(Statement)
S_Expr *Wat_Compiler::compile_statement(Statement statement)
{
    switch (statement.kind) {
    case Statement_Kind::Local_Var_Def:
        reporter.fail(statement.offset, "TODO: Local variable definitions are only allowed at the beginning of the function");
        break;
    case Statement_Kind::If:
        if (statement.iph.then == nullptr && statement.iph.elze == nullptr) {
            return list(atom("drop"_sv), compile_expression(statement.iph.condition));
        } else {
            //  (if (result <type>)
            //    (then <then-branch>)
            //    (else (else-branch)))
            if (statement.type == Type::U0) {
                return list(
                    atom("if"_sv),
                    compile_expression(statement.iph.condition),
                    append(list(atom("then"_sv)), compile_block(statement.iph.then)),
                    append(list(atom("else"_sv)), compile_block(statement.iph.elze)));
            } else {
                return list(
                    atom("if"_sv), list(atom("result"_sv), wat_name_of_type(statement.type)),
                    compile_expression(statement.iph.condition),
                    append(list(atom("then"_sv)), compile_block(statement.iph.then)),
                    append(list(atom("else"_sv)), compile_block(statement.iph.elze)));
            }
        }
    case Statement_Kind::While:
        // (block
        //  (loop
        //   (br_if 1 (i32.eqz <condition>))
        //   <body>
        //   (br 0)))
        return list(
            atom("block"_sv),
            append(
                list(atom("loop"_sv),
                     list(atom("br_if"_sv), atom(1),
                          list(atom("i32.eqz"_sv), compile_expression(statement.hwile.condition)))),
                compile_block(statement.hwile.body),
                list(list(atom("br"_sv), atom(0)))));

    case Statement_Kind::Assignment:
        return list(atom("set_local"_sv),
                    wat_ident(statement.assignment.var_name),
                    compile_expression(statement.assignment.value));

    case Statement_Kind::Expression:
        return compile_expression(statement.expression);

    case Statement_Kind::Return:
        return list(atom("return"_sv), compile_expression(statement.reeturn.value));
    }

    assert(0 && "Memory corruption?");
    return nullptr;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1f0, %rsp            # imm = 0x1F0
leaq 0x10(%rbp), %rax
movq %rax, -0x128(%rbp)
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rcx
movq %rcx, -0x120(%rbp)
movl (%rax), %eax
movq %rax, -0x118(%rbp)
subq $0x5, %rax
ja 0x8eff
movq -0x118(%rbp), %rax
leaq 0x5dda(%rip), %rcx      # 0xe510
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x128(%rbp), %rax
movq -0x120(%rbp), %rdi
addq $0x8, %rdi
movq 0x8(%rax), %rsi
leaq 0x74fa(%rip), %rdx      # 0xfc56
callq 0xb850
movq -0x128(%rbp), %rax
cmpq $0x0, 0x18(%rax)
jne 0x87ea
movq -0x128(%rbp), %rax
cmpq $0x0, 0x20(%rax)
jne 0x87ea
leaq 0x7485(%rip), %rdi      # 0xfc09
movl $0x4, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x20(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x20(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x130(%rbp)
movq 0x10(%rax), %rsi
callq 0x70d0
movq -0x120(%rbp), %rdi
movq -0x130(%rbp), %rsi
movq %rax, %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x8f1e
movq -0x128(%rbp), %rax
cmpl $0x1, 0x4(%rax)
jne 0x896a
leaq 0x74ba(%rip), %rdi      # 0xfcbc
movl $0x2, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x30(%rbp)
movq %rdx, -0x28(%rbp)
movq -0x30(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x148(%rbp)
movq 0x10(%rax), %rsi
callq 0x70d0
movq %rax, -0x140(%rbp)
leaq 0x7452(%rip), %rdi      # 0xfca9
movl $0x4, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x40(%rbp)
movq %rdx, -0x38(%rbp)
movq -0x40(%rbp), %rsi
movq -0x38(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rsi
callq 0xba10
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x158(%rbp)
movq 0x18(%rax), %rsi
callq 0x8f30
movq -0x158(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb8f0
movq %rax, -0x138(%rbp)
leaq 0x6351(%rip), %rdi      # 0xec22
movl $0x4, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x50(%rbp)
movq %rdx, -0x48(%rbp)
movq -0x50(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rsi
callq 0xba10
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x150(%rbp)
movq 0x20(%rax), %rsi
callq 0x8f30
movq -0x150(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb8f0
movq -0x120(%rbp), %rdi
movq -0x148(%rbp), %rsi
movq -0x140(%rbp), %rdx
movq -0x138(%rbp), %rcx
movq %rax, %r8
callq 0xb890
movq %rax, -0x8(%rbp)
jmp 0x8f1e
leaq 0x734b(%rip), %rdi      # 0xfcbc
movl $0x2, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x60(%rbp)
movq %rdx, -0x58(%rbp)
movq -0x60(%rbp), %rsi
movq -0x58(%rbp), %rdx
callq 0xb5c0
movq %rax, -0x178(%rbp)
leaq 0x65bf(%rip), %rdi      # 0xef64
movl $0x6, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x70(%rbp)
movq %rdx, -0x68(%rbp)
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x190(%rbp)
movl 0x4(%rax), %esi
callq 0x69a0
movq -0x190(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb780
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x170(%rbp)
movq 0x10(%rax), %rsi
callq 0x70d0
movq %rax, -0x168(%rbp)
leaq 0x7279(%rip), %rdi      # 0xfca9
movl $0x4, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x80(%rbp)
movq %rdx, -0x78(%rbp)
movq -0x80(%rbp), %rsi
movq -0x78(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rsi
callq 0xba10
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x188(%rbp)
movq 0x18(%rax), %rsi
callq 0x8f30
movq -0x188(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb8f0
movq %rax, -0x160(%rbp)
leaq 0x6178(%rip), %rdi      # 0xec22
movl $0x4, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x90(%rbp)
movq %rdx, -0x88(%rbp)
movq -0x90(%rbp), %rsi
movq -0x88(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rsi
callq 0xba10
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x180(%rbp)
movq 0x20(%rax), %rsi
callq 0x8f30
movq -0x180(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb8f0
movq -0x120(%rbp), %rdi
movq -0x178(%rbp), %rsi
movq -0x170(%rbp), %rdx
movq -0x168(%rbp), %rcx
movq -0x160(%rbp), %r8
movq %rax, %r9
callq 0xba50
movq %rax, -0x8(%rbp)
jmp 0x8f1e
leaq 0x7151(%rip), %rdi      # 0xfcae
movl $0x5, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0xa0(%rbp)
movq %rdx, -0x98(%rbp)
movq -0xa0(%rbp), %rsi
movq -0x98(%rbp), %rdx
callq 0xb5c0
movq %rax, -0x198(%rbp)
leaq 0x7117(%rip), %rdi      # 0xfcb4
movl $0x4, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0xb0(%rbp)
movq %rdx, -0xa8(%rbp)
movq -0xb0(%rbp), %rsi
movq -0xa8(%rbp), %rdx
callq 0xb5c0
movq %rax, -0x1b8(%rbp)
leaq 0x70dc(%rip), %rdi      # 0xfcb9
movl $0x5, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0xc0(%rbp)
movq %rdx, -0xb8(%rbp)
movq -0xc0(%rbp), %rsi
movq -0xb8(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, -0x1c8(%rbp)
movl $0x1, %esi
callq 0xb7d0
movq %rax, -0x1c0(%rbp)
leaq 0x708a(%rip), %rdi      # 0xfcbf
movl $0x7, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0xd0(%rbp)
movq %rdx, -0xc8(%rbp)
movq -0xd0(%rbp), %rsi
movq -0xc8(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x1d0(%rbp)
movq 0x10(%rax), %rsi
callq 0x70d0
movq -0x1d0(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb780
movq -0x1c8(%rbp), %rsi
movq -0x1c0(%rbp), %rdx
movq -0x120(%rbp), %rdi
movq %rax, %rcx
callq 0xb6d0
movq -0x1b8(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb780
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x1a8(%rbp)
movq 0x18(%rax), %rsi
callq 0x8f30
movq %rax, -0x1a0(%rbp)
leaq 0x6fc7(%rip), %rdi      # 0xfcc7
movl $0x2, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0xe0(%rbp)
movq %rdx, -0xd8(%rbp)
movq -0xe0(%rbp), %rsi
movq -0xd8(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, -0x1b0(%rbp)
xorl %esi, %esi
callq 0xb7d0
movq -0x1b0(%rbp), %rsi
movq -0x120(%rbp), %rdi
movq %rax, %rdx
callq 0xb780
movq -0x120(%rbp), %rdi
movq %rax, %rsi
callq 0xba10
movq -0x1a8(%rbp), %rsi
movq -0x1a0(%rbp), %rdx
movq -0x120(%rbp), %rdi
movq %rax, %rcx
callq 0xbab0
movq -0x120(%rbp), %rdi
movq -0x198(%rbp), %rsi
movq %rax, %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x8f1e
leaq 0x6f1b(%rip), %rdi      # 0xfcca
movl $0x9, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0xf0(%rbp)
movq %rdx, -0xe8(%rbp)
movq -0xf0(%rbp), %rsi
movq -0xe8(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x1e0(%rbp)
movq 0x10(%rax), %rcx
movq %rcx, -0x100(%rbp)
movq 0x18(%rax), %rax
movq %rax, -0xf8(%rbp)
movq -0x100(%rbp), %rsi
movq -0xf8(%rbp), %rdx
callq 0x6920
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x1d8(%rbp)
movq 0x20(%rax), %rsi
callq 0x70d0
movq -0x120(%rbp), %rdi
movq -0x1e0(%rbp), %rsi
movq -0x1d8(%rbp), %rdx
movq %rax, %rcx
callq 0xb6d0
movq %rax, -0x8(%rbp)
jmp 0x8f1e
movq -0x120(%rbp), %rdi
movq -0x128(%rbp), %rax
movq 0x10(%rax), %rsi
callq 0x70d0
movq %rax, -0x8(%rbp)
jmp 0x8f1e
leaq 0x5d97(%rip), %rdi      # 0xec27
movl $0x6, %esi
callq 0x12e0
movq -0x120(%rbp), %rdi
movq %rax, -0x110(%rbp)
movq %rdx, -0x108(%rbp)
movq -0x110(%rbp), %rsi
movq -0x108(%rbp), %rdx
callq 0xb5c0
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movq -0x128(%rbp), %rax
movq %rcx, -0x1e8(%rbp)
movq 0x10(%rax), %rsi
callq 0x70d0
movq -0x120(%rbp), %rdi
movq -0x1e8(%rbp), %rsi
movq %rax, %rdx
callq 0xb780
movq %rax, -0x8(%rbp)
jmp 0x8f1e
leaq 0x6219(%rip), %rdi      # 0xf11f
leaq 0x5fab(%rip), %rsi      # 0xeeb8
movl $0x1ed, %edx            # imm = 0x1ED
leaq 0x6dbb(%rip), %rcx      # 0xfcd4
callq 0x10c0
movq -0x8(%rbp), %rax
addq $0x1f0, %rsp            # imm = 0x1F0
popq %rbp
retq
nopl (%rax,%rax)