// File: /workspace/github_c_makefile_star2_O0/adamjedlicka[P]blu/src/vm/compiler/compiler.c
// Function: forStatement
static void forStatement(bluCompiler* compiler) {
	beginScope(compiler);

	// The initialization clause.
	if (match(compiler, TOKEN_VAR)) {
		varDeclaration(compiler);
	} else if (match(compiler, TOKEN_SEMICOLON)) {
		// No initializer;
	} else {
		expressionStatement(compiler);
	}

	int32_t loopStart = compiler->function->chunk.code.count;

	// The exit condition.
	int32_t exitJump = 0;
	if (!match(compiler, TOKEN_SEMICOLON)) {
		expression(compiler);
		consume(compiler, TOKEN_SEMICOLON, "Expect ';' after loop condition.");

		// Jump out of the loop if the condition is false.
		exitJump = emitJump(compiler, OP_JUMP_IF_FALSE);
		emitByte(compiler, OP_POP); // Condition.
	}

	// Increment ste.
	if (!match(compiler, TOKEN_LEFT_BRACE)) {
		// We don't want to execute the incrment before the body, so jump over it.
		int32_t bodyJump = emitJump(compiler, OP_JUMP);

		int32_t incrementStart = compiler->function->chunk.code.count;
		expression(compiler);
		emitByte(compiler, OP_POP);

		// After the increment, start the whole loop over.
		emitLoop(compiler, loopStart);

		// At the end of the body, we want to jump to the increment, not the top of the loop.
		loopStart = incrementStart;

		patchJump(compiler, bodyJump);
	}

	// Compile the body.
	if (match(compiler, TOKEN_COLON)) {
		statement(compiler);
	} else {
		consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' after for clause.");
		beginScope(compiler);
		block(compiler);
		endScope(compiler);
	}

	// Jump back to the begining (or the increment).
	emitLoop(compiler, loopStart);

	if (exitJump != 0) {
		patchJump(compiler, exitJump);
		emitByte(compiler, OP_POP); // Condition;
	}

	endScope(compiler);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x3ad0
movq -0x8(%rbp), %rdi
movl $0x2d, %esi
callq 0x2c40
testb $0x1, %al
jne 0x4a79
jmp 0x4a84
movq -0x8(%rbp), %rdi
callq 0x3ff0
jmp 0x4aa5
movq -0x8(%rbp), %rdi
movl $0xb, %esi
callq 0x2c40
testb $0x1, %al
jne 0x4a98
jmp 0x4a9a
jmp 0x4aa3
movq -0x8(%rbp), %rdi
callq 0x4df0
jmp 0x4aa5
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movl 0x40(%rax), %eax
movl %eax, -0xc(%rbp)
movl $0x0, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movl $0xb, %esi
callq 0x2c40
testb $0x1, %al
jne 0x4b09
movq -0x8(%rbp), %rdi
callq 0x3450
movq -0x8(%rbp), %rdi
movl $0xb, %esi
leaq 0x9b26(%rip), %rdx      # 0xe60b
callq 0x3200
movq -0x8(%rbp), %rdi
movl $0x16, %esi
callq 0x3ee0
movl %eax, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movl $0x5, %esi
callq 0x32b0
movq -0x8(%rbp), %rdi
movl $0x5, %esi
callq 0x2c40
testb $0x1, %al
jne 0x4b6f
movq -0x8(%rbp), %rdi
movl $0x15, %esi
callq 0x3ee0
movl %eax, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movl 0x40(%rax), %eax
movl %eax, -0x18(%rbp)
movq -0x8(%rbp), %rdi
callq 0x3450
movq -0x8(%rbp), %rdi
movl $0x5, %esi
callq 0x32b0
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x4e30
movl -0x18(%rbp), %eax
movl %eax, -0xc(%rbp)
movq -0x8(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x3f20
movq -0x8(%rbp), %rdi
movl $0x2, %esi
callq 0x2c40
testb $0x1, %al
jne 0x4b83
jmp 0x4b8e
movq -0x8(%rbp), %rdi
callq 0x4500
jmp 0x4bbe
movq -0x8(%rbp), %rdi
movl $0x5, %esi
leaq 0x9a8e(%rip), %rdx      # 0xe62c
callq 0x3200
movq -0x8(%rbp), %rdi
callq 0x3ad0
movq -0x8(%rbp), %rdi
callq 0x3af0
movq -0x8(%rbp), %rdi
callq 0x3b60
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x4e30
cmpl $0x0, -0x10(%rbp)
je 0x4bea
movq -0x8(%rbp), %rdi
movl -0x10(%rbp), %esi
callq 0x3f20
movq -0x8(%rbp), %rdi
movl $0x5, %esi
callq 0x32b0
movq -0x8(%rbp), %rdi
callq 0x3b60
addq $0x20, %rsp
popq %rbp
retq
nopl (%rax)