commit 4a13f042541401587373f41eafdc6675f6fbc411
parent a15a212daf2301d4e216adb84ddc078a489f4882
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date: Thu, 1 Aug 2024 21:43:38 +0200
for
Diffstat:
1 file changed, 49 insertions(+), 0 deletions(-)
diff --git a/zlox/src/compiler.zig b/zlox/src/compiler.zig
@@ -515,6 +515,8 @@ pub fn Compiler(size: comptime_int) type {
self.ifStatement();
} else if (self.match(Token.WHILE)) {
self.whileStatement();
+ } else if (self.match(Token.FOR)) {
+ self.forStatement();
} else if (self.match(Token.LEFT_BRACE)) {
self.beginScope();
self.block();
@@ -540,6 +542,53 @@ pub fn Compiler(size: comptime_int) type {
self.emitOP(OP.POP);
}
+ fn forStatement(self: *Self) void {
+ self.beginScope();
+ self.consume(Token.LEFT_PAREN, "Expect '(' after 'for'.");
+
+ if (self.match(Token.SEMICOLON)) {
+ // Empty initializer
+ } else if (self.match(Token.VAR)) {
+ self.varDeclaration();
+ } else if (self.match(Token.CON)) {
+ self.conDeclaration();
+ } else {
+ self.expressionStatement();
+ }
+
+ var loopStart = self.currentChunk().code.len;
+
+ var exitJump: ?usize = null;
+ if (!self.match(Token.SEMICOLON)) {
+ self.expression();
+ self.consume(Token.SEMICOLON, "Expect ';' after condition clause");
+
+ exitJump = self.emitJump(OP.JUMP_IF_FALSE);
+ self.emitOP(OP.POP);
+ }
+
+ if (!self.match(Token.RIGHT_PAREN)) {
+ const bodyJump = self.emitJump(OP.JUMP);
+ const incrementStart = self.currentChunk().code.len;
+ self.expression();
+ self.emitOP(OP.POP);
+ self.consume(Token.RIGHT_PAREN, "Expect ')' after increment clause");
+
+ self.emitLoop(loopStart);
+ loopStart = incrementStart;
+ self.patchJump(bodyJump);
+ }
+
+ self.statement();
+ self.emitLoop(loopStart);
+
+ if (exitJump) |jump| {
+ self.patchJump(jump);
+ self.emitOP(OP.POP);
+ }
+ self.endScope();
+ }
+
fn emitLoop(self: *Self, start: usize) void {
self.emitOP(OP.LOOP);
const offset = self.currentChunk().code.len - start + 2;