// File: /workspace/github_c_makefile_star2_O0/gaultier[P]lox-c/parse.c
// Function: for_stmt
static void for_stmt(Parser* parser, Vm* vm) {
    begin_scope(parser);
    expect(parser, TOKEN_LEFT_PAREN, "Expect `(` after `for`");

    if (match(parser, TOKEN_VAR)) {
        var_declaration(parser, vm);
    } else if (match(parser, TOKEN_SEMICOLON)) {
    } else {
        expr_stmt(parser, vm);
    }

    size_t loop_start = buf_size(parser->compiler->fn->chunk.opcodes);

    intmax_t exit_jump = -1;
    if (!match(parser, TOKEN_SEMICOLON)) {
        expression(parser, vm);
        expect(parser, TOKEN_SEMICOLON,
               "Expect `;` after for-loop stop condition");

        exit_jump = jump_emit(parser, OP_JUMP_IF_FALSE);
        emit_byte(parser, OP_POP);
    }

    if (!match(parser, TOKEN_RIGHT_PAREN)) {
        const intmax_t body_jump = jump_emit(parser, OP_JUMP);

        const size_t increment_start =
            buf_size(parser->compiler->fn->chunk.opcodes);

        expression(parser, vm);
        emit_byte(parser, OP_POP);

        expect(parser, TOKEN_RIGHT_PAREN,
               "Expect `)` after for-loop stop condition");

        emit_loop(parser, loop_start);
        loop_start = increment_start;
        jump_patch(parser, body_jump);
    }

    statement(parser, vm);

    emit_loop(parser, loop_start);

    if (exit_jump != -1) {
        jump_patch(parser, exit_jump);
        emit_byte(parser, OP_POP);
    }

    end_scope(parser);
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
movq %rsi, 0x38(%rsp)
movq 0x40(%rsp), %rdi
callq 0x5890
movq 0x40(%rsp), %rdi
movl $0x1, %esi
leaq 0x5ebd(%rip), %rdx      # 0xbc16
callq 0x3980
movq 0x40(%rsp), %rdi
movl $0x25, %esi
callq 0x2fc0
testb $0x1, %al
jne 0x5d73
jmp 0x5d84
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x31f0
jmp 0x5dac
movq 0x40(%rsp), %rdi
movl $0x9, %esi
callq 0x2fc0
testb $0x1, %al
jne 0x5d99
jmp 0x5d9b
jmp 0x5daa
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x6030
jmp 0x5dac
movq 0x40(%rsp), %rax
movq 0x80(%rax), %rax
movq 0x3010(%rax), %rax
cmpq $0x0, 0x18(%rax)
je 0x5de8
movq 0x40(%rsp), %rax
movq 0x80(%rax), %rax
movq 0x3010(%rax), %rax
movq 0x18(%rax), %rax
movq -0x8(%rax), %rax
movq %rax, 0x10(%rsp)
jmp 0x5df1
xorl %eax, %eax
movq %rax, 0x10(%rsp)
jmp 0x5df1
movq 0x10(%rsp), %rax
movq %rax, 0x30(%rsp)
movq $-0x1, 0x28(%rsp)
movq 0x40(%rsp), %rdi
movl $0x9, %esi
callq 0x2fc0
testb $0x1, %al
jne 0x5e5f
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x3500
movq 0x40(%rsp), %rdi
movl $0x9, %esi
leaq 0x5df6(%rip), %rdx      # 0xbc2d
callq 0x3980
movq 0x40(%rsp), %rdi
movl $0x15, %esi
callq 0x5560
movq %rax, 0x28(%rsp)
movq 0x40(%rsp), %rdi
movl $0xf, %esi
callq 0x3530
movq 0x40(%rsp), %rdi
movl $0x2, %esi
callq 0x2fc0
testb $0x1, %al
jne 0x5f35
movq 0x40(%rsp), %rdi
movl $0x16, %esi
callq 0x5560
movq %rax, 0x20(%rsp)
movq 0x40(%rsp), %rax
movq 0x80(%rax), %rax
movq 0x3010(%rax), %rax
cmpq $0x0, 0x18(%rax)
je 0x5ec6
movq 0x40(%rsp), %rax
movq 0x80(%rax), %rax
movq 0x3010(%rax), %rax
movq 0x18(%rax), %rax
movq -0x8(%rax), %rax
movq %rax, 0x8(%rsp)
jmp 0x5ecf
xorl %eax, %eax
movq %rax, 0x8(%rsp)
jmp 0x5ecf
movq 0x8(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x3500
movq 0x40(%rsp), %rdi
movl $0xf, %esi
callq 0x3530
movq 0x40(%rsp), %rdi
movl $0x2, %esi
leaq 0x5d4e(%rip), %rdx      # 0xbc56
callq 0x3980
movq 0x40(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x6080
movq 0x18(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x40(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x55f0
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x32e0
movq 0x40(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x6080
cmpq $-0x1, 0x28(%rsp)
je 0x5f79
movq 0x40(%rsp), %rdi
movq 0x28(%rsp), %rsi
callq 0x55f0
movq 0x40(%rsp), %rdi
movl $0xf, %esi
callq 0x3530
movq 0x40(%rsp), %rdi
callq 0x5a70
addq $0x48, %rsp
retq
nopl (%rax,%rax)