DzLox

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

commit bb3007599d98231af265275281a7f824aa96a29c
parent 5db367d76d8508a2a93089780380792516d022af
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date:   Thu,  8 Aug 2024 14:49:20 +0200

Split Obj subclasses into separate files

Diffstat:
Mzlox/src/obj.zig | 282++-----------------------------------------------------------------------------
Azlox/src/obj/function.zig | 42++++++++++++++++++++++++++++++++++++++++++
Azlox/src/obj/list.zig | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Azlox/src/obj/string.zig | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Azlox/src/obj/table.zig | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Azlox/src/obj/template.zig | 37+++++++++++++++++++++++++++++++++++++
Mzlox/src/vm.zig | 2+-
Azlox/src/vm/callbacks.zig | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dzlox/src/vm_callbacks.zig | 65-----------------------------------------------------------------
9 files changed, 384 insertions(+), 342 deletions(-)

diff --git a/zlox/src/obj.zig b/zlox/src/obj.zig @@ -1,287 +1,17 @@ const std = @import("std"); const utils = @import("comptime_utils.zig"); -const hash = @import("hash.zig"); -const table = @import("table.zig"); -const value = @import("value.zig"); -const chunk = @import("chunk.zig"); +const TableError = @import("table.zig").TableError; pub const Obj = packed struct { const Super = @This(); - pub const Error = table.TableError || error{ OutOfMemory, IllegalCastError, NotFound }; + pub const Error = TableError || error{ OutOfMemory, IllegalCastError, NotFound }; type: Type, - // pub const Template = packed struct { - // const Self = @This(); - // pub const Arg = void; - // obj: Super, - // pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { - // _ = arg; - // _ = allocator; - // } - // pub fn cast(self: *Self) *Super { - // _ = self; - // } - // pub fn print(self: *const Self) void { - // _ = self; - // } - // pub fn eql(self: *const Self, other: *const Self) bool { - // _ = self; - // _ = other; - // } - // pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - // _ = self; - // _ = allocator; - // } - // }; - - pub const List = struct { - const Self = @This(); - const Element = struct { - obj: *Super, - next: ?*@This(), - }; - - tip: ?*Element, - allocator: std.mem.Allocator, - table: String.Table, - - pub fn init(allocator: std.mem.Allocator) Self { - return Self{ .tip = null, .allocator = allocator, .table = String.Table.init(allocator) }; - } - - pub fn push(self: *Self, val: *Super) Error!void { - var new_tip = try self.allocator.create(Element); - new_tip.next = self.tip; - new_tip.obj = val; - self.tip = new_tip; - } - - pub fn emplace(self: *Self, comptime tp: Type, arg: tp.get().Arg) Error!*Super { - var newObj = true; - const obj = switch (tp) { - .String => (try String.intern(arg, &self.table, &newObj, self.allocator)).cast(), - else => try Super.init(tp, arg, self.allocator), - }; - if (newObj) try self.push(obj); - return obj; - } - - pub fn pop(self: *Self) ?*Element { - if (self.tip) |tip| { - self.tip = tip.next; - tip.obj.free(self.allocator); - return tip; - } - return null; - } - - pub fn deinit(self: *Self) void { - while (self.pop()) |tip| { - self.allocator.destroy(tip); - } - self.table.deinit(); - } - }; - - 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; - - obj: Super, - len: usize = 0, - hash: u32, - - fn data(self: anytype) utils.copy_const(@TypeOf(self), [*]u8) { - const p: utils.copy_const(@TypeOf(self), [*]u8) = @ptrCast(self); - return p + @sizeOf(Self); - } - fn new(arg: Arg, params: ArgParams, allocator: std.mem.Allocator) Error!*Self { - const ret: *Self = @ptrCast(try allocator.alignedAlloc(u8, @alignOf(Self), @sizeOf(Self) + params.len)); - ret.* = Self{ - .obj = Super{ - .type = Super.Type.String, - }, - .hash = params.hash, - }; - for (arg) |el| { - @memcpy(ret.data() + ret.len, el); - ret.len += el.len; - } - return ret; - } - - pub fn slice(self: *const Self) []const u8 { - return self.data()[0..self.len]; - } - pub fn cast(self: *Self) *Super { - return @ptrCast(self); - } - pub fn print(self: *const Self) void { - std.debug.print("\"{s}\"", .{self.slice()}); - } - 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 { - 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 value.Value.init(self.data()[@intFromFloat(index.number)]); - } - - const ArgParams = struct { len: usize, hash: u32 }; - - fn table_check(m_arg: Arg, m_params: ArgParams) struct { - arg: Arg, - params: ArgParams, - pub fn check(self: *const @This(), k2: *const Self) bool { - if (k2.hash == self.params.hash and k2.len == self.params.len) { - var idx: usize = 0; - for (self.arg) |el| { - if (!std.mem.eql(u8, k2.data()[idx .. idx + el.len], el)) - return false; - idx += el.len; - } - return true; - } - return false; - } - } { - return @TypeOf(table_check(m_arg, m_params)){ .arg = m_arg, .params = m_params }; - } - - fn arg_params(arg: Arg) ArgParams { - var ret = ArgParams{ .len = 0, .hash = hash.hash_t([]const u8)(&.{}) }; - - for (arg) |el| { - ret.len += el.len; - ret.hash = hash.hash_append(ret.hash, el); - } - return ret; - } - - pub fn intern(arg: Arg, tabl: *Self.Table, isNewKey: *bool, allocator: std.mem.Allocator) Error!*Self { - const params = arg_params(arg); - - try tabl.checkCapacity(); - const entry = Self.Table.find_(tabl.entries, params.hash, table_check(arg, params)); - isNewKey.* = entry.* != Self.Table.Entry.some; - if (isNewKey.*) { - _ = tabl.set_(entry, try new(arg, params, allocator), {}); - } - return entry.some.key; - } - - pub fn init(_: Arg, _: std.mem.Allocator) Error!*Self { - @compileError("The String Obj has to be interned"); - } - - pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - const p: [*]align(@alignOf(Self)) const u8 = @ptrCast(self); - allocator.free(p[0 .. @sizeOf(Self) + self.len]); - } - }; - - 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); - - obj: Super, - table: *Self.Table, - hash: u32, - - pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self { - const self: *Self = try allocator.create(Self); - self.* = Self{ - .obj = Super{ - .type = Super.Type.Table, - }, - .table = try allocator.create(Self.Table), - .hash = 0, - }; - self.table.* = Self.Table.init(allocator); - return self; - } - pub fn cast(self: *Self) *Super { - return @ptrCast(self); - } - - pub fn set(self: *Self, key: value.Value, val: value.Value) !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 { - return self.table.get(key); - } - - pub fn delete(self: *Self, key: value.Value) void { - const val = self.table.get(key) catch return; - self.hash -%= hash.hash(key) -% hash.hash(val); - _ = self.table.delete(key); - } - - fn print_element(key: value.Value, val: value.Value) void { - key.print(); - std.debug.print(":", .{}); - val.print(); - std.debug.print(",", .{}); - - } - pub fn print(self: *const Self) void { - std.debug.print("[", .{}); - self.table.for_each(Self.print_element); - std.debug.print("]", .{}); - } - pub fn eql(self: *const Self, other: *const Self) bool { - return self.table.eql(other.table, value.Value.eql); - } - pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - self.table.deinit(); - allocator.destroy(self.table); - allocator.destroy(self); - } - - }; - - pub const Function = packed struct { - const Self = @This(); - pub const Arg = void; - - obj: Super, - arity: u8, - chunk: *chunk.Chunk, - name: *String, - - pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { - _ = arg; - _ = allocator; - return error.OutOfMemory; - } - - pub fn cast(self: *Self) *Super { - return @ptrCast(self); - } - - pub fn print(self: *const Self) void { - _ = self; - } - - pub fn eql(self: *const Self, other: *const Self) bool { - _ = self; - _ = other; - return false; - } - - pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - _ = self; - _ = allocator; - } - - }; + pub const List = @import("obj/list.zig").List; + pub const String = @import("obj/string.zig").String; + pub const Table = @import("obj/table.zig").Table; + pub const Function = @import("obj/function.zig").Function; pub const Type = enum(u8) { String, diff --git a/zlox/src/obj/function.zig b/zlox/src/obj/function.zig @@ -0,0 +1,42 @@ +const std = @import("std"); +const chunk = @import("../chunk.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 = void; + + obj: Super, + arity: u8, + chunk: *chunk.Chunk, + name: *String, + + pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { + _ = arg; + _ = allocator; + return error.OutOfMemory; + } + + pub fn cast(self: *Self) *Super { + return @ptrCast(self); + } + + pub fn print(self: *const Self) void { + _ = self; + } + + pub fn eql(self: *const Self, other: *const Self) bool { + _ = self; + _ = other; + return false; + } + + pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + _ = self; + _ = allocator; + } + +}; diff --git a/zlox/src/obj/list.zig b/zlox/src/obj/list.zig @@ -0,0 +1,55 @@ +const std = @import("std"); + +const Super = @import("../obj.zig").Obj; +const Error = Super.Error; +const String = Super.String; +const Type = Super.Type; + +pub const List = struct { + const Self = @This(); + const Element = struct { + obj: *Super, + next: ?*@This(), + }; + + tip: ?*Element, + allocator: std.mem.Allocator, + table: String.Table, + + pub fn init(allocator: std.mem.Allocator) Self { + return Self{ .tip = null, .allocator = allocator, .table = String.Table.init(allocator) }; + } + + pub fn push(self: *Self, val: *Super) Error!void { + var new_tip = try self.allocator.create(Element); + new_tip.next = self.tip; + new_tip.obj = val; + self.tip = new_tip; + } + + pub fn emplace(self: *Self, comptime tp: Type, arg: tp.get().Arg) Error!*Super { + var newObj = true; + const obj = switch (tp) { + .String => (try String.intern(arg, &self.table, &newObj, self.allocator)).cast(), + else => try Super.init(tp, arg, self.allocator), + }; + if (newObj) try self.push(obj); + return obj; + } + + pub fn pop(self: *Self) ?*Element { + if (self.tip) |tip| { + self.tip = tip.next; + tip.obj.free(self.allocator); + return tip; + } + return null; + } + + pub fn deinit(self: *Self) void { + while (self.pop()) |tip| { + self.allocator.destroy(tip); + } + self.table.deinit(); + } +}; diff --git a/zlox/src/obj/string.zig b/zlox/src/obj/string.zig @@ -0,0 +1,108 @@ +const std = @import("std"); +const table = @import("../table.zig"); +const hash = @import("../hash.zig"); +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; + + obj: Super, + len: usize = 0, + hash: u32, + + fn data(self: anytype) utils.copy_const(@TypeOf(self), [*]u8) { + const p: utils.copy_const(@TypeOf(self), [*]u8) = @ptrCast(self); + return p + @sizeOf(Self); + } + fn new(arg: Arg, params: ArgParams, allocator: std.mem.Allocator) Error!*Self { + const ret: *Self = @ptrCast(try allocator.alignedAlloc(u8, @alignOf(Self), @sizeOf(Self) + params.len)); + ret.* = Self{ + .obj = Super{ + .type = Super.Type.String, + }, + .hash = params.hash, + }; + for (arg) |el| { + @memcpy(ret.data() + ret.len, el); + ret.len += el.len; + } + return ret; + } + + pub fn slice(self: *const Self) []const u8 { + return self.data()[0..self.len]; + } + pub fn cast(self: *Self) *Super { + return @ptrCast(self); + } + pub fn print(self: *const Self) void { + std.debug.print("\"{s}\"", .{self.slice()}); + } + 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 { + 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 value.Value.init(self.data()[@intFromFloat(index.number)]); + } + + const ArgParams = struct { len: usize, hash: u32 }; + + fn table_check(m_arg: Arg, m_params: ArgParams) struct { + arg: Arg, + params: ArgParams, + pub fn check(self: *const @This(), k2: *const Self) bool { + if (k2.hash == self.params.hash and k2.len == self.params.len) { + var idx: usize = 0; + for (self.arg) |el| { + if (!std.mem.eql(u8, k2.data()[idx .. idx + el.len], el)) + return false; + idx += el.len; + } + return true; + } + return false; + } + } { + return @TypeOf(table_check(m_arg, m_params)){ .arg = m_arg, .params = m_params }; + } + + fn arg_params(arg: Arg) ArgParams { + var ret = ArgParams{ .len = 0, .hash = hash.hash_t([]const u8)(&.{}) }; + + for (arg) |el| { + ret.len += el.len; + ret.hash = hash.hash_append(ret.hash, el); + } + return ret; + } + + pub fn intern(arg: Arg, tabl: *Self.Table, isNewKey: *bool, allocator: std.mem.Allocator) Error!*Self { + const params = arg_params(arg); + + try tabl.checkCapacity(); + const entry = Self.Table.find_(tabl.entries, params.hash, table_check(arg, params)); + isNewKey.* = entry.* != Self.Table.Entry.some; + if (isNewKey.*) { + _ = tabl.set_(entry, try new(arg, params, allocator), {}); + } + return entry.some.key; + } + + pub fn init(_: Arg, _: std.mem.Allocator) Error!*Self { + @compileError("The String Obj has to be interned"); + } + + pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + const p: [*]align(@alignOf(Self)) const u8 = @ptrCast(self); + allocator.free(p[0 .. @sizeOf(Self) + self.len]); + } +}; diff --git a/zlox/src/obj/table.zig b/zlox/src/obj/table.zig @@ -0,0 +1,70 @@ +const std = @import("std"); +const table = @import("../table.zig"); +const hash = @import("../hash.zig"); +const value = @import("../value.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); + + obj: Super, + table: *Self.Table, + hash: u32, + + pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self { + const self: *Self = try allocator.create(Self); + self.* = Self{ + .obj = Super{ + .type = Super.Type.Table, + }, + .table = try allocator.create(Self.Table), + .hash = 0, + }; + self.table.* = Self.Table.init(allocator); + return self; + } + pub fn cast(self: *Self) *Super { + return @ptrCast(self); + } + + pub fn set(self: *Self, key: value.Value, val: value.Value) !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 { + return self.table.get(key); + } + + pub fn delete(self: *Self, key: value.Value) void { + const val = self.table.get(key) catch return; + self.hash -%= hash.hash(key) -% hash.hash(val); + _ = self.table.delete(key); + } + + fn print_element(key: value.Value, val: value.Value) void { + key.print(); + std.debug.print(":", .{}); + val.print(); + std.debug.print(",", .{}); + + } + pub fn print(self: *const Self) void { + std.debug.print("[", .{}); + self.table.for_each(Self.print_element); + std.debug.print("]", .{}); + } + pub fn eql(self: *const Self, other: *const Self) bool { + return self.table.eql(other.table, value.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 @@ -0,0 +1,37 @@ +const std = @import("std"); + +const Super = @import("../obj.zig").Obj; +const Error = Super.Error; + +pub const Template = packed struct { + const Self = @This(); + + pub const Arg = void; + + obj: Super, + pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { + _ = arg; + _ = allocator; + return error.OutOfMemory; + } + + pub fn cast(self: *Self) *Super { + return @ptrCast(self); + } + + pub fn print(self: *const Self) void { + _ = self; + } + + pub fn eql(self: *const Self, other: *const Self) bool { + _ = self; + _ = other; + return false; + } + + pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + _ = self; + _ = allocator; + } +}; + diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig @@ -5,7 +5,7 @@ const std = @import("std"); const debug = @import("debug.zig"); const compiler = @import("compiler.zig"); const Obj = @import("obj.zig").Obj; -const Callback = @import("vm_callbacks.zig"); +const Callback = @import("vm/callbacks.zig"); const table = @import("table.zig"); const hash = @import("hash.zig"); diff --git a/zlox/src/vm/callbacks.zig b/zlox/src/vm/callbacks.zig @@ -0,0 +1,65 @@ +const std = @import("std"); +const Obj = @import("../obj.zig").Obj; +const Value = @import("../value.zig").Value; + +const Number = Value.tagType(.number); +const Bool = Value.tagType(.bool); + +pub const Error = Obj.Error; + +pub fn Type(comptime in_tag: anytype, comptime out_tag: anytype) type { + if (@TypeOf(in_tag) == Obj.Type) { + return struct { + objects: *Obj.List, + _call: *const fn (self: *const @This(), Value.tagType(in_tag), Value.tagType(in_tag)) Error!Value.tagType(out_tag), + pub fn call(self: *const @This(), a: Value.tagType(in_tag), b: Value.tagType(in_tag)) Error!Value.tagType(out_tag) { + return self._call(self, a, b); + } + }; + } else { + return struct { + call: fn (Value.tagType(in_tag), Value.tagType(in_tag)) callconv(.Inline) Error!Value.tagType(out_tag), + }; + } +} + +pub fn concatenate(objects: *Obj.List) Type(Obj.Type.String, Obj.Type.String) { + const Ret = Type(Obj.Type.String, Obj.Type.String); + const ret = Ret{ .objects = objects, ._call = struct { + pub fn concatenate(self: *const Ret, lhs: *Obj, rhs: *Obj) Error!*Obj { + return try self.objects.emplace(.String, &.{ (lhs.cast(.String) catch unreachable).slice(), (rhs.cast(.String) catch unreachable).slice() }); + } + }.concatenate }; + return ret; +} + +pub const add = Type(Value.number, Value.number){ .call = struct { + pub inline fn add(a: Number, b: Number) Error!Number { + return a + b; + } +}.add }; +pub const mul = Type(Value.number, Value.number){ .call = struct { + pub inline fn mul(a: Number, b: Number) Error!Number { + return a * b; + } +}.mul }; +pub const sub = Type(Value.number, Value.number){ .call = struct { + pub inline fn sub(a: Number, b: Number) Error!Number { + return a - b; + } +}.sub }; +pub const div = Type(Value.number, Value.number){ .call = struct { + pub inline fn div(a: Number, b: Number) Error!Number { + return a / b; + } +}.div }; +pub const less = Type(Value.number, Value.bool){ .call = struct { + pub inline fn less(a: Number, b: Number) Error!Bool { + return a < b; + } +}.less }; +pub const more = Type(Value.number, Value.bool){ .call = struct { + pub inline fn more(a: Number, b: Number) Error!Bool { + return a > b; + } +}.more }; diff --git a/zlox/src/vm_callbacks.zig b/zlox/src/vm_callbacks.zig @@ -1,65 +0,0 @@ -const Value = @import("value.zig").Value; -const std = @import("std"); -const Obj = @import("obj.zig").Obj; - -const Number = Value.tagType(.number); -const Bool = Value.tagType(.bool); - -pub const Error = Obj.Error; - -pub fn Type(comptime in_tag: anytype, comptime out_tag: anytype) type { - if (@TypeOf(in_tag) == Obj.Type) { - return struct { - objects: *Obj.List, - _call: *const fn (self: *const @This(), Value.tagType(in_tag), Value.tagType(in_tag)) Error!Value.tagType(out_tag), - pub fn call(self: *const @This(), a: Value.tagType(in_tag), b: Value.tagType(in_tag)) Error!Value.tagType(out_tag) { - return self._call(self, a, b); - } - }; - } else { - return struct { - call: fn (Value.tagType(in_tag), Value.tagType(in_tag)) callconv(.Inline) Error!Value.tagType(out_tag), - }; - } -} - -pub fn concatenate(objects: *Obj.List) Type(Obj.Type.String, Obj.Type.String) { - const Ret = Type(Obj.Type.String, Obj.Type.String); - const ret = Ret{ .objects = objects, ._call = struct { - pub fn concatenate(self: *const Ret, lhs: *Obj, rhs: *Obj) Error!*Obj { - return try self.objects.emplace(.String, &.{ (lhs.cast(.String) catch unreachable).slice(), (rhs.cast(.String) catch unreachable).slice() }); - } - }.concatenate }; - return ret; -} - -pub const add = Type(Value.number, Value.number){ .call = struct { - pub inline fn add(a: Number, b: Number) Error!Number { - return a + b; - } -}.add }; -pub const mul = Type(Value.number, Value.number){ .call = struct { - pub inline fn mul(a: Number, b: Number) Error!Number { - return a * b; - } -}.mul }; -pub const sub = Type(Value.number, Value.number){ .call = struct { - pub inline fn sub(a: Number, b: Number) Error!Number { - return a - b; - } -}.sub }; -pub const div = Type(Value.number, Value.number){ .call = struct { - pub inline fn div(a: Number, b: Number) Error!Number { - return a / b; - } -}.div }; -pub const less = Type(Value.number, Value.bool){ .call = struct { - pub inline fn less(a: Number, b: Number) Error!Bool { - return a < b; - } -}.less }; -pub const more = Type(Value.number, Value.bool){ .call = struct { - pub inline fn more(a: Number, b: Number) Error!Bool { - return a > b; - } -}.more };