commit 1bdf43f7670fca732061f69181b5f1281f0ee1ea
parent e135a269eda05077d26a9875de5dcfc2081fb3e9
Author: Szymon Mikulicz <szymon.mikulicz@posteo.net>
Date: Mon, 24 Oct 2022 01:26:55 +0200
Separate Array handling
Diffstat:
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);