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:
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;