for statements (ch23)

This commit is contained in:
Patrick MARIE 2024-08-27 15:13:21 +02:00
parent d67c99ffe5
commit 95c4e44dbb
3 changed files with 54 additions and 1 deletions

View File

@ -13,7 +13,7 @@ While reading [Crafting Interpreters](https://craftinginterpreters.com/), after
- [x] 20 - Hash Tables - [x] 20 - Hash Tables
- [x] 21 - Global Variables - [x] 21 - Global Variables
- [x] 22 - Local Variables - [x] 22 - Local Variables
- [ ] 23 - Jumping Back and Forth - [x] 23 - Jumping Back and Forth
- [ ] 24 - Calls and Functions - [ ] 24 - Calls and Functions
- [ ] 25 - Closures - [ ] 25 - Closures
- [ ] 26 - Garbage Collection - [ ] 26 - Garbage Collection

3
samples/ch23_for.lox Normal file
View File

@ -0,0 +1,3 @@
for(var i = 0; i < 10; i = i + 1) {
print i;
}

View File

@ -360,6 +360,8 @@ const Parser = struct {
fn statement(self: *Parser) ParsingError!void { fn statement(self: *Parser) ParsingError!void {
if (self.match(TokenType.PRINT)) { if (self.match(TokenType.PRINT)) {
try self.print_statement(); try self.print_statement();
} else if (self.match(TokenType.FOR)) {
try self.for_statement();
} else if (self.match(TokenType.IF)) { } else if (self.match(TokenType.IF)) {
try self.if_statement(); try self.if_statement();
} else if (self.match(TokenType.WHILE)) { } else if (self.match(TokenType.WHILE)) {
@ -644,6 +646,54 @@ const Parser = struct {
try self.emit_byte(@intCast((offset >> 8) & 0xff)); try self.emit_byte(@intCast((offset >> 8) & 0xff));
try self.emit_byte(@intCast(offset & 0xff)); try self.emit_byte(@intCast(offset & 0xff));
} }
fn for_statement(self: *Parser) ParsingError!void {
self.begin_scope();
self.consume(TokenType.LEFT_PAREN, "Expect '(' after 'for'.");
if (self.match(TokenType.SEMICOLON)) {
// No initializer
} else if (self.match(TokenType.VAR)) {
try self.var_declaration();
} else {
try self.expression_statement();
}
var loop_start = self.chunk.count;
var exit_jump: ?usize = null;
if (!self.match(TokenType.SEMICOLON)) {
try self.expression();
self.consume(TokenType.SEMICOLON, "Expect ';' after loop condition.");
// Jump out of the loop if the condition is false.
exit_jump = try self.emit_jump(@intFromEnum(OpCode.OP_JUMP_IF_FALSE));
_ = try self.emit_byte(@intFromEnum(OpCode.OP_POP)); // Condition
}
if (!self.match(TokenType.RIGHT_PAREN)) {
const body_jump = try self.emit_jump(@intFromEnum(OpCode.OP_JUMP));
const increment_start = self.chunk.count;
try self.expression();
try self.emit_byte(@intFromEnum(OpCode.OP_POP));
self.consume(TokenType.RIGHT_PAREN, "Expect ')' after for clauses.");
try self.emit_loop(loop_start);
loop_start = increment_start;
self.patch_jump(body_jump);
}
try self.statement();
try self.emit_loop(loop_start);
if (exit_jump != null) {
self.patch_jump(exit_jump.?);
try self.emit_byte(@intFromEnum(OpCode.OP_POP));
}
try self.end_scope();
}
}; };
const Compiler = struct { const Compiler = struct {