while statements (ch23)
This commit is contained in:
parent
9de028d09c
commit
d67c99ffe5
6
samples/ch23_while.lox
Normal file
6
samples/ch23_while.lox
Normal file
@ -0,0 +1,6 @@
|
||||
var i = 0;
|
||||
|
||||
while(i < 10) {
|
||||
print i;
|
||||
i = i + 1;
|
||||
}
|
@ -101,6 +101,7 @@ pub const Chunk = struct {
|
||||
@intFromEnum(OpCode.OP_SET_LOCAL) => return utils.byte_instruction("OP_SET_LOCAL", self, offset),
|
||||
@intFromEnum(OpCode.OP_JUMP) => return utils.jump_instruction("OP_JUMP", 1, self, offset),
|
||||
@intFromEnum(OpCode.OP_JUMP_IF_FALSE) => return utils.jump_instruction("OP_JUMP_IF_FALSE", 1, self, offset),
|
||||
@intFromEnum(OpCode.OP_LOOP) => return utils.jump_instruction("OP_LOOP", -1, self, offset),
|
||||
else => {
|
||||
debug.print("unknown opcode {d}\n", .{instruction});
|
||||
return offset + 1;
|
||||
|
@ -362,6 +362,8 @@ const Parser = struct {
|
||||
try self.print_statement();
|
||||
} else if (self.match(TokenType.IF)) {
|
||||
try self.if_statement();
|
||||
} else if (self.match(TokenType.WHILE)) {
|
||||
try self.while_statement();
|
||||
} else if (self.match(TokenType.LEFT_BRACE)) {
|
||||
self.begin_scope();
|
||||
try self.block();
|
||||
@ -616,6 +618,32 @@ const Parser = struct {
|
||||
try self.parse_precedence(Precedence.Or);
|
||||
self.patch_jump(end_jump);
|
||||
}
|
||||
|
||||
fn while_statement(self: *Parser) ParsingError!void {
|
||||
const loop_start = self.chunk.count;
|
||||
self.consume(TokenType.LEFT_PAREN, "Expect '(' after 'while'.");
|
||||
try self.expression();
|
||||
self.consume(TokenType.RIGHT_PAREN, "Expect ')' after condition.");
|
||||
|
||||
const exit_jump = try self.emit_jump(@intFromEnum(OpCode.OP_JUMP_IF_FALSE));
|
||||
try self.emit_byte(@intFromEnum(OpCode.OP_POP));
|
||||
try self.statement();
|
||||
try self.emit_loop(loop_start);
|
||||
self.patch_jump(exit_jump);
|
||||
try self.emit_byte(@intFromEnum(OpCode.OP_POP));
|
||||
}
|
||||
|
||||
fn emit_loop(self: *Parser, loop_start: usize) ParsingError!void {
|
||||
try self.emit_byte(@intFromEnum(OpCode.OP_LOOP));
|
||||
|
||||
const offset = self.chunk.count - loop_start + 2;
|
||||
if (offset > 65536) {
|
||||
self.error_msg("Loop body too large.");
|
||||
}
|
||||
|
||||
try self.emit_byte(@intCast((offset >> 8) & 0xff));
|
||||
try self.emit_byte(@intCast(offset & 0xff));
|
||||
}
|
||||
};
|
||||
|
||||
const Compiler = struct {
|
||||
|
@ -21,5 +21,6 @@ pub const OpCode = enum(u8) {
|
||||
OP_PRINT,
|
||||
OP_JUMP,
|
||||
OP_JUMP_IF_FALSE,
|
||||
OP_LOOP,
|
||||
OP_RETURN,
|
||||
};
|
||||
|
@ -192,6 +192,10 @@ pub const VM = struct {
|
||||
self.ip.? += offset;
|
||||
}
|
||||
},
|
||||
@intFromEnum(OpCode.OP_LOOP) => {
|
||||
const offset = self.read_short();
|
||||
self.ip.? -= offset;
|
||||
},
|
||||
else => {
|
||||
debug.print("Invalid instruction: {d}\n", .{instruction});
|
||||
return InterpretResult.RUNTIME_ERROR;
|
||||
|
Loading…
Reference in New Issue
Block a user