implementing constants

This commit is contained in:
Patrick MARIE 2024-08-24 15:11:45 +02:00
parent a8257c2b03
commit 9e3ced0f2e
3 changed files with 82 additions and 11 deletions

View File

@ -2,18 +2,25 @@ const std = @import("std");
const debug = std.debug; const debug = std.debug;
const Allocator = std.mem.Allocator; 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 { const Chunk = struct {
count: usize, count: usize,
capacity: usize, capacity: usize,
code: []u8, code: []u8,
constants: ValueArray,
pub fn new() Chunk { pub fn new() Chunk {
return Chunk{ return Chunk{
.count = 0, .count = 0,
.capacity = 0, .capacity = 0,
.code = &.{}, .code = &.{},
.constants = ValueArray.new(),
}; };
} }
@ -23,12 +30,13 @@ const Chunk = struct {
self.count = 0; self.count = 0;
self.capacity = 0; self.capacity = 0;
self.code = &.{}; self.code = &.{};
self.constants = ValueArray.new();
} }
pub fn write(self: *Chunk, allocator: Allocator, byte: u8) !void { pub fn write(self: *Chunk, allocator: Allocator, byte: u8) !void {
if (self.capacity < self.count + 1) { if (self.capacity < self.count + 1) {
const old_capacity = self.capacity; 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); 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 { pub fn dissassemble(self: Chunk, name: []const u8) void {
debug.print("== {s} ==\n", .{name}); debug.print("== {s} ==\n", .{name});
for (0..self.count) |idx| { var offset: usize = 0;
const offset = self.dissassemble_instruction(idx);
_ = offset; while (offset < self.count) {
offset += self.dissassemble_instruction(offset);
} }
} }
@ -56,6 +65,7 @@ const Chunk = struct {
switch (instruction) { switch (instruction) {
@intFromEnum(OpCode.OP_RETURN) => return simple_instruction("OP_RETURN", offset), @intFromEnum(OpCode.OP_RETURN) => return simple_instruction("OP_RETURN", offset),
@intFromEnum(OpCode.OP_CONSTANT) => return constant_instruction("OP_CONSTANT", self, offset),
else => { else => {
debug.print("unknown opcode {d}\n", .{instruction}); debug.print("unknown opcode {d}\n", .{instruction});
return offset + 1; return offset + 1;
@ -64,23 +74,31 @@ const Chunk = struct {
} }
pub fn deinit(self: *Chunk, allocator: Allocator) void { pub fn deinit(self: *Chunk, allocator: Allocator) void {
self.constants.free(allocator);
if (self.capacity > 0) { if (self.capacity > 0) {
allocator.free(self.code); 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 { 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; return offset + 1;
} }
pub fn grow_capacity(capacity: usize) usize { pub fn constant_instruction(opcode_name: []const u8, chunk: Chunk, offset: usize) usize {
if (capacity < 8) { const constant = chunk.code[offset + 1];
return 8; debug.print("{s:16} {d:4} ", .{ opcode_name, constant });
} values.print_value(chunk.constants.values[constant]);
return capacity * 2; debug.print("\n", .{});
return offset + 2;
} }
pub fn main() !void { pub fn main() !void {
@ -92,6 +110,10 @@ pub fn main() !void {
try chunk.init(allocator); try chunk.init(allocator);
try chunk.write(allocator, @intFromEnum(OpCode.OP_RETURN)); 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.dissassemble("test chunk");
chunk.deinit(allocator); chunk.deinit(allocator);

6
src/utils.zig Normal file
View File

@ -0,0 +1,6 @@
pub fn grow_capacity(capacity: usize) usize {
if (capacity < 8) {
return 8;
}
return capacity * 2;
}

43
src/values.zig Normal file
View File

@ -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});
}