while statements (ch23)
This commit is contained in:
		
							
								
								
									
										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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user