commit 5db367d76d8508a2a93089780380792516d022af
parent 4d66bf9b40763f7ab7a28945c135076352f5616d
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date: Thu, 8 Aug 2024 10:21:52 +0200
Function boilerplate
Diffstat:
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;
}
},