DzLox

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

commit b574f44463c63fca8a23628d6430e427498eb045
parent 2a1da9dbbc9718c63924cae9604dbad3918c63cb
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date:   Mon, 26 Aug 2024 17:03:28 +0200

Little refactor

Diffstat:
Mzlox/src/chunk.zig | 9++++-----
Mzlox/src/debug.zig | 2+-
Mzlox/src/gc.zig | 20++++++++++++--------
Azlox/src/list.zig | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mzlox/src/obj.zig | 12++++++++++--
Mzlox/src/obj/closure.zig | 2+-
Mzlox/src/obj/function.zig | 2+-
Mzlox/src/obj/list.zig | 139++++++++++++++++---------------------------------------------------------------
Mzlox/src/obj/native.zig | 9++++-----
Mzlox/src/obj/string.zig | 6+++---
Mzlox/src/obj/table.zig | 20+++++++++++---------
Mzlox/src/obj/template.zig | 4++--
Mzlox/src/obj/upvalue.zig | 2+-
Mzlox/src/table.zig | 30+++++++++++++++---------------
Mzlox/src/value.zig | 4++--
Mzlox/src/vm.zig | 39+++++++++++++++------------------------
Mzlox/src/vm/native.zig | 23++++++++++++-----------
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()); }