DzLox

:)
git clone https://git.sr.ht/~ashymad/DzLox
Log | Files | Refs | Submodules | LICENSE

commit 1bdf43f7670fca732061f69181b5f1281f0ee1ea
parent e135a269eda05077d26a9875de5dcfc2081fb3e9
Author: Szymon Mikulicz <szymon.mikulicz@posteo.net>
Date:   Mon, 24 Oct 2022 01:26:55 +0200

Separate Array handling

Diffstat:
Azlox/src/array.zig | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mzlox/src/chunk.zig | 28++++++++--------------------
Mzlox/src/debug.zig | 24++++++++++++------------
Mzlox/src/main.zig | 4++--
Dzlox/src/rlearray.zig | 48------------------------------------------------
Mzlox/src/value.zig | 31++-----------------------------
6 files changed, 108 insertions(+), 111 deletions(-)

diff --git a/zlox/src/array.zig b/zlox/src/array.zig @@ -0,0 +1,84 @@ +const std = @import("std"); + +pub fn Array(comptime T: type, comptime S: type, comptime size: S) type { + return struct { + count: S, + capacity: S, + elements: []T, + allocator: std.mem.Allocator, + + pub fn init(allocator: std.mem.Allocator) !@This() { + return @This() { + .count = 0, + .capacity = size, + .elements = try allocator.alloc(T, size), + .allocator = allocator + }; + } + + pub fn add(self: *@This(), val: T) !void { + if (self.capacity < self.count + 1) { + self.capacity = 2 * self.count; + self.elements = try self.allocator.realloc(self.elements, self.capacity); + } + self.elements[self.count] = val; + self.count += 1; + } + + pub fn get(self: *const @This(), idx: S) !T { + if (idx >= self.count) + return error.IndexOutOfBounds; + return self.elements[idx]; + } + + pub fn last(self: *const @This()) !T { + if (self.count == 0) + return error.IndexOutOfBounds; + return self.get(self.count - 1); + } + + pub fn deinit(self: *@This()) void { + self.allocator.free(self.elements); + } + }; +} + +pub fn RLEArray(comptime T: type, comptime size: usize) type { + return struct { + array: Array(element, usize, size), + + const element = struct {val: T, run: usize}; + + pub fn init(allocator: std.mem.Allocator) !@This() { + return @This() { + .array = try Array(element, usize, size).init(allocator), + }; + } + + pub fn add(self: *@This(), val: T) !void { + const last = self.array.last() catch { + try self.array.add(.{.val = val, .run = 1}); + return; + }; + if (val == last.val) { + self.array.elements[self.array.count-1].run += 1; + } else { + try self.array.add(.{.val = val, .run = 1}); + } + } + + pub fn get(self: *const @This(), idx: usize) !T { + var i: usize = 0; + var sum: usize = 0; + while(idx >= sum) : (i += 1) { + sum += (try self.array.get(i)).run; + } + if (i > 0) return self.array.elements[i-1].val + else return (try self.array.get(i)).val; + } + + pub fn deinit(self: *@This()) void { + self.array.deinit(); + } + }; +} diff --git a/zlox/src/chunk.zig b/zlox/src/chunk.zig @@ -1,7 +1,7 @@ const std = @import("std"); const value = @import("value.zig"); const ValueArray = value.ValueArray; -const RLEArray = @import("rlearray.zig").RLEArray; +const array = @import("array.zig"); pub const OP = enum(u8) { CONSTANT, @@ -10,42 +10,30 @@ pub const OP = enum(u8) { pub const Chunk = struct { pub fn init(allocator: std.mem.Allocator) !@This() { - const cap = 8; return @This() { - .count = 0, - .capacity = cap, - .code = try allocator.alloc(u8, cap), + .code = try array.Array(u8, usize, 8).init(allocator), .constants = try ValueArray.init(allocator), - .lines = try RLEArray(u32).init(allocator), - .allocator = allocator + .lines = try array.RLEArray(u32, 8).init(allocator), }; } pub fn write(self: *@This(), byte: u8, line: u32) !void { - if (self.capacity < self.count + 1) { - self.capacity = 2 * self.count; - self.code = try self.allocator.realloc(self.code, self.capacity); - } - self.code[self.count] = byte; + try self.code.add(byte); try self.lines.add(line); - self.count += 1; } pub fn addConstant(self: *@This(), val: value.Value) !u8 { - try self.constants.write(val); + try self.constants.add(val); return self.constants.count - 1; } pub fn deinit(self: *@This()) void { self.constants.deinit(); self.lines.deinit(); - self.allocator.free(self.code); + self.code.deinit(); } - count: usize, - capacity: usize, - code: []u8, + code: array.Array(u8, usize, 8), constants: ValueArray, - lines: RLEArray(u32), - allocator: std.mem.Allocator, + lines: array.RLEArray(u32, 8), }; diff --git a/zlox/src/debug.zig b/zlox/src/debug.zig @@ -3,30 +3,30 @@ const chunk = @import("chunk.zig"); const value = @import("value.zig"); const print = std.debug.print; -pub fn disassembleChunk(ch: chunk.Chunk, name: []const u8) void { +pub fn disassembleChunk(ch: chunk.Chunk, name: []const u8) !void { print("== {s} ==\n", .{name}); var offset: usize = 0; - while (offset < ch.count) { - offset = disassembleInstruction(ch, offset); + while (offset < ch.code.count) { + offset = try disassembleInstruction(ch, offset); } } -pub fn disassembleInstruction(ch: chunk.Chunk, offset: usize) usize { +pub fn disassembleInstruction(ch: chunk.Chunk, offset: usize) !usize { const OP = chunk.OP; print("{d:0>4} ", .{offset}); - if (offset > 0 and ch.lines.get(offset) == ch.lines.get(offset-1)) { + if (offset > 0 and (try ch.lines.get(offset)) == (try ch.lines.get(offset-1))) { print(" | ", .{}); } else { - print("{d:4} ", .{ch.lines.get(offset)}); + print("{d:4} ", .{try ch.lines.get(offset)}); } - return switch (ch.code[offset]) { + return switch (try ch.code.get(offset)) { @enumToInt(OP.RETURN) => simpleInstruction("OP_RETURN", offset), - @enumToInt(OP.CONSTANT) => constantInstruction("OP_CONSTANT", ch, offset), + @enumToInt(OP.CONSTANT) => try constantInstruction("OP_CONSTANT", ch, offset), else => blk: { - print("Unknown opcode {}\n", .{ch.code[offset]}); + print("Unknown opcode {}\n", .{try ch.code.get(offset)}); break :blk offset + 1; }, }; @@ -37,10 +37,10 @@ fn simpleInstruction(name: []const u8, offset: usize) usize { return offset + 1; } -fn constantInstruction(name: []const u8, ch: chunk.Chunk, offset: usize) usize { - const constant = ch.code[offset + 1]; +fn constantInstruction(name: []const u8, ch: chunk.Chunk, offset: usize) !usize { + const constant = try ch.code.get(offset + 1); print("{s:<16} {d:4} '", .{name, constant}); - value.printValue(ch.constants.values[constant]); + value.printValue(try ch.constants.get(constant)); print("'\n", .{}); return offset + 2; } diff --git a/zlox/src/main.zig b/zlox/src/main.zig @@ -6,6 +6,7 @@ pub fn main() anyerror!u8 { var allocator = std.heap.GeneralPurposeAllocator(.{}){}; defer std.debug.assert(!allocator.deinit()); var ch = try chunk.Chunk.init(allocator.allocator()); + defer ch.deinit(); const constant = try ch.addConstant(1.2); try ch.write(@enumToInt(chunk.OP.CONSTANT), 123); @@ -13,7 +14,6 @@ pub fn main() anyerror!u8 { try ch.write(@enumToInt(chunk.OP.RETURN), 123); - debug.disassembleChunk(ch, "test chunk"); - ch.deinit(); + try debug.disassembleChunk(ch, "test chunk"); return 0; } diff --git a/zlox/src/rlearray.zig b/zlox/src/rlearray.zig @@ -1,48 +0,0 @@ -const std = @import("std"); - -pub fn RLEArray(comptime T: type) type { - return struct { - count: usize, - capacity: usize, - elements: []element, - allocator: std.mem.Allocator, - - const element = struct {val: T, run: usize}; - - pub fn init(allocator: std.mem.Allocator) !@This() { - const cap = 8; - return @This() { - .count = 0, - .capacity = cap, - .elements = try allocator.alloc(element, cap), - .allocator = allocator - }; - } - - pub fn add(self: *@This(), val: T) !void { - if (self.capacity < self.count + 1) { - self.capacity = 2 * self.count; - self.elements = try self.allocator.realloc(self.elements, self.capacity); - } - if (val == self.elements[self.count].val) { - self.elements[self.count].run += 1; - } else { - self.elements[self.count] = .{.val = val, .run = 0}; - self.count += 1; - } - } - - pub fn get(self: *const @This(), idx: usize) T { - var i: usize = 0; - var sum: usize = 0; - while(idx > sum) : (i += 1) { - sum += self.elements[i].run; - } - return self.elements[i].val; - } - - pub fn deinit(self: *@This()) void { - self.allocator.free(self.elements); - } - }; -} diff --git a/zlox/src/value.zig b/zlox/src/value.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const array = @import("array.zig"); pub const Value = f64; @@ -6,32 +7,4 @@ pub fn printValue(value: Value) void { std.debug.print("{d}", .{value}); } -pub const ValueArray = struct { - pub fn init(allocator: std.mem.Allocator) !@This() { - const cap = 8; - return @This() { - .count = 0, - .capacity = cap, - .values = try allocator.alloc(Value, cap), - .allocator = allocator - }; - } - - pub fn write(self: *@This(), byte: Value) !void { - if (self.capacity < self.count + 1) { - self.capacity = 2 * self.count; - self.values = try self.allocator.realloc(self.values, self.capacity); - } - self.values[self.count] = byte; - self.count += 1; - } - - pub fn deinit(self: *@This()) void { - self.allocator.free(self.values); - } - - count: u8, - capacity: u8, - values: []Value, - allocator: std.mem.Allocator, -}; +pub const ValueArray = array.Array(Value, u8, 8);