commit b574f44463c63fca8a23628d6430e427498eb045
parent 2a1da9dbbc9718c63924cae9604dbad3918c63cb
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date: Mon, 26 Aug 2024 17:03:28 +0200
Little refactor
Diffstat:
17 files changed, 279 insertions(+), 202 deletions(-)
diff --git a/zlox/src/chunk.zig b/zlox/src/chunk.zig
@@ -1,6 +1,5 @@
const std = @import("std");
-const value = @import("value.zig");
-const ValueArray = value.ValueArray;
+const Value = @import("value.zig").Value;
const array = @import("array.zig");
const Obj = @import("obj.zig").Obj;
@@ -45,7 +44,7 @@ pub const Chunk = struct {
pub fn init(allocator: std.mem.Allocator) Error!@This() {
return @This(){
.code = try array.Array(u8, usize, 8).init(allocator),
- .constants = try ValueArray.init(allocator),
+ .constants = try Value.Array.init(allocator),
.lines = try array.RLEArray(i32, 8).init(allocator),
};
}
@@ -59,7 +58,7 @@ pub const Chunk = struct {
try self.write(@intFromEnum(op), line);
}
- pub fn addConstant(self: *@This(), val: value.Value) Error!u8 {
+ pub fn addConstant(self: *@This(), val: Value) Error!u8 {
for (self.constants.slice(), 0..) |el, i| {
if (el.eql(val)) {
return @intCast(i);
@@ -76,6 +75,6 @@ pub const Chunk = struct {
}
code: array.Array(u8, usize, 8),
- constants: ValueArray,
+ constants: Value.Array,
lines: array.RLEArray(i32, 8),
};
diff --git a/zlox/src/debug.zig b/zlox/src/debug.zig
@@ -4,7 +4,7 @@ const value = @import("value.zig");
const Obj = @import("obj.zig").Obj;
const print = std.debug.print;
-const Error = error{OutOfMemory, KeyError, IllegalCastError, NotFound, IndexOutOfBounds};
+const Error = Obj.Error;
pub fn disassembleChunk(ch: *const chunk.Chunk, name: []const u8) Error!void {
print("/= {s} =\\\n", .{name});
diff --git a/zlox/src/gc.zig b/zlox/src/gc.zig
@@ -1,42 +1,46 @@
const std = @import("std");
const Obj = @import("obj.zig").Obj;
+const list = @import("list.zig");
const Value = @import("value.zig").Value;
pub const GC = struct {
const Self = @This();
+ const List = list.List(*Obj);
+
allocator: std.mem.Allocator,
table: Obj.String.Table,
- list: *Obj.List,
+ list: List,
pub fn init(allocator: std.mem.Allocator) !Self {
return Self{
.allocator = allocator,
.table = Obj.String.Table.init(allocator),
- .list = try Obj.List.init({}, allocator),
+ .list = List.init(allocator),
};
}
- pub fn emplace(self: *Self, comptime tp: Obj.Type, arg: tp.get().Arg) Obj.Error!*tp.get() {
+ pub fn emplace(self: *Self, comptime tp: Obj.Type, arg: tp.get().Arg) (List.Error || tp.get().Error)!*tp.get() {
var newObj = true;
const obj = switch (tp) {
.String => try Obj.String.intern(arg, &self.table, &newObj, self.allocator),
else => try tp.get().init(arg, self.allocator),
};
- if (newObj) try self.list.push(Value.init(obj.cast()), self.allocator);
+ if (newObj) try self.list.push(obj.cast());
return obj;
}
- pub fn emplace_cast(self: *Self, comptime tp: Obj.Type, arg: tp.get().Arg) Obj.Error!*Obj {
+ pub fn emplace_cast(self: *Self, comptime tp: Obj.Type, arg: tp.get().Arg) (List.Error || tp.get().Error)!*Obj {
return (try self.emplace(tp, arg)).cast();
}
pub fn deinit(self: *Self) void {
- while (self.list.pop(self.allocator)) |el| {
- el.obj.free(self.allocator);
+ while (true) {
+ const el = self.list.pop() catch break;
+ el.free(self.allocator);
}
- self.list.free(self.allocator);
+ self.list.free();
self.table.deinit();
}
};
diff --git a/zlox/src/list.zig b/zlox/src/list.zig
@@ -0,0 +1,158 @@
+const std = @import("std");
+
+pub fn List(T: type) type {
+ return struct {
+ const Self = @This();
+
+ pub const Error = error{ OutOfMemory, IndexOutOfBounds, Empty };
+
+ const Element = struct {
+ val: ?T,
+ next: ?*@This(),
+ prev: ?*@This(),
+ };
+
+ len: usize,
+ tip: ?*Element,
+ end: ?*Element,
+ allocator: std.mem.Allocator,
+
+ pub fn init(allocator: std.mem.Allocator) Self {
+ return Self{
+ .len = 0,
+ .tip = null,
+ .end = null,
+ .allocator = allocator,
+ };
+ }
+
+ pub fn eql(self: *const Self, other: *const Self, eql_fn: fn(T, T) bool) bool {
+ if (self.len != other.len) return false;
+ if (self.len == 0) return true;
+ var tip1 = self.tip;
+ var tip2 = other.tip;
+ while (tip1) |el1| : (tip1 = el1.next) {
+ if (el1.val) |val1| {
+ if (tip2.?.val) |val2| {
+ if (!eql_fn(val1, val2)) return false;
+ } else {
+ return false;
+ }
+ } else if (tip2.?.val) |_| {
+ return false;
+ }
+ tip2 = tip2.?.next;
+ }
+ return true;
+ }
+
+ pub fn free(self: *Self) void {
+ while (true) {_ = self.pop() catch return;}
+ }
+
+ pub fn get(self: *const Self, index: usize) Error!T {
+ if (index >= self.len) {
+ return Error.IndexOutOfBounds;
+ }
+ var idx_rev: usize = index;
+ var idx = self.len - idx_rev;
+ idx_rev += 1;
+
+ if (idx < idx_rev) {
+ var tip = self.tip;
+ while(idx > 1) : (idx -= 1) {
+ tip = tip.?.next;
+ }
+ return tip.?.val orelse Error.IndexOutOfBounds;
+ } else {
+ var end = self.end;
+ while(idx_rev > 1) : (idx_rev -= 1) {
+ end = end.?.prev;
+ }
+ return end.?.val orelse Error.IndexOutOfBounds;
+ }
+ }
+
+ fn _set(self: *Self, index: usize, val: ?T) Error!void {
+ var idx_rev: isize = @intCast(index);
+ var idx: isize = @as(isize, @intCast(self.len)) - idx_rev;
+ idx_rev += 1;
+
+ if (idx <= 0) {
+ while(idx < 0) : (idx += 1) {
+ try self._push(null);
+ }
+ try self._push(val);
+ } else if (idx < idx_rev) {
+ var tip = self.tip;
+ while(idx > 1) : (idx -= 1) {
+ tip = tip.?.next;
+ }
+ tip.?.val = val;
+ } else {
+ var end = self.end;
+ while(idx_rev > 1) : (idx_rev -= 1) {
+ end = end.?.prev;
+ }
+ end.?.val = val;
+ }
+
+ }
+
+ pub fn set(self: *Self, index: usize, val: T) Error!void {
+ return self._set(index, val);
+ }
+
+ pub fn delete(self: *Self, index: usize) void {
+ if (index >= self.len) return;
+ if (index == self.len - 1) {
+ _ = self.pop() catch unreachable;
+ } else {
+ self._set(index, null) catch unreachable;
+ }
+ }
+
+ fn _pop(self: *Self) Error!?T {
+ if (self.tip) |tip| {
+ if (tip.next) |next| {
+ next.prev = null;
+ self.tip = next;
+ } else {
+ self.tip = null;
+ self.end = null;
+ }
+ self.len -= 1;
+ const val = tip.val;
+ self.allocator.destroy(tip);
+ return val;
+ }
+ return Error.Empty;
+ }
+
+ pub fn pop(self: *Self) Error!T {
+ const val = try self._pop();
+ while (self.tip) |tip| {
+ if (tip.val) |_| break;
+ _ = self._pop() catch unreachable;
+ }
+ return val.?;
+ }
+
+ fn _push(self: *Self, val: ?T) Error!void {
+ const new_tip = try self.allocator.create(Element);
+ if (self.end == null) {
+ self.end = new_tip;
+ }
+ if (self.tip) |old_tip| {
+ old_tip.prev = new_tip;
+ }
+ new_tip.* = Element{.val = val, .next = self.tip, .prev = null};
+ self.tip = new_tip;
+ self.len += 1;
+ }
+
+ pub fn push(self: *Self, val: T) Error!void {
+ return self._push(val);
+ }
+ };
+}
diff --git a/zlox/src/obj.zig b/zlox/src/obj.zig
@@ -1,10 +1,8 @@
const std = @import("std");
const utils = @import("comptime_utils.zig");
-const TableError = @import("table.zig").TableError;
pub const Obj = packed struct {
const Super = @This();
- pub const Error = TableError || error{ OutOfMemory, IllegalCastError, NotFound };
type: Type,
@@ -16,6 +14,16 @@ pub const Obj = packed struct {
pub const Closure = @import("obj/closure.zig").Closure;
pub const Upvalue = @import("obj/upvalue.zig").Upvalue;
+ pub const Error = error {IllegalCastError}
+ || List.Error
+ || String.Error
+ || Table.Error
+ || Function.Error
+ || Native.Error
+ || List.Error
+ || Closure.Error
+ || Upvalue.Error;
+
pub const Type = enum(u8) {
String,
Table,
diff --git a/zlox/src/obj/closure.zig b/zlox/src/obj/closure.zig
@@ -2,12 +2,12 @@ const std = @import("std");
const utils = @import("../comptime_utils.zig");
const Super = @import("../obj.zig").Obj;
-const Error = Super.Error;
pub const Closure = packed struct {
const Self = @This();
pub const Arg = *const Super.Function;
+ pub const Error = error { OutOfMemory };
obj: Super,
function: *const Super.Function,
diff --git a/zlox/src/obj/function.zig b/zlox/src/obj/function.zig
@@ -3,12 +3,12 @@ const chunk = @import("../chunk.zig");
const utils = @import("../comptime_utils.zig");
const Super = @import("../obj.zig").Obj;
-const Error = Super.Error;
const String = Super.String;
pub const Function = packed struct {
const Self = @This();
pub const Arg = Type;
+ pub const Error = error { OutOfMemory };
pub const Type = enum(u8) {
Function,
diff --git a/zlox/src/obj/list.zig b/zlox/src/obj/list.zig
@@ -3,25 +3,19 @@ const std = @import("std");
const Value = @import("../value.zig").Value;
const Super = @import("../obj.zig").Obj;
const utils = @import("../comptime_utils.zig");
-const Error = Super.Error;
+const list = @import("../list.zig");
const String = Super.String;
const Type = Super.Type;
pub const List = packed struct {
const Self = @This();
- const Element = struct {
- val: Value,
- next: ?*@This(),
- prev: ?*@This(),
- };
-
+ pub const List = list.List(Value);
pub const Arg = void;
+ pub const Error = error { OutOfMemory, InvalidArgument } || Self.List.Error;
obj: Super,
- len: usize = 0,
- tip: ?*Element,
- end: ?*Element,
+ list: *Self.List,
pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self {
const self: *Self = try allocator.create(Self);
@@ -29,9 +23,9 @@ pub const List = packed struct {
.obj = Super{
.type = Super.Type.List,
},
- .tip = null,
- .end = null,
+ .list = try allocator.create(Self.List)
};
+ self.list.* = Self.List.init(allocator);
return self;
}
@@ -41,125 +35,46 @@ pub const List = packed struct {
pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) utils.fn_error(@TypeOf(writer).write)!void {
_ = try writer.write("[");
- var end = self.end;
+ var end = self.list.end;
while (end) |el| : (end = el.prev) {
- try el.val.format(fmt, options, writer);
+ if (el.val) |v| {
+ try v.format(fmt, options, writer);
+ } else {
+ _ = try writer.write("-");
+ }
if (el.prev) |_| _ = try writer.write(", ");
}
_ = try writer.writeAll("]");
}
pub fn eql(self: *const Self, other: *const Self) bool {
- if (self.len != other.len) return false;
- if (self.len == 0) return true;
- var tip1 = self.tip;
- var tip2 = other.tip;
- while (tip1) |el1| : (tip1 = el1.next) {
- if (!el1.val.eql(tip2.?.val))
- return false;
- tip2 = tip2.?.next;
- }
- return true;
+ return self.list.eql(other.list, Value.eql);
}
pub fn free(self: *Self, allocator: std.mem.Allocator) void {
- while (self.pop(allocator)) |_| {}
+ self.list.free();
+ allocator.destroy(self.list);
allocator.destroy(self);
}
- pub fn get(self: *const Self, index: Value) !Value {
- if (!index.is(Value.number) or index.number >= @as(Value.tagType(Value.number), @floatFromInt(self.len)) or index.number < 0) {
- return error.KeyError;
- }
- var idx_rev: usize = @intFromFloat(index.number);
- var idx = self.len - idx_rev;
- idx_rev += 1;
-
- if (idx < idx_rev) {
- var tip = self.tip;
- while(idx > 1) : (idx -= 1) {
- tip = tip.?.next;
- }
- return tip.?.val;
- } else {
- var end = self.end;
- while(idx_rev > 1) : (idx_rev -= 1) {
- end = end.?.prev;
- }
- return end.?.val;
+ pub fn delete(self: *Self, index: Value) void {
+ if (!index.is(Value.number) or index.number >= @as(Value.tagType(Value.number), @floatFromInt(self.list.len)) or index.number < 0) {
+ return;
}
+ self.list.delete(@intFromFloat(index.number));
}
- pub fn set(self: *Self, index: Value, val: Value, allocator: std.mem.Allocator) !void {
- if (!index.is(Value.number) or index.number < 0) {
- return error.KeyError;
+ pub fn get(self: *const Self, index: Value) Error!Value {
+ if (!index.is(Value.number) or index.number >= @as(Value.tagType(Value.number), @floatFromInt(self.list.len)) or index.number < 0) {
+ return Error.InvalidArgument;
}
-
- var idx_rev: isize = @intFromFloat(index.number);
- var idx: isize = @as(isize, @intCast(self.len)) - idx_rev;
- idx_rev += 1;
-
- if (idx <= 0) {
- while(idx < 0) : (idx += 1) {
- try self.push(Value.init({}), allocator);
- }
- try self.push(val, allocator);
- } else if (idx < idx_rev) {
- var tip = self.tip;
- while(idx > 1) : (idx -= 1) {
- tip = tip.?.next;
- }
- tip.?.val = val;
- } else {
- var end = self.end;
- while(idx_rev > 1) : (idx_rev -= 1) {
- end = end.?.prev;
- }
- end.?.val = val;
- }
-
- }
-
- pub fn pop(self: *Self, allocator: std.mem.Allocator) ?Value {
- if (self.tip) |tip| {
- if (tip.next) |next| {
- next.prev = null;
- self.tip = next;
- } else {
- self.tip = null;
- self.end = null;
- }
- self.len -= 1;
- const val = tip.val;
- allocator.destroy(tip);
- return val;
- }
- return null;
+ return self.list.get(@intFromFloat(index.number));
}
- pub fn push(self: *Self, val: Value, allocator: std.mem.Allocator) Error!void {
- const new_tip = try allocator.create(Element);
- if (self.end == null) {
- self.end = new_tip;
- }
- if (self.tip) |old_tip| {
- old_tip.prev = new_tip;
- }
- new_tip.* = Element{.val = val, .next = self.tip, .prev = null};
- self.tip = new_tip;
- self.len += 1;
- }
-
- pub fn push_end(self: *Self, val: Value, allocator: std.mem.Allocator) Error!void {
- const new_end = try allocator.create(Element);
- if (self.tip == null) {
- self.tip = new_end;
- }
- if (self.end) |old_end| {
- old_end.next = new_end;
+ pub fn set(self: *Self, index: Value, val: Value) Error!void {
+ if (!index.is(Value.number) or index.number < 0) {
+ return Error.InvalidArgument;
}
- new_end.* = Element{.val = val, .next = null, .prev = self.end};
- self.end = new_end;
- self.len += 1;
+ return self.list.set(@intFromFloat(index.number), val);
}
};
diff --git a/zlox/src/obj/native.zig b/zlox/src/obj/native.zig
@@ -4,13 +4,12 @@ const utils = @import("../comptime_utils.zig");
const GC = @import("../gc.zig").GC;
const Value = @import("../value.zig").Value;
const Super = @import("../obj.zig").Obj;
-const Error = Super.Error;
-
-pub const NativeError = error { NativeError };
pub const Native = packed struct {
const Self = @This();
- pub const Fn = *const fn (*GC, []const Value) NativeError!Value;
+ pub const Error = error { OutOfMemory, Native };
+
+ pub const Fn = *const fn (*GC, []const Value) Error!Value;
pub const ArityMin = 0;
pub const ArityMax = std.math.maxInt(u8);
@@ -44,7 +43,7 @@ pub const Native = packed struct {
return self;
}
- pub fn call(self: *const Self, gc: *GC, argCount: u8, args: [*]Value) NativeError!Value {
+ pub fn call(self: *const Self, gc: *GC, argCount: u8, args: [*]Value) Error!Value {
return self.fun(gc, args[0..argCount]);
}
diff --git a/zlox/src/obj/string.zig b/zlox/src/obj/string.zig
@@ -5,12 +5,12 @@ const utils = @import("../comptime_utils.zig");
const value = @import("../value.zig");
const Super = @import("../obj.zig").Obj;
-const Error = Super.Error;
pub const String = packed struct {
const Self = @This();
pub const Table = table.Table(*Self, void, hash.hash_t(*const Self), Self.eql);
pub const Arg = []const []const u8;
+ pub const Error = error { OutOfMemory, IndexOutOfBounds } || Table.Error;
obj: Super,
len: usize = 0,
@@ -49,9 +49,9 @@ pub const String = packed struct {
pub fn eql(self: *const Self, other: *const Self) bool {
return @intFromPtr(self) == @intFromPtr(other);
}
- pub fn get(self: *const Self, index: value.Value) !value.Value {
+ pub fn get(self: *const Self, index: value.Value) Error!value.Value {
if (!index.is(value.Value.number) or index.number >= @as(value.Value.tagType(value.Value.number), @floatFromInt(self.len)) or index.number < 0) {
- return error.KeyError;
+ return Error.IndexOutOfBounds;
}
return value.Value.init(self.data()[@intFromFloat(index.number)]);
}
diff --git a/zlox/src/obj/table.zig b/zlox/src/obj/table.zig
@@ -1,16 +1,16 @@
const std = @import("std");
const table = @import("../table.zig");
const hash = @import("../hash.zig");
-const value = @import("../value.zig");
+const Value = @import("../value.zig").Value;
const utils = @import("../comptime_utils.zig");
const Super = @import("../obj.zig").Obj;
-const Error = Super.Error;
pub const Table = packed struct {
const Self = @This();
pub const Arg = void;
- const Table = table.Table(value.Value, value.Value, hash.hash_t(value.Value), value.Value.eql);
+ const Table = table.Table(Value, Value, hash.hash_t(Value), Value.eql);
+ pub const Error = error { OutOfMemory } || Self.Table.Error;
obj: Super,
table: *Self.Table,
@@ -33,27 +33,28 @@ pub const Table = packed struct {
return @ptrCast(self);
}
- pub fn set(self: *Self, key: value.Value, val: value.Value) !bool {
+ pub fn set(self: *Self, key: Value, val: Value) Error!bool {
self.hash +%= hash.hash(key) +% hash.hash(val);
return self.table.set(key, val);
}
- pub fn get(self: *Self, key: value.Value) !value.Value {
+ pub fn get(self: *Self, key: Value) Error!Value {
return self.table.get(key);
}
- pub fn delete(self: *Self, key: value.Value) void {
+ pub fn delete(self: *Self, key: Value) void {
const val = self.table.get(key) catch return;
self.hash -%= hash.hash(key) -% hash.hash(val);
_ = self.table.delete(key);
}
+
pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
const Printer = struct {
options: std.fmt.FormatOptions,
writer: @TypeOf(writer),
count: usize,
- pub fn print(this: *@This(), key: value.Value, val: value.Value) utils.fn_error(@TypeOf(writer).write)!void {
+ pub fn print(this: *@This(), key: Value, val: Value) utils.fn_error(@TypeOf(writer).write)!void {
this.count -= 1;
try key.format(fmt, this.options, this.writer);
@@ -73,13 +74,14 @@ pub const Table = packed struct {
}
_ = try writer.writeAll("]");
}
+
pub fn eql(self: *const Self, other: *const Self) bool {
- return self.table.eql(other.table, value.Value.eql);
+ return self.table.eql(other.table, Value.eql);
}
+
pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
self.table.deinit();
allocator.destroy(self.table);
allocator.destroy(self);
}
-
};
diff --git a/zlox/src/obj/template.zig b/zlox/src/obj/template.zig
@@ -2,18 +2,18 @@ const std = @import("std");
const utils = @import("../comptime_utils.zig");
const Super = @import("../obj.zig").Obj;
-const Error = Super.Error;
pub const Template = packed struct {
const Self = @This();
pub const Arg = void;
+ pub const Error = error { OutOfMemory };
obj: Super,
pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self {
_ = arg;
_ = allocator;
- return error.OutOfMemory;
+ return Error.OutOfMemory;
}
pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) {
diff --git a/zlox/src/obj/upvalue.zig b/zlox/src/obj/upvalue.zig
@@ -3,12 +3,12 @@ const std = @import("std");
const utils = @import("../comptime_utils.zig");
const Value = @import("../value.zig").Value;
const Super = @import("../obj.zig").Obj;
-const Error = Super.Error;
pub const Upvalue = packed struct {
const Self = @This();
pub const Arg = *Value;
+ pub const Error = error { OutOfMemory };
obj: Super,
location: *Value,
diff --git a/zlox/src/table.zig b/zlox/src/table.zig
@@ -1,13 +1,13 @@
const std = @import("std");
const utils = @import("comptime_utils.zig");
-pub const TableError = error{ OutOfMemory, KeyError };
-
pub fn Table(K: type, V: type, hash_fn: fn (K) u32, cmp_fn: fn (K, K) bool) type {
return struct {
const Self = @This();
const MaxLoad: f32 = 0.75;
+ pub const Error = error{ OutOfMemory, KeyError };
+
pub const Entry = union(enum) {
const Some = struct {
key: K,
@@ -33,7 +33,7 @@ pub fn Table(K: type, V: type, hash_fn: fn (K) u32, cmp_fn: fn (K, K) bool) type
10;
}
- fn adjustCapacity(self: *Self, newsize: usize) TableError!void {
+ fn adjustCapacity(self: *Self, newsize: usize) Error!void {
const entries = try self.allocator.alloc(Entry, newsize);
for (entries) |*entry| {
entry.* = .none;
@@ -79,7 +79,7 @@ pub fn Table(K: type, V: type, hash_fn: fn (K) u32, cmp_fn: fn (K, K) bool) type
}
}
- pub fn addAll(self: *Self, other: *const Self) TableError!void {
+ pub fn addAll(self: *Self, other: *const Self) Error!void {
for (other.entries) |entry| {
switch (entry) {
.some => |some| self.set(some.key, some.value),
@@ -137,7 +137,7 @@ pub fn Table(K: type, V: type, hash_fn: fn (K) u32, cmp_fn: fn (K, K) bool) type
return true;
}
- pub fn checkCapacity(self: *Self) TableError!void {
+ pub fn checkCapacity(self: *Self) Error!void {
const len: f32 = @floatFromInt(self.entries.len);
const count: f32 = @floatFromInt(self.count);
if (count + 1.0 > len * MaxLoad) {
@@ -145,40 +145,40 @@ pub fn Table(K: type, V: type, hash_fn: fn (K) u32, cmp_fn: fn (K, K) bool) type
}
}
- pub fn set(self: *Self, key: K, val: V) TableError!bool {
+ pub fn set(self: *Self, key: K, val: V) Error!bool {
try self.checkCapacity();
return self.set_(find(self.entries, key), key, val);
}
- pub fn replace(self: *Self, key: K, val: V) TableError!void {
+ pub fn replace(self: *Self, key: K, val: V) Error!void {
if (self.entries.len == 0)
- return TableError.KeyError;
+ return Error.KeyError;
const entry = find(self.entries, key);
switch (entry.*) {
.some => _ = self.set_(entry, key, val),
- else => return TableError.KeyError,
+ else => return Error.KeyError,
}
}
- pub fn replace_if(self: *Self, key: K, val: V, fun: fn (V) bool) TableError!bool {
+ pub fn replace_if(self: *Self, key: K, val: V, fun: fn (V) bool) Error!bool {
if (self.entries.len == 0)
- return TableError.KeyError;
+ return Error.KeyError;
const entry = find(self.entries, key);
switch (entry.*) {
.some => |some| return fun(some.value) and !self.set_(entry, key, val),
- else => return TableError.KeyError,
+ else => return Error.KeyError,
}
}
- pub fn get(self: *const Self, key: K) TableError!V {
+ pub fn get(self: *const Self, key: K) Error!V {
if (self.entries.len == 0)
- return TableError.KeyError;
+ return Error.KeyError;
return switch (find(self.entries, key).*) {
.some => |some| some.value,
- else => TableError.KeyError,
+ else => Error.KeyError,
};
}
diff --git a/zlox/src/value.zig b/zlox/src/value.zig
@@ -13,6 +13,8 @@ pub const Value = union(enum) {
const Self = @This();
pub const Tag = std.meta.Tag(Self);
+ pub const Array = array.Array(Value, u8, 8);
+
pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
switch (self) {
.number => |val| try writer.print("{d}", .{val}),
@@ -90,5 +92,3 @@ pub const Value = union(enum) {
};
}
};
-
-pub const ValueArray = array.Array(Value, u8, 8);
diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig
@@ -12,7 +12,7 @@ const hash = @import("hash.zig");
const utils = @import("comptime_utils.zig");
const vm_native = @import("vm/native.zig");
-pub const InterpreterError = vm_native.NativeError || compiler.CompilerError || Callback.Error || error{ CompileError, RuntimeError, StackOverflow, IndexOutOfBounds, Overflow, DivisionByZero };
+pub const InterpreterError = Obj.Error || compiler.CompilerError || Callback.Error || error{ CompileError, RuntimeError, StackOverflow, IndexOutOfBounds, Overflow, DivisionByZero };
pub const VM = struct {
objects: GC,
@@ -96,7 +96,7 @@ pub const VM = struct {
const function = try compiler.Compiler(stack_size).compile(source, &self.objects);
- try debug.disassembleChunk(function.chunk, "Main");
+ if (dbg) try debug.disassembleChunk(function.chunk, "Main");
try Interpreter(callstack_size, stack_size).run(self, function, dbg);
}
@@ -351,32 +351,23 @@ pub const VM = struct {
const val = self.pop();
const key = self.pop();
const obj = self.pop();
- if (obj.is(Obj.Type.Table)) {
- var m = obj.obj.cast(.Table) catch unreachable;
- if (val.is(Value.nil)) {
- m.delete(key);
- } else {
- _ = try m.set(key, val);
- }
- } else if (obj.is(Obj.Type.List)) {
- var m = obj.obj.cast(.List) catch unreachable;
- if (val.is(Value.nil) and key.eql(Value.init(@as(f64, @floatFromInt(m.len - 1))))) {
- _ = m.pop(self.vm.allocator);
- while(m.tip) |t| {
- if (t.val.is(Value.nil)) {
- _ = m.pop(self.vm.allocator);
+ var pushed = false;
+ if (obj.is(Value.obj)) {
+ switch(obj.obj.type) {
+ .Function, .Native, .Closure, .Upvalue, .String => {},
+ inline else => |tp| {
+ var m = obj.obj.cast(tp) catch unreachable;
+ if (val.is(Value.nil)) {
+ m.delete(key);
} else {
- break;
+ _ = try m.set(key, val);
}
+ pushed = true;
}
- } else {
- m.set(key, val, self.vm.allocator) catch {
- self.runtimeError("Invalid index for a list, has to be a number greater than 0", .{});
- return InterpreterError.RuntimeError;
- };
}
- } else {
- self.runtimeError("Cannot index a non-table value", .{});
+ }
+ if (!pushed) {
+ self.runtimeError("Cannot index a value of type {s}", .{obj.typeName()});
return InterpreterError.RuntimeError;
}
self.push(val);
diff --git a/zlox/src/vm/native.zig b/zlox/src/vm/native.zig
@@ -1,7 +1,8 @@
const std = @import("std");
const GC = @import("../gc.zig").GC;
const Value = @import("../value.zig").Value;
-pub const NativeError = @import("../obj/native.zig").NativeError;
+
+pub const Error = @import("../obj.zig").Obj.Native.Error;
pub const Clock = struct {
var start: std.time.Instant = undefined;
@@ -10,33 +11,33 @@ pub const Clock = struct {
start = try std.time.Instant.now();
}
- pub fn clock(_: *GC, _: [] const Value) NativeError!Value {
- const now = std.time.Instant.now() catch return NativeError.NativeError;
+ pub fn clock(_: *GC, _: [] const Value) Error!Value {
+ const now = std.time.Instant.now() catch return Error.Native;
const elapsed: f64 = @floatFromInt(now.since(start));
return Value.init(elapsed / std.time.ns_per_s);
}
};
-pub fn put(_: *GC, args: []const Value) NativeError!Value {
+pub fn put(_: *GC, args: []const Value) Error!Value {
std.debug.print("{s}", .{args[0]});
return Value.init({});
}
-pub fn table(gc: *GC, args: []const Value) NativeError!Value {
- var tbl = gc.emplace(.Table, {}) catch return NativeError.NativeError;
- if (args.len % 2 != 0) return NativeError.NativeError;
+pub fn table(gc: *GC, args: []const Value) Error!Value {
+ var tbl = gc.emplace(.Table, {}) catch return Error.Native;
+ if (args.len % 2 != 0) return Error.Native;
var i: usize = 0;
while(i < args.len) : (i += 2) {
- _ = tbl.set(args[i], args[i+1]) catch return NativeError.NativeError;
+ _ = tbl.set(args[i], args[i+1]) catch return Error.Native;
}
return Value.init(tbl.cast());
}
-pub fn list(gc: *GC, args: []const Value) NativeError!Value {
- var lis = gc.emplace(.List, {}) catch return NativeError.NativeError;
+pub fn list(gc: *GC, args: []const Value) Error!Value {
+ var lis = gc.emplace(.List, {}) catch return Error.Native;
for(args) |arg| {
- lis.push(arg, gc.allocator) catch return NativeError.NativeError;
+ lis.list.push(arg) catch return Error.Native;
}
return Value.init(lis.cast());
}