diff --git a/src/main.zig b/src/main.zig index 2524f58..baabf78 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,18 +2,25 @@ const std = @import("std"); const debug = std.debug; const Allocator = std.mem.Allocator; -const OpCode = enum(u8) { OP_RETURN }; +const utils = @import("./utils.zig"); +const values = @import("./values.zig"); +const Value = values.Value; +const ValueArray = values.ValueArray; + +const OpCode = enum(u8) { OP_CONSTANT, OP_RETURN }; const Chunk = struct { count: usize, capacity: usize, code: []u8, + constants: ValueArray, pub fn new() Chunk { return Chunk{ .count = 0, .capacity = 0, .code = &.{}, + .constants = ValueArray.new(), }; } @@ -23,12 +30,13 @@ const Chunk = struct { self.count = 0; self.capacity = 0; self.code = &.{}; + self.constants = ValueArray.new(); } pub fn write(self: *Chunk, allocator: Allocator, byte: u8) !void { if (self.capacity < self.count + 1) { const old_capacity = self.capacity; - self.capacity = grow_capacity(old_capacity); + self.capacity = utils.grow_capacity(old_capacity); self.code = try allocator.realloc(self.code, self.capacity); } @@ -43,9 +51,10 @@ const Chunk = struct { pub fn dissassemble(self: Chunk, name: []const u8) void { debug.print("== {s} ==\n", .{name}); - for (0..self.count) |idx| { - const offset = self.dissassemble_instruction(idx); - _ = offset; + var offset: usize = 0; + + while (offset < self.count) { + offset += self.dissassemble_instruction(offset); } } @@ -56,6 +65,7 @@ const Chunk = struct { switch (instruction) { @intFromEnum(OpCode.OP_RETURN) => return simple_instruction("OP_RETURN", offset), + @intFromEnum(OpCode.OP_CONSTANT) => return constant_instruction("OP_CONSTANT", self, offset), else => { debug.print("unknown opcode {d}\n", .{instruction}); return offset + 1; @@ -64,23 +74,31 @@ const Chunk = struct { } pub fn deinit(self: *Chunk, allocator: Allocator) void { + self.constants.free(allocator); + if (self.capacity > 0) { allocator.free(self.code); } } + + pub fn add_constant(self: *Chunk, allocator: Allocator, value: Value) !usize { + try self.constants.write(allocator, value); + return self.constants.count - 1; + } }; pub fn simple_instruction(opcode_name: []const u8, offset: usize) usize { - debug.print("{s}\n", .{opcode_name}); + debug.print("{s:16}\n", .{opcode_name}); return offset + 1; } -pub fn grow_capacity(capacity: usize) usize { - if (capacity < 8) { - return 8; - } - return capacity * 2; +pub fn constant_instruction(opcode_name: []const u8, chunk: Chunk, offset: usize) usize { + const constant = chunk.code[offset + 1]; + debug.print("{s:16} {d:4} ", .{ opcode_name, constant }); + values.print_value(chunk.constants.values[constant]); + debug.print("\n", .{}); + return offset + 2; } pub fn main() !void { @@ -92,6 +110,10 @@ pub fn main() !void { try chunk.init(allocator); try chunk.write(allocator, @intFromEnum(OpCode.OP_RETURN)); + const constant = try chunk.add_constant(allocator, 1.2); + try chunk.write(allocator, @intFromEnum(OpCode.OP_CONSTANT)); + try chunk.write(allocator, @intCast(constant)); + chunk.dissassemble("test chunk"); chunk.deinit(allocator); diff --git a/src/utils.zig b/src/utils.zig new file mode 100644 index 0000000..bd758bc --- /dev/null +++ b/src/utils.zig @@ -0,0 +1,6 @@ +pub fn grow_capacity(capacity: usize) usize { + if (capacity < 8) { + return 8; + } + return capacity * 2; +} diff --git a/src/values.zig b/src/values.zig new file mode 100644 index 0000000..7075031 --- /dev/null +++ b/src/values.zig @@ -0,0 +1,43 @@ +const std = @import("std"); +const debug = std.debug; + +const Allocator = std.mem.Allocator; + +const utils = @import("./utils.zig"); + +pub const Value = f64; + +pub const ValueArray = struct { + capacity: usize, + count: usize, + values: []Value, + + pub fn new() ValueArray { + return ValueArray{ + .capacity = 0, + .count = 0, + .values = &.{}, + }; + } + + pub fn write(self: *ValueArray, allocator: Allocator, value: Value) !void { + if (self.capacity < self.count + 1) { + const old_capacity = self.capacity; + self.capacity = utils.grow_capacity(old_capacity); + self.values = try allocator.realloc(self.values, self.capacity); + } + + self.values[self.count] = value; + self.count += 1; + } + + pub fn free(self: *ValueArray, allocator: Allocator) void { + if (self.capacity > 0) { + allocator.free(self.values); + } + } +}; + +pub fn print_value(value: Value) void { + debug.print("{any}", .{value}); +}