// File: /workspace/github_c_makefile_star2_O2/mahrr[P]raven/src/compiler.c
// Function: match
static void match(Parser *parser) {
    Debug_Log(parser);

    expression(parser); // Value
    consume(parser, TOKEN_DO, "expect 'do' after match value");

    int cases_exit[MATCH_LIMIT];
    int cases_count = 0;

    do {
        if (cases_count == MATCH_LIMIT) {
            error_limit(parser, "match cases", MATCH_LIMIT);
            break;
        }

        begin_scope(parser);

        Pattern_Context context = {0};
        pattern(parser, &context, false);
        consume(parser, TOKEN_ARROW, "expect '->' after pattern");

        // Match succeeded.
        expression(parser);

        // Save the expression value in X and rewind the stack.
        emit_byte(parser, OP_POP_X);
        unwind_stack(parser, parser->context->scope_depth);
        emit_byte(parser, OP_PUSH_X);
        cases_exit[cases_count++] = emit_jump(parser, OP_JMP);

        // Match failed.
        for (int i = 0; i < context.cases_count; ++i) {
            patch_jump(parser, context.cases_next[i]);
        }

        // Discard the case scope.
        parser->context->scope_depth--;
    } while (consume_if(parser, TOKEN_COMMA));

    // If all patterns didn't match.
    emit_bytes(parser, OP_POP, OP_PUSH_NIL);

    for (int i = 0; i < cases_count; i++) {
        patch_jump(parser, cases_exit[i]);
    }

    consume(parser, TOKEN_END, "expect 'end' after match cases");

    Debug_Exit(parser);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x898, %rsp            # imm = 0x898
movq %rdi, %rbx
callq 0x5a96
leaq 0x373b(%rip), %rdx      # 0x9a22
pushq $0x22
popq %rsi
movq %rbx, %rdi
callq 0x5bf2
xorl %r12d, %r12d
leaq 0x8(%rsp), %r14
pushq $0x1e
popq %r15
pushq $0x25
popq %rbp
cmpq $0x200, %r12            # imm = 0x200
je 0x63cf
movq 0x8(%rbx), %rax
incl 0x221c(%rax)
movl $0x88, %edx
movq %r14, %rdi
xorl %esi, %esi
callq 0x2100
movq %rbx, %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x6c51
movq %rbx, %rdi
pushq $0x24
popq %rsi
leaq 0x36ff(%rip), %rdx      # 0x9a40
callq 0x5bf2
movq %rbx, %rdi
callq 0x5a96
movq %rbx, %rdi
pushq $0x5
popq %rsi
callq 0x5a9e
movq 0x8(%rbx), %rax
movl 0x221c(%rax), %esi
movq %rbx, %rdi
callq 0x5f95
movq %rbx, %rdi
pushq $0x4
popq %rsi
callq 0x5a9e
movq %rbx, %rdi
movl %r15d, %esi
callq 0x6b8f
movl %eax, 0x90(%rsp,%r12,4)
xorl %r13d, %r13d
movslq 0x88(%rsp), %rax
cmpq %rax, %r13
jge 0x63ab
movl 0x8(%rsp,%r13,4), %esi
movq %rbx, %rdi
callq 0x6bba
incq %r13
jmp 0x638c
incq %r12
movq 0x8(%rbx), %rax
decl 0x221c(%rax)
movq %rbx, %rdi
movl %ebp, %esi
callq 0x5876
testb %al, %al
jne 0x6301
movl %r12d, %r14d
jmp 0x63e9
leaq 0x3697(%rip), %rsi      # 0x9a6d
movq %rbx, %rdi
movl $0x200, %edx            # imm = 0x200
callq 0x5d22
movl $0x200, %r14d           # imm = 0x200
pushq $0x7
popq %rsi
pushq $0x2
popq %rdx
movq %rbx, %rdi
callq 0x5d5f
xorl %r15d, %r15d
cmpq %r15, %r14
je 0x6414
movl 0x90(%rsp,%r15,4), %esi
movq %rbx, %rdi
callq 0x6bba
incq %r15
jmp 0x63fa
leaq 0x363f(%rip), %rdx      # 0x9a5a
pushq $0x23
popq %rsi
movq %rbx, %rdi
callq 0x5bf2
addq $0x898, %rsp            # imm = 0x898
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq