refactor: using current_chunk()

This commit is contained in:
Patrick MARIE 2024-08-28 09:23:33 +02:00
parent f7c10c13bb
commit 0850198784
3 changed files with 73 additions and 18 deletions

View File

@ -62,6 +62,10 @@ const Parser = struct {
};
}
inline fn current_chunk(self: *Parser) *Chunk {
return self.chunk;
}
fn advance(self: *Parser) void {
self.previous = self.current;
@ -117,7 +121,7 @@ const Parser = struct {
}
fn emit_byte(self: *Parser, byte: u8) ParsingError!void {
self.chunk.write(byte, self.previous.?.line) catch |err| {
self.current_chunk().write(byte, self.previous.?.line) catch |err| {
switch (err) {
error.OutOfMemory => return ParsingError.OutOfMemory,
}
@ -135,7 +139,7 @@ const Parser = struct {
fn end_parser(self: *Parser) !void {
if (!self.had_error and self.vm.has_tracing()) {
self.chunk.dissassemble("code");
self.current_chunk().dissassemble("code");
}
try self.emit_return();
}
@ -162,7 +166,7 @@ const Parser = struct {
}
fn make_constant(self: *Parser, value: Value) !u8 {
const constant = try self.chunk.add_constant(value);
const constant = try self.current_chunk().add_constant(value);
if (constant > constants.UINT8_MAX) {
self.error_msg("Too many constants in one chunk.");
return 0;
@ -585,11 +589,11 @@ const Parser = struct {
try self.emit_byte(0xff);
try self.emit_byte(0xff);
return self.chunk.count - 2;
return self.current_chunk().count - 2;
}
fn patch_jump(self: *Parser, offset: usize) void {
const jump = self.chunk.count - offset - 2;
const jump = self.current_chunk().count - offset - 2;
if (jump > constants.UINT16_MAX) {
self.error_msg("Too much code to jump over.");
@ -598,8 +602,8 @@ const Parser = struct {
const b1 = (jump >> 8) & 0xff;
const b0 = jump & 0xff;
self.chunk.code[offset] = @intCast(b1);
self.chunk.code[offset + 1] = @intCast(b0);
self.current_chunk().code[offset] = @intCast(b1);
self.current_chunk().code[offset + 1] = @intCast(b0);
}
fn and_(self: *Parser, can_assign: bool) ParsingError!void {
@ -624,7 +628,7 @@ const Parser = struct {
}
fn while_statement(self: *Parser) ParsingError!void {
const loop_start = self.chunk.count;
const loop_start = self.current_chunk().count;
self.consume(TokenType.LEFT_PAREN, "Expect '(' after 'while'.");
try self.expression();
self.consume(TokenType.RIGHT_PAREN, "Expect ')' after condition.");
@ -640,7 +644,7 @@ const Parser = struct {
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;
const offset = self.current_chunk().count - loop_start + 2;
if (offset > constants.UINT16_MAX) {
self.error_msg("Loop body too large.");
}
@ -661,7 +665,7 @@ const Parser = struct {
try self.expression_statement();
}
var loop_start = self.chunk.count;
var loop_start = self.current_chunk().count;
var exit_jump: ?usize = null;
@ -676,7 +680,7 @@ const Parser = struct {
if (!self.match(TokenType.RIGHT_PAREN)) {
const body_jump = try self.emit_jump(@intFromEnum(OpCode.OP_JUMP));
const increment_start = self.chunk.count;
const increment_start = self.current_chunk().count;
try self.expression();
try self.emit_byte(@intFromEnum(OpCode.OP_POP));
self.consume(TokenType.RIGHT_PAREN, "Expect ')' after for clauses.");

View File

@ -2,10 +2,13 @@ const std = @import("std");
const debug = std.debug;
const Allocator = std.mem.Allocator;
const Chunk = @import("./chunk.zig").Chunk;
const compute_hash = @import("./utils.zig").compute_hash;
pub const ObjType = enum {
String,
Function,
};
pub const Obj = struct {
@ -13,8 +16,8 @@ pub const Obj = struct {
allocator: std.mem.Allocator,
pub const String = struct {
chars: []const u8,
obj: Obj,
chars: []const u8,
hash: u32,
pub fn new(allocator: std.mem.Allocator, chars: []const u8) *String {
@ -39,6 +42,33 @@ pub const Obj = struct {
}
};
pub const Function = struct {
obj: Obj,
arity: usize,
chunk: *Chunk,
name: *Obj.String,
pub fn new(allocator: std.mem.Allocator) *Function {
const obj = Obj{
.kind = ObjType.Function,
.allocator = allocator,
};
const function_obj = allocator.create(Function) catch unreachable;
function_obj.obj = obj;
function_obj.arity = 0;
function_obj.chunk = Chunk.new(allocator);
return function_obj;
}
pub fn destroy(self: *Function) void {
const allocator = self.obj.allocator;
self.chunk.deinit();
allocator.destroy(self);
}
};
pub fn is_type(self: *Obj, kind: ObjType) bool {
return self.kind == kind;
}
@ -47,12 +77,20 @@ pub const Obj = struct {
return self.is_type(ObjType.String);
}
pub fn is_function(self: *Obj) bool {
return self.is_function(ObjType.Function);
}
pub fn print(self: *Obj) void {
switch (self.kind) {
ObjType.String => {
const obj = self.as_string();
debug.print("{s}", .{obj.chars});
},
ObjType.Function => {
const obj = self.as_function();
debug.print("<fn {s}>", .{obj.name.chars});
},
}
}
@ -62,6 +100,10 @@ pub const Obj = struct {
const obj: *String = @fieldParentPtr("obj", self);
obj.destroy();
},
ObjType.Function => {
const obj: *Function = @fieldParentPtr("obj", self);
obj.destroy();
},
}
}
@ -69,4 +111,9 @@ pub const Obj = struct {
std.debug.assert(self.kind == ObjType.String);
return @fieldParentPtr("obj", self);
}
pub fn as_function(self: *Obj) *Function {
std.debug.assert(self.kind == ObjType.Function);
return @fieldParentPtr("obj", self);
}
};

View File

@ -61,6 +61,10 @@ pub const VM = struct {
self.references.deinit();
}
inline fn current_chunk(self: *VM) *Chunk {
return self.chunk.?;
}
pub fn set_trace(self: *VM, tracing: bool) void {
self.tracing = tracing;
}
@ -96,7 +100,7 @@ pub const VM = struct {
}
debug.print("\n", .{});
}
_ = self.chunk.?.dissassemble_instruction(self.ip.?);
_ = self.current_chunk().dissassemble_instruction(self.ip.?);
}
const instruction = self.read_byte();
@ -209,7 +213,7 @@ pub const VM = struct {
// XXX In the book, we're using a ptr to data directly, to avoid dereferencing to a given offset
// How to do that in Zig?
pub fn read_byte(self: *VM) u8 {
const ret = self.chunk.?.code[self.ip.?];
const ret = self.current_chunk().code[self.ip.?];
self.ip.? += 1;
return ret;
@ -218,11 +222,11 @@ pub const VM = struct {
pub fn read_short(self: *VM) u16 {
self.ip.? += 2;
return (@as(u16, self.chunk.?.code[self.ip.? - 2]) << 8) | (@as(u16, self.chunk.?.code[self.ip.? - 1]));
return (@as(u16, self.current_chunk().code[self.ip.? - 2]) << 8) | (@as(u16, self.current_chunk().code[self.ip.? - 1]));
}
pub fn read_constant(self: *VM) Value {
return self.chunk.?.constants.values[read_byte(self)];
return self.current_chunk().constants.values[read_byte(self)];
}
pub fn push(self: *VM, value: Value) !void {
@ -269,7 +273,7 @@ pub const VM = struct {
const b = self.pop().as_cstring();
const a = self.pop().as_cstring();
const concat_str = try std.mem.concat(self.chunk.?.allocator, u8, &.{ a, b });
const concat_str = try std.mem.concat(self.current_chunk().allocator, u8, &.{ a, b });
var string_obj = self.take_string(concat_str);
@ -284,7 +288,7 @@ pub const VM = struct {
pub fn runtime_error(self: *VM, err_msg: []const u8) void {
const instruction = self.ip.?;
const line = self.chunk.?.lines[instruction];
const line = self.current_chunk().lines[instruction];
debug.print("err: {s}\n", .{err_msg});
debug.print("[line {d}] in script\n", .{line});