for statements (ch23)
This commit is contained in:
parent
d67c99ffe5
commit
95c4e44dbb
@ -13,7 +13,7 @@ While reading [Crafting Interpreters](https://craftinginterpreters.com/), after
|
||||
- [x] 20 - Hash Tables
|
||||
- [x] 21 - Global Variables
|
||||
- [x] 22 - Local Variables
|
||||
- [ ] 23 - Jumping Back and Forth
|
||||
- [x] 23 - Jumping Back and Forth
|
||||
- [ ] 24 - Calls and Functions
|
||||
- [ ] 25 - Closures
|
||||
- [ ] 26 - Garbage Collection
|
||||
|
3
samples/ch23_for.lox
Normal file
3
samples/ch23_for.lox
Normal file
@ -0,0 +1,3 @@
|
||||
for(var i = 0; i < 10; i = i + 1) {
|
||||
print i;
|
||||
}
|
@ -360,6 +360,8 @@ const Parser = struct {
|
||||
fn statement(self: *Parser) ParsingError!void {
|
||||
if (self.match(TokenType.PRINT)) {
|
||||
try self.print_statement();
|
||||
} else if (self.match(TokenType.FOR)) {
|
||||
try self.for_statement();
|
||||
} else if (self.match(TokenType.IF)) {
|
||||
try self.if_statement();
|
||||
} 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 & 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user