DzLox

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

commit 5db367d76d8508a2a93089780380792516d022af
parent 4d66bf9b40763f7ab7a28945c135076352f5616d
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date:   Thu,  8 Aug 2024 10:21:52 +0200

Function boilerplate

Diffstat:
Mzlox/src/comptime_utils.zig | 16++++++++++++++++
Mzlox/src/hash.zig | 1+
Mzlox/src/obj.zig | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mzlox/src/value.zig | 22+++++++++++++++-------
Mzlox/src/vm.zig | 16+++++++++++-----
5 files changed, 105 insertions(+), 12 deletions(-)

diff --git a/zlox/src/comptime_utils.zig b/zlox/src/comptime_utils.zig @@ -1,5 +1,21 @@ +const std = @import("std"); + pub fn copy_const(T: type, U: type) type { comptime var info = @typeInfo(U); info.Pointer.is_const = @typeInfo(T).Pointer.is_const; return @Type(info); } + +pub fn typeFromTag(T: type, comptime tag: std.meta.Tag(T)) type { + return @TypeOf(@field(@unionInit(T, @tagName(tag), undefined), @tagName(tag))); + +} + +pub fn tagFromType(T: type, U: type) std.meta.Tag(T) { + inline for (@typeInfo(T).Union.fields) |field| { + if (U == field.type) { + return @field(T, field.name); + } + } + @compileError("No matching tag for type " ++ @typeName(U) ++ " in Union " ++ @typeName(T)); +} diff --git a/zlox/src/hash.zig b/zlox/src/hash.zig @@ -45,6 +45,7 @@ pub fn hash_t(T: type) fn (T) u32 { return switch (val.type) { .String => hash_append_t([]const u8)(hash(val.cast(.String) catch unreachable), "\x01"), .Table => hash_append_t([]const u8)(hash(val.cast(.Table) catch unreachable), "\x02"), + inline else => |tag| @panic("hash_t(Obj." ++ @tagName(tag) ++ "): Unsupported type"), }; } }.fun, diff --git a/zlox/src/obj.zig b/zlox/src/obj.zig @@ -3,6 +3,7 @@ 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"); pub const Obj = packed struct { const Super = @This(); @@ -10,6 +11,30 @@ pub const Obj = packed struct { 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 { @@ -222,9 +247,46 @@ pub const Obj = packed struct { }; + 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 Type = enum(u8) { String, Table, + Function, pub fn get(comptime self: @This()) type { return @field(Super, @tagName(self)); diff --git a/zlox/src/value.zig b/zlox/src/value.zig @@ -1,6 +1,7 @@ const std = @import("std"); const array = @import("array.zig"); const Obj = @import("obj.zig").Obj; +const utils = @import("comptime_utils.zig"); pub const Value = union(enum) { number: f64, @@ -21,15 +22,22 @@ pub const Value = union(enum) { } } + pub fn tagNameOf(T: type) []const u8 { + return @tagName(utils.tagFromType(@This(), T)); + } + + pub fn typeName(self: @This()) []const u8 { + return switch (self) { + .obj => |o| @tagName(o.type), + inline else => |tp| tagNameOf(@TypeOf(tp)), + }; + } + pub fn init(val: anytype) @This() { - inline for (@typeInfo(@This()).Union.fields) |field| { - if (@TypeOf(val) == field.type) { - return @unionInit(@This(), field.name, val); - } - } - @compileError("Invalid Value type"); + return @unionInit(@This(), tagNameOf(@TypeOf(val)), val); } + fn toTag(comptime from: anytype) Tag { return if (@TypeOf(from) == Obj.Type) .obj @@ -53,7 +61,7 @@ pub const Value = union(enum) { } pub fn tagType(comptime tag: anytype) type { - return @TypeOf(@field(@unionInit(@This(), @tagName(toTag(tag)), undefined), @tagName(toTag(tag)))); + return utils.typeFromTag(@This(), toTag(tag)); } pub const ParseNumberError = std.fmt.ParseFloatError; diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig @@ -61,7 +61,7 @@ pub const VM = struct { fn Interpreter(size: comptime_int) type { return struct { ip: [*]const u8, - chunk: *Chunk, + chunk: *const Chunk, stackTop: [*]Value, stack: [size]Value, vm: *VM, @@ -208,12 +208,18 @@ pub const VM = struct { @intFromEnum(OP.GET_INDEX) => { const key = self.pop(); const obj = self.pop(); - if (obj.is(Obj.Type.Table) or obj.is(Obj.Type.String)) { + var pushed = false; + if (obj.is(Value.obj)) { switch(obj.obj.type) { - inline else => |tp| self.push((obj.obj.cast(tp) catch unreachable).get(key) catch Value.init({})), + .Function => {}, + inline else => |tp| { + self.push((obj.obj.cast(tp) catch unreachable).get(key) catch Value.init({})); + pushed = true; + }, } - } else { - self.runtimeError("Cannot index a non-map value", .{}); + } + if (!pushed) { + self.runtimeError("Cannot index a value of type {s}", .{obj.typeName()}); return InterpreterError.RuntimeError; } },