DzLox

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

commit d4f440b41b027c3333067b328ce19a5c3bab6aa1
parent ea03f224ef9647514545a56168f6bf065039bce4
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date:   Fri,  6 Dec 2024 15:09:40 +0100

Additional fields for Obj

Diffstat:
Mzlox/src/chunk.zig | 1-
Mzlox/src/compiler.zig | 2+-
Mzlox/src/comptime_utils.zig | 18++++++++++++++++++
Mzlox/src/debug.zig | 2+-
Mzlox/src/gc.zig | 42++++++++++++++++++++++++++++++++++++++++--
Mzlox/src/hash.zig | 2+-
Mzlox/src/obj.zig | 153++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mzlox/src/obj/closure.zig | 98++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mzlox/src/obj/function.zig | 106++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mzlox/src/obj/list.zig | 149+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mzlox/src/obj/native.zig | 100++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mzlox/src/obj/string.zig | 164++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mzlox/src/obj/table.zig | 126++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mzlox/src/obj/template.zig | 76+++++++++++++++++++++++++++++++++++++++-------------------------------------
Mzlox/src/obj/upvalue.zig | 92++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mzlox/src/table.zig | 3+++
Mzlox/src/value.zig | 9+--------
Mzlox/src/vm.zig | 2+-
Mzlox/src/vm/callbacks.zig | 2+-
Mzlox/src/vm/native.zig | 2+-
20 files changed, 607 insertions(+), 542 deletions(-)

diff --git a/zlox/src/chunk.zig b/zlox/src/chunk.zig @@ -1,7 +1,6 @@ const std = @import("std"); const Value = @import("value.zig").Value; const array = @import("array.zig"); -const Obj = @import("obj.zig").Obj; pub const OP = enum(u8) { CONSTANT, diff --git a/zlox/src/compiler.zig b/zlox/src/compiler.zig @@ -4,8 +4,8 @@ const Chunk = @import("chunk.zig").Chunk; const OP = @import("chunk.zig").OP; const Value = @import("value.zig").Value; const ValueArray = @import("value.zig").ValueArray; -const Obj = @import("obj.zig").Obj; const GC = @import("gc.zig").GC; +const Obj = GC.Obj; const debug = @import("debug.zig"); const Token = scanner.TokenType; const vm_native = @import("vm/native.zig"); diff --git a/zlox/src/comptime_utils.zig b/zlox/src/comptime_utils.zig @@ -37,3 +37,21 @@ pub fn if_not_null(comptime fun: anytype) fn (?param_type(fun, 0)) void { } }.function; } + +pub fn make_packed(s: type) type { + const oldFields = @typeInfo(s).@"struct".fields; + var newFields: [oldFields.len]std.builtin.Type.StructField = undefined; + + for (oldFields, &newFields) |oldField, *newField| { + newField.* = oldField; + newField.alignment = 0; + newField.is_comptime = false; + } + + return @Type(std.builtin.Type{.@"struct" = .{ + .layout = std.builtin.Type.ContainerLayout.@"packed", + .fields = &newFields, + .decls = &[_]std.builtin.Type.Declaration{}, + .is_tuple = false + }}); +} diff --git a/zlox/src/debug.zig b/zlox/src/debug.zig @@ -1,7 +1,7 @@ const std = @import("std"); const chunk = @import("chunk.zig"); const value = @import("value.zig"); -const Obj = @import("obj.zig").Obj; +const Obj = @import("gc.zig").GC.Obj; const print = std.debug.print; const Error = Obj.Error; diff --git a/zlox/src/gc.zig b/zlox/src/gc.zig @@ -1,10 +1,12 @@ 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 { + + pub const Obj = @import("obj.zig").Obj(.{.mark = false}); + const Self = @This(); const List = list.List(*Obj); @@ -44,7 +46,7 @@ pub const GC = struct { }; if (newObj) { if (DBG_STRESS) { - // self.collect(); + self.collect(); } dbg_print("Allocating {} at 0x{x}: {s}\n", .{obj.obj.type, @intFromPtr(obj), obj}); try self.list.push(obj.cast()); @@ -52,6 +54,42 @@ pub const GC = struct { return obj; } + pub fn markTable(table: anytype) void { + const Table = @TypeOf(table); + table.for_each({}, struct{ + pub fn fun(key: Table.Key, val: Table.Value) void { + Self.mark(key); + Self.mark(val); + } + }.fun); + + } + + pub fn markArray(arr: anytype) void { + for(arr) |el| { + Self.mark(el); + } + } + + pub fn mark(arg: anytype) void { + const T = @TypeOf(arg); + switch(T) { + Value => switch(arg) { + .obj => |o| { + mark(o); + }, + else => {} + }, + *Obj => { + dbg_print("Marking {} at 0x{x}: {s}\n", .{arg.type, @intFromPtr(arg), arg}); + arg.fields.mark = true; + }, + else => if(Obj.isChild(T)) { + mark(arg.cast()); + } + } + } + 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(); } diff --git a/zlox/src/hash.zig b/zlox/src/hash.zig @@ -1,4 +1,4 @@ -const Obj = @import("obj.zig").Obj; +const Obj = @import("gc.zig").GC.Obj; const Value = @import("value.zig").Value; pub fn hash_append_t(T: type) fn (u32, T) u32 { diff --git a/zlox/src/obj.zig b/zlox/src/obj.zig @@ -2,96 +2,99 @@ const std = @import("std"); const utils = @import("comptime_utils.zig"); fn nameOf(fqn: []const u8) []const u8 { - if (std.mem.lastIndexOf(u8, fqn, ".")) |index| { - return fqn[index + 1 ..]; + var lastDot = 0; + for(fqn, 0..) |c, i| { + if (c == '.') lastDot = i + 1; + if (c == '(') return fqn[lastDot..i]; } return fqn; } -pub const Obj = packed struct { - const Self = @This(); +pub fn Obj(fields: anytype) type { + return packed struct { + const Self = @This(); - type: Type, - marked: bool, + type: Type, + fields: utils.make_packed(@TypeOf(fields)) = fields, - 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 Native = @import("obj/native.zig").Native; - pub const Closure = @import("obj/closure.zig").Closure; - pub const Upvalue = @import("obj/upvalue.zig").Upvalue; + pub const List = @import("obj/list.zig").List(fields); + pub const String = @import("obj/string.zig").String(fields); + pub const Table = @import("obj/table.zig").Table(fields); + pub const Function = @import("obj/function.zig").Function(fields); + pub const Native = @import("obj/native.zig").Native(fields); + pub const Closure = @import("obj/closure.zig").Closure(fields); + pub const Upvalue = @import("obj/upvalue.zig").Upvalue(fields); - pub const Error = error {IllegalCastError} - || List.Error - || String.Error - || Table.Error - || Function.Error - || Native.Error - || List.Error - || Closure.Error - || Upvalue.Error; + 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, - Function, - Native, - List, - Closure, - Upvalue, + pub const Type = enum(u8) { + String, + Table, + Function, + Native, + List, + Closure, + Upvalue, - pub fn get(comptime self: @This()) type { - return @field(Self, @tagName(self)); - } - }; - - pub fn make(child: type) Self { - return Self { - .type = @field(Type, nameOf(@typeName(child))), - .marked = false + pub fn get(comptime self: @This()) type { + return @field(Self, @tagName(self)); + } }; - } - pub fn mark(self: *Self) void { - self.marked = true; - switch (self.type) { - inline .List, .Table => |tp| self._cast(tp).mark(), - else => {} + pub fn isChild(T: type) bool { + inline for(@typeInfo(Type).@"enum".fields) |field| { + const U = @field(Self, field.name); + if (T == U or T == *U or T == *const U) return true; + } + return false; } - } - pub fn init(comptime tp: Type, arg: tp.get().Arg, allocator: std.mem.Allocator) !*Self { - return (try tp.get().init(arg, allocator)).cast(); - } + pub fn make(child: type) Self { + return Self { + .type = @field(Type, nameOf(@typeName(child))), + }; + } - pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { - switch (self.type) { - inline else => |tp| try self._cast(tp).format(fmt, options, writer), + pub fn init(comptime tp: Type, arg: tp.get().Arg, allocator: std.mem.Allocator) !*Self { + return (try tp.get().init(arg, allocator)).cast(); } - } - pub fn eql(self: *const Self, other: *const Self) bool { - if (!self.is(other.type)) return false; - return switch (self.type) { - inline else => |tp| self._cast(tp).eql(other._cast(tp)), - }; - } - pub fn free(obj: *Self, allocator: std.mem.Allocator) void { - return switch (obj.type) { - inline else => |tp| obj._cast(tp).free(allocator), - }; - } - pub fn is(self: *const Self, tp: Type) bool { - return self.type == tp; - } + pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { + switch (self.type) { + inline else => |tp| try self._cast(tp).format(fmt, options, writer), + } + } + pub fn eql(self: *const Self, other: *const Self) bool { + if (!self.is(other.type)) return false; + return switch (self.type) { + inline else => |tp| self._cast(tp).eql(other._cast(tp)), + }; + } + pub fn free(obj: *Self, allocator: std.mem.Allocator) void { + return switch (obj.type) { + inline else => |tp| obj._cast(tp).free(allocator), + }; + } - pub fn cast(self: anytype, comptime tp: Type) Error!utils.copy_const(@TypeOf(self), *tp.get()) { - if (!self.is(tp)) return Error.IllegalCastError; - return self._cast(tp); - } + pub fn is(self: *const Self, tp: Type) bool { + return self.type == tp; + } - fn _cast(self: anytype, comptime tp: Type) utils.copy_const(@TypeOf(self), *tp.get()) { - return @ptrCast(@alignCast(self)); - } -}; + pub fn cast(self: anytype, comptime tp: Type) Error!utils.copy_const(@TypeOf(self), *tp.get()) { + if (!self.is(tp)) return Error.IllegalCastError; + return self._cast(tp); + } + + fn _cast(self: anytype, comptime tp: Type) utils.copy_const(@TypeOf(self), *tp.get()) { + return @ptrCast(@alignCast(self)); + } + }; +} diff --git a/zlox/src/obj/closure.zig b/zlox/src/obj/closure.zig @@ -1,52 +1,54 @@ const std = @import("std"); const utils = @import("../comptime_utils.zig"); -const Super = @import("../obj.zig").Obj; - -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, - upvalues: [*]?*Super.Upvalue, - upvalues_len: u8, - - pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { - const self: *Self = try allocator.create(Self); - self.* = Self{ - .obj = Super.make(Self), - .upvalues = (try allocator.alloc(?*Super.Upvalue, arg.upvalue_count)).ptr, - .upvalues_len = arg.upvalue_count, - .function = arg, - }; - for(self.upvalues[0..self.upvalues_len]) - |*upvalue| upvalue.* = null; - return self; - } - - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } - - pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - _ = try writer.write("<C: "); - if (self.function.name) |name| { - _ = try writer.write(name.slice()); - } else { - _ = try writer.write("-"); +pub fn Closure(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); + + return packed struct { + const Self = @This(); + + pub const Arg = *const Super.Function; + pub const Error = error { OutOfMemory }; + + obj: Super, + function: *const Super.Function, + upvalues: [*]?*Super.Upvalue, + upvalues_len: u8, + + pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { + const self: *Self = try allocator.create(Self); + self.* = Self{ + .obj = Super.make(Self), + .upvalues = (try allocator.alloc(?*Super.Upvalue, arg.upvalue_count)).ptr, + .upvalues_len = arg.upvalue_count, + .function = arg, + }; + for(self.upvalues[0..self.upvalues_len]) + |*upvalue| upvalue.* = null; + return self; } - _ = try writer.writeAll(">"); - } - - pub fn eql(_: *const Self, _: *const Self) bool { - return false; - } - - pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - allocator.free(self.upvalues[0..self.upvalues_len]); - allocator.destroy(self); - } -}; + + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); + } + + pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + _ = try writer.write("<C: "); + if (self.function.name) |name| { + _ = try writer.write(name.slice()); + } else { + _ = try writer.write("-"); + } + _ = try writer.writeAll(">"); + } + + pub fn eql(_: *const Self, _: *const Self) bool { + return false; + } + + pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + allocator.free(self.upvalues[0..self.upvalues_len]); + allocator.destroy(self); + } + }; +} diff --git a/zlox/src/obj/function.zig b/zlox/src/obj/function.zig @@ -2,65 +2,67 @@ const std = @import("std"); const chunk = @import("../chunk.zig"); const utils = @import("../comptime_utils.zig"); -const Super = @import("../obj.zig").Obj; -const String = Super.String; +pub fn Function(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); + const String = Super.String; -pub const Function = packed struct { - const Self = @This(); - pub const Arg = Type; - pub const Error = error { OutOfMemory }; + return packed struct { + const Self = @This(); + pub const Arg = Type; + pub const Error = error { OutOfMemory }; - pub const Type = enum(u8) { - Function, - Script - }; - - obj: Super, - arity: u8, - chunk: *chunk.Chunk, - name: ?*const String, - type: Type, - upvalue_count: u8, - - pub fn init(tp: Arg, allocator: std.mem.Allocator) Error!*Self { - const self: *Self = try allocator.create(Self); - self.* = Self{ - .obj = Super.make(Self), - .chunk = try allocator.create(chunk.Chunk), - .arity = 0, - .name = null, - .type = tp, - .upvalue_count = 0, + pub const Type = enum(u8) { + Function, + Script }; - self.chunk.* = try chunk.Chunk.init(allocator); - return self; - } - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } + obj: Super, + arity: u8, + chunk: *chunk.Chunk, + name: ?*const String, + type: Type, + upvalue_count: u8, - pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - switch(self.type) { - .Function => _ = try writer.write("<F: "), - .Script => _ = try writer.write("<S: "), + pub fn init(tp: Arg, allocator: std.mem.Allocator) Error!*Self { + const self: *Self = try allocator.create(Self); + self.* = Self{ + .obj = Super.make(Self), + .chunk = try allocator.create(chunk.Chunk), + .arity = 0, + .name = null, + .type = tp, + .upvalue_count = 0, + }; + self.chunk.* = try chunk.Chunk.init(allocator); + return self; } - if (self.name) |name| { - _ = try writer.write(name.slice()); - } else { - _ = try writer.write("-"); + + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); } - _ = try writer.writeAll(">"); - } - pub fn eql(_: *const Self, _: *const Self) bool { - return false; - } + pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + switch(self.type) { + .Function => _ = try writer.write("<F: "), + .Script => _ = try writer.write("<S: "), + } + if (self.name) |name| { + _ = try writer.write(name.slice()); + } else { + _ = try writer.write("-"); + } + _ = try writer.writeAll(">"); + } - pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - self.chunk.deinit(); - allocator.destroy(self.chunk); - allocator.destroy(self); - } + pub fn eql(_: *const Self, _: *const Self) bool { + return false; + } + + pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + self.chunk.deinit(); + allocator.destroy(self.chunk); + allocator.destroy(self); + } -}; + }; +} diff --git a/zlox/src/obj/list.zig b/zlox/src/obj/list.zig @@ -1,93 +1,90 @@ const std = @import("std"); const Value = @import("../value.zig").Value; -const Super = @import("../obj.zig").Obj; const utils = @import("../comptime_utils.zig"); const list = @import("../list.zig"); -const String = Super.String; -const Type = Super.Type; - -pub const List = packed struct { - const Self = @This(); - - pub const List = list.List(Value); - pub const Arg = void; - pub const Error = error { OutOfMemory, InvalidArgument } || Self.List.Error; - - obj: Super, - list: *Self.List, - - pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self { - const self: *Self = try allocator.create(Self); - self.* = Self{ - .obj = Super.make(Self), - .list = try allocator.create(Self.List) - }; - self.list.* = Self.List.init(allocator); - return self; - } - - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } - - pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) utils.fn_error(@TypeOf(writer).write)!void { - const Printer = struct { - options: std.fmt.FormatOptions, - writer: @TypeOf(writer), - count: usize, - - pub fn print(this: *@This(), val: ?Value) utils.fn_error(@TypeOf(writer).write)!void { - this.count -= 1; - if (val) |v| { - try v.format(fmt, this.options, this.writer); - } else { - _ = try this.writer.write("-"); - } - if (this.count > 0) _ = try this.writer.write(", "); - } - }; +pub fn List(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); - var printer = Printer{.options = options, .writer = writer, .count = self.list.len}; + return packed struct { + const Self = @This(); - _ = try writer.write("["); - try self.list.for_each_try(&printer, Printer.print); - _ = try writer.writeAll("]"); - } + pub const List = list.List(Value); + pub const Arg = void; + pub const Error = error { OutOfMemory, InvalidArgument } || Self.List.Error; - pub fn mark(self: *Self) void { - self.list.for_each({}, utils.if_not_null(Value.mark)); - } + obj: Super, + list: *Self.List, - pub fn eql(self: *const Self, other: *const Self) bool { - return self.list.eql(other.list, Value.eql); - } + pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self { + const self: *Self = try allocator.create(Self); + self.* = Self{ + .obj = Super.make(Self), + .list = try allocator.create(Self.List) + }; + self.list.* = Self.List.init(allocator); + return self; + } - pub fn free(self: *Self, allocator: std.mem.Allocator) void { - self.list.free(); - allocator.destroy(self.list); - allocator.destroy(self); - } + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); + } - 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; + pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) utils.fn_error(@TypeOf(writer).write)!void { + const Printer = struct { + options: std.fmt.FormatOptions, + writer: @TypeOf(writer), + count: usize, + + pub fn print(this: *@This(), val: ?Value) utils.fn_error(@TypeOf(writer).write)!void { + this.count -= 1; + if (val) |v| { + try v.format(fmt, this.options, this.writer); + } else { + _ = try this.writer.write("-"); + } + if (this.count > 0) _ = try this.writer.write(", "); + } + + }; + + var printer = Printer{.options = options, .writer = writer, .count = self.list.len}; + + _ = try writer.write("["); + try self.list.for_each_try(&printer, Printer.print); + _ = try writer.writeAll("]"); } - self.list.delete(@intFromFloat(index.number)); - } - 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; + pub fn eql(self: *const Self, other: *const Self) bool { + return self.list.eql(other.list, Value.eql); } - return self.list.get(@intFromFloat(index.number)); - } - pub fn set(self: *Self, index: Value, val: Value) Error!void { - if (!index.is(Value.number) or index.number < 0) { - return Error.InvalidArgument; + pub fn free(self: *Self, allocator: std.mem.Allocator) void { + self.list.free(); + allocator.destroy(self.list); + allocator.destroy(self); + } + + 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 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; + } + return self.list.get(@intFromFloat(index.number)); + } + + pub fn set(self: *Self, index: Value, val: Value) Error!void { + if (!index.is(Value.number) or index.number < 0) { + return Error.InvalidArgument; + } + _ = try self.list.set(@intFromFloat(index.number), val); } - _ = try self.list.set(@intFromFloat(index.number), val); - } -}; + }; +} diff --git a/zlox/src/obj/native.zig b/zlox/src/obj/native.zig @@ -3,64 +3,66 @@ const std = @import("std"); const utils = @import("../comptime_utils.zig"); const GC = @import("../gc.zig").GC; const Value = @import("../value.zig").Value; -const Super = @import("../obj.zig").Obj; -pub const Native = packed struct { - const Self = @This(); - pub const Error = error { OutOfMemory, Native }; +pub fn Native(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); - pub const Fn = *const fn (*GC, []const Value) Error!Value; + return packed struct { + const Self = @This(); + pub const Error = error { OutOfMemory, Native }; - pub const ArityMin = 0; - pub const ArityMax = std.math.maxInt(u8); + pub const Fn = *const fn (*GC, []const Value) Error!Value; - pub const Arg = struct { - fun: Fn, - arity_min: u8 = ArityMin, - arity_max: u8 = ArityMax, - name: []const u8 = "" - }; - - obj: Super, - fun: Fn, - arity_min: u8, - arity_max: u8, - name: [*]const u8, - name_len: usize, + pub const ArityMin = 0; + pub const ArityMax = std.math.maxInt(u8); - pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { - const self: *Self = try allocator.create(Self); - self.* = Self{ - .obj = Super.make(Self), - .fun = arg.fun, - .arity_min = arg.arity_min, - .arity_max = arg.arity_max, - .name = arg.name.ptr, - .name_len = arg.name.len + pub const Arg = struct { + fun: Fn, + arity_min: u8 = ArityMin, + arity_max: u8 = ArityMax, + name: []const u8 = "" }; - return self; - } - pub fn call(self: *const Self, gc: *GC, argCount: u8, args: [*]Value) Error!Value { - return self.fun(gc, args[0..argCount]); - } + obj: Super, + fun: Fn, + arity_min: u8, + arity_max: u8, + name: [*]const u8, + name_len: usize, + + pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { + const self: *Self = try allocator.create(Self); + self.* = Self{ + .obj = Super.make(Self), + .fun = arg.fun, + .arity_min = arg.arity_min, + .arity_max = arg.arity_max, + .name = arg.name.ptr, + .name_len = arg.name.len + }; + return self; + } - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } + pub fn call(self: *const Self, gc: *GC, argCount: u8, args: [*]Value) Error!Value { + return self.fun(gc, args[0..argCount]); + } - pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - _ = try writer.write("<N: "); - _ = try writer.write(self.name[0..self.name_len]); - _ = try writer.writeAll(">"); - } + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); + } - pub fn eql(_: *const Self, _: *const Self) bool { - return false; - } + pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + _ = try writer.write("<N: "); + _ = try writer.write(self.name[0..self.name_len]); + _ = try writer.writeAll(">"); + } - pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - allocator.destroy(self); - } -}; + pub fn eql(_: *const Self, _: *const Self) bool { + return false; + } + pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + allocator.destroy(self); + } + }; +} diff --git a/zlox/src/obj/string.zig b/zlox/src/obj/string.zig @@ -4,105 +4,107 @@ const hash = @import("../hash.zig"); const utils = @import("../comptime_utils.zig"); const value = @import("../value.zig"); -const Super = @import("../obj.zig").Obj; +pub fn String(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); -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; + return 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, - hash: u32, + 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.make(Self), - .hash = params.hash, - }; - for (arg) |el| { - @memcpy(ret.data() + ret.len, el); - ret.len += el.len; + 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.make(Self), + .hash = params.hash, + }; + for (arg) |el| { + @memcpy(ret.data() + ret.len, el); + ret.len += el.len; + } + return ret; } - return ret; - } - pub fn slice(self: *const Self) []const u8 { - return self.data()[0..self.len]; - } + pub fn slice(self: *const Self) []const u8 { + return self.data()[0..self.len]; + } - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); + } - pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - _ = try writer.writeAll(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) 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.IndexOutOfBounds; + pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + _ = try writer.writeAll(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) 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.IndexOutOfBounds; + } + return value.Value.init(self.data()[@intFromFloat(index.number)]); } - return value.Value.init(self.data()[@intFromFloat(index.number)]); - } - const ArgParams = struct { len: usize, hash: u32 }; + 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; + 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 true; + return false; } - return false; + } { + return @TypeOf(table_check(m_arg, m_params)){ .arg = m_arg, .params = m_params }; } - } { - 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)(&.{}) }; + 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); + for (arg) |el| { + ret.len += el.len; + ret.hash = hash.hash_append(ret.hash, el); + } + return ret; } - return ret; - } - pub fn intern(arg: Arg, tabl: *Self.Table, isNewKey: *bool, allocator: std.mem.Allocator) Error!*Self { - const params = arg_params(arg); + 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), {}); + 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; } - return entry.some.key; - } - pub fn init(_: Arg, _: std.mem.Allocator) Error!*Self { - @compileError("The String Obj has to be interned"); - } + 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 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 @@ -4,80 +4,82 @@ const hash = @import("../hash.zig"); const Value = @import("../value.zig").Value; const utils = @import("../comptime_utils.zig"); -const Super = @import("../obj.zig").Obj; +pub fn Table(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); -pub const Table = packed struct { - const Self = @This(); - pub const Arg = void; - const Table = table.Table(Value, Value, hash.hash_t(Value), Value.eql); - pub const Error = error { OutOfMemory } || Self.Table.Error; + return packed struct { + const Self = @This(); + pub const Arg = void; + 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, - len: usize, + obj: Super, + table: *Self.Table, + len: usize, - pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self { - const self: *Self = try allocator.create(Self); - self.* = Self{ - .obj = Super.make(Self), - .table = try allocator.create(Self.Table), - .len = 0, - }; - self.table.* = Self.Table.init(allocator); - return self; - } + pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self { + const self: *Self = try allocator.create(Self); + self.* = Self{ + .obj = Super.make(Self), + .table = try allocator.create(Self.Table), + .len = 0, + }; + self.table.* = Self.Table.init(allocator); + return self; + } - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); + } - pub fn set(self: *Self, key: Value, val: Value) Error!bool { - self.len += 1; - return self.table.set(key, val); - } + pub fn set(self: *Self, key: Value, val: Value) Error!bool { + self.len += 1; + return self.table.set(key, val); + } - pub fn get(self: *Self, key: Value) Error!Value { - return self.table.get(key); - } + pub fn get(self: *Self, key: Value) Error!Value { + return self.table.get(key); + } - pub fn delete(self: *Self, key: Value) void { - if (self.table.delete(key)) self.len -= 1; - } + pub fn delete(self: *Self, key: Value) void { + if (self.table.delete(key)) self.len -= 1; + } - 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 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, val: Value) utils.fn_error(@TypeOf(writer).write)!void { - this.count -= 1; + 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); - _ = try this.writer.write(":"); - try val.format(fmt, this.options, this.writer); - if (this.count > 0) _ = try this.writer.write(", "); - } + try key.format(fmt, this.options, this.writer); + _ = try this.writer.write(":"); + try val.format(fmt, this.options, this.writer); + if (this.count > 0) _ = try this.writer.write(", "); + } - }; + }; - var printer = Printer{.options = options, .writer = writer, .count = self.len}; - _ = try writer.write("["); - if (self.table.count > 0) { - try self.table.for_each_try(&printer, Printer.print); - } else { - _ = try writer.write(":"); + var printer = Printer{.options = options, .writer = writer, .count = self.len}; + _ = try writer.write("["); + if (self.table.count > 0) { + try self.table.for_each_try(&printer, Printer.print); + } else { + _ = try writer.write(":"); + } + _ = try writer.writeAll("]"); } - _ = try writer.writeAll("]"); - } - pub fn eql(self: *const Self, other: *const Self) bool { - return self.table.eql(other.table, Value.eql); - } + pub fn eql(self: *const Self, other: *const Self) bool { + 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); - } -}; + 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 @@ -1,41 +1,43 @@ const std = @import("std"); const utils = @import("../comptime_utils.zig"); -const Super = @import("../obj.zig").Obj; - -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; - } - - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } - - pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { - _ = self; - _ = fmt; - _ = options; - _ = writer; - } - - 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 fn Template(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); + + return 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; + } + + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); + } + + pub fn format(self: *const Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { + _ = self; + _ = fmt; + _ = options; + _ = writer; + } + + 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/upvalue.zig b/zlox/src/obj/upvalue.zig @@ -2,55 +2,57 @@ const std = @import("std"); const utils = @import("../comptime_utils.zig"); const Value = @import("../value.zig").Value; -const Super = @import("../obj.zig").Obj; - -pub const Upvalue = packed struct { - const Self = @This(); - - pub const Arg = struct {val: *Value, slot: u8}; - pub const Error = error { OutOfMemory }; - - obj: Super, - location: *Value, - closed: bool, - slot: u8, - - pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { - const self: *Self = try allocator.create(Self); - self.* = Self{ - .obj = Super.make(Self), - .location = arg.val, - .closed = false, - .slot = arg.slot - }; - return self; - } - - pub fn close(self: *Self, allocator: std.mem.Allocator) Error!void { - if (!self.closed) { - const new = try allocator.create(Value); - new.* = self.location.*; - self.location = new; - self.closed = true; + +pub fn Upvalue(fields: anytype) type { + const Super = @import("../obj.zig").Obj(fields); + + return packed struct { + const Self = @This(); + + pub const Arg = struct {val: *Value, slot: u8}; + pub const Error = error { OutOfMemory }; + + obj: Super, + location: *Value, + closed: bool, + slot: u8, + + pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self { + const self: *Self = try allocator.create(Self); + self.* = Self{ + .obj = Super.make(Self), + .location = arg.val, + .closed = false, + .slot = arg.slot + }; + return self; } - } + pub fn close(self: *Self, allocator: std.mem.Allocator) Error!void { + if (!self.closed) { + const new = try allocator.create(Value); + new.* = self.location.*; + self.location = new; + self.closed = true; + } + } - pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { - return @ptrCast(self); - } - pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - try writer.print("<Upvalue{{{} at 0x{x}, {}, {}}}>", .{self.location.*, @intFromPtr(self.location), self.closed, self.slot}); - } + pub fn cast(self: anytype) utils.copy_const(@TypeOf(self), *Super) { + return @ptrCast(self); + } - pub fn eql(_: *const Self, _: *const Self) bool { - return false; - } + pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + try writer.print("<Upvalue{{{} at 0x{x}, {}, {}}}>", .{self.location.*, @intFromPtr(self.location), self.closed, self.slot}); + } - pub fn free(self: *const Self, allocator: std.mem.Allocator) void { - if (self.closed) allocator.destroy(self.location); - allocator.destroy(self); - } -}; + pub fn eql(_: *const Self, _: *const Self) bool { + return false; + } + pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + if (self.closed) allocator.destroy(self.location); + allocator.destroy(self); + } + }; +} diff --git a/zlox/src/table.zig b/zlox/src/table.zig @@ -8,6 +8,9 @@ pub fn Table(K: type, V: type, hash_fn: fn (K) u32, cmp_fn: fn (K, K) bool) type pub const Error = error{ OutOfMemory, KeyError }; + pub const Key = K; + pub const Value = V; + pub const Entry = union(enum) { const Some = struct { key: K, diff --git a/zlox/src/value.zig b/zlox/src/value.zig @@ -1,6 +1,6 @@ const std = @import("std"); const array = @import("array.zig"); -const Obj = @import("obj.zig").Obj; +const Obj = @import("gc.zig").GC.Obj; const utils = @import("comptime_utils.zig"); pub const Value = union(enum) { @@ -91,11 +91,4 @@ pub const Value = union(enum) { .obj => |x| x.eql(other.obj), }; } - - pub fn mark(self: Self) void { - switch(self) { - .obj => |x| x.mark(), - else => {} - } - } }; diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig @@ -4,8 +4,8 @@ const Value = @import("value.zig").Value; const std = @import("std"); const debug = @import("debug.zig"); const compiler = @import("compiler.zig"); -const Obj = @import("obj.zig").Obj; const GC = @import("gc.zig").GC; +const Obj = GC.Obj; const Callback = @import("vm/callbacks.zig"); const table = @import("table.zig"); const list = @import("list.zig"); diff --git a/zlox/src/vm/callbacks.zig b/zlox/src/vm/callbacks.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const Obj = @import("../obj.zig").Obj; const GC = @import("../gc.zig").GC; +const Obj = GC.Obj; const Value = @import("../value.zig").Value; const Number = Value.tagType(.number); diff --git a/zlox/src/vm/native.zig b/zlox/src/vm/native.zig @@ -2,7 +2,7 @@ const std = @import("std"); const GC = @import("../gc.zig").GC; const Value = @import("../value.zig").Value; -pub const Error = @import("../obj.zig").Obj.Native.Error; +pub const Error = GC.Obj.Native.Error; pub const Clock = struct { var start: std.time.Instant = undefined;