commit cd43147544be4d6d48a6959ea0bdae6176d9c321
parent bb3007599d98231af265275281a7f824aa96a29c
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date: Fri, 9 Aug 2024 17:43:26 +0200
Print via format()
Diffstat:
10 files changed, 84 insertions(+), 51 deletions(-)
diff --git a/zlox/src/comptime_utils.zig b/zlox/src/comptime_utils.zig
@@ -19,3 +19,7 @@ pub fn tagFromType(T: type, U: type) std.meta.Tag(T) {
}
@compileError("No matching tag for type " ++ @typeName(U) ++ " in Union " ++ @typeName(T));
}
+
+pub fn fn_error(comptime fun: anytype) type {
+ return @typeInfo(@typeInfo(@TypeOf(fun)).Fn.return_type.?).ErrorUnion.error_set;
+}
diff --git a/zlox/src/debug.zig b/zlox/src/debug.zig
@@ -68,9 +68,7 @@ fn simpleInstruction(name: []const u8, offset: usize) usize {
fn constantInstruction(name: []const u8, ch: chunk.Chunk, offset: usize) !usize {
const constant = try ch.code.get(offset + 1);
- print("{s:<32} {d:4} '", .{ name, constant });
- (try ch.constants.get(constant)).print();
- print("'\n", .{});
+ print("{s:<32} {d:4} '{s}'\n", .{ name, constant, try ch.constants.get(constant)});
return offset + 2;
}
diff --git a/zlox/src/obj.zig b/zlox/src/obj.zig
@@ -26,9 +26,10 @@ pub const Obj = packed struct {
pub fn init(comptime tp: Type, arg: tp.get().Arg, allocator: std.mem.Allocator) !*Super {
return (try tp.get().init(arg, allocator)).cast();
}
- pub fn print(self: *const Super) void {
+
+ pub fn format(self: *const Super, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
switch (self.type) {
- inline else => |tp| self._cast(tp).print(),
+ inline else => |tp| try self._cast(tp).format(fmt, options, writer),
}
}
pub fn eql(self: *const Super, other: *const Super) bool {
diff --git a/zlox/src/obj/function.zig b/zlox/src/obj/function.zig
@@ -14,18 +14,28 @@ pub const Function = packed struct {
chunk: *chunk.Chunk,
name: *String,
- pub fn init(arg: Arg, allocator: std.mem.Allocator) Error!*Self {
- _ = arg;
- _ = allocator;
- return error.OutOfMemory;
+ pub fn init(_: Arg, allocator: std.mem.Allocator) Error!*Self {
+ const self: *Self = try allocator.create(Self);
+ self.* = Self{
+ .obj = Super{
+ .type = Super.Type.Function,
+ },
+ .chunk = try allocator.create(chunk.Chunk),
+ .arity = 0,
+ };
+ self.chunk.* = chunk.Chunk.init(allocator);
+ return self;
}
pub fn cast(self: *Self) *Super {
return @ptrCast(self);
}
- pub fn print(self: *const Self) void {
+ 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 {
@@ -35,8 +45,9 @@ pub const Function = packed struct {
}
pub fn free(self: *const Self, allocator: std.mem.Allocator) void {
- _ = self;
- _ = allocator;
+ self.chunk.deinit();
+ allocator.destroy(self.chunk);
+ allocator.destroy(self);
}
};
diff --git a/zlox/src/obj/string.zig b/zlox/src/obj/string.zig
@@ -41,8 +41,10 @@ pub const String = packed struct {
pub fn cast(self: *Self) *Super {
return @ptrCast(self);
}
- pub fn print(self: *const Self) void {
- std.debug.print("\"{s}\"", .{self.slice()});
+ pub fn format(self: *const Self, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ _ = try writer.write("\"");
+ _ = try writer.write(self.slice());
+ _ = try writer.writeAll("\"");
}
pub fn eql(self: *const Self, other: *const Self) bool {
return @intFromPtr(self) == @intFromPtr(other);
diff --git a/zlox/src/obj/table.zig b/zlox/src/obj/table.zig
@@ -2,6 +2,7 @@ const std = @import("std");
const table = @import("../table.zig");
const hash = @import("../hash.zig");
const value = @import("../value.zig");
+const utils = @import("../comptime_utils.zig");
const Super = @import("../obj.zig").Obj;
const Error = Super.Error;
@@ -45,18 +46,23 @@ pub const Table = packed struct {
self.hash -%= hash.hash(key) -% hash.hash(val);
_ = self.table.delete(key);
}
+ 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),
- fn print_element(key: value.Value, val: value.Value) void {
- key.print();
- std.debug.print(":", .{});
- val.print();
- std.debug.print(",", .{});
+ pub fn print(this: @This(), key: value.Value, val: value.Value) utils.fn_error(@TypeOf(writer).write)!void {
+ try key.format(fmt, this.options, this.writer);
+ _ = try this.writer.write(":");
+ try val.format(fmt, this.options, this.writer);
+ _ = try this.writer.write(",");
+ }
- }
- pub fn print(self: *const Self) void {
- std.debug.print("[", .{});
- self.table.for_each(Self.print_element);
- std.debug.print("]", .{});
+ };
+
+ _ = try writer.write("[");
+ try self.table.for_each_try(Printer{.options = options, .writer = writer}, Printer.print);
+ _ = try writer.writeAll("]");
}
pub fn eql(self: *const Self, other: *const Self) bool {
return self.table.eql(other.table, value.Value.eql);
diff --git a/zlox/src/obj/template.zig b/zlox/src/obj/template.zig
@@ -19,8 +19,11 @@ pub const Template = packed struct {
return @ptrCast(self);
}
- pub fn print(self: *const Self) void {
+ 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 {
diff --git a/zlox/src/table.zig b/zlox/src/table.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const utils = @import("comptime_utils.zig");
pub const TableError = error{ OutOfMemory, KeyError };
@@ -87,10 +88,19 @@ pub fn Table(K: type, V: type, hash_fn: fn (K) u32, cmp_fn: fn (K, K) bool) type
}
}
- pub fn for_each(self: *const Self, fun: fn (K, V) void) void {
+ pub fn for_each(self: *const Self, arg: anytype, fun: fn (@TypeOf(arg), K, V) void) void {
for (self.entries) |entry| {
switch (entry) {
- .some => |some| fun(some.key, some.value),
+ .some => |some| fun(arg, some.key, some.value),
+ else => {},
+ }
+ }
+ }
+
+ pub fn for_each_try(self: *const Self, arg: anytype, fun: anytype) utils.fn_error(fun)!void {
+ for (self.entries) |entry| {
+ switch (entry) {
+ .some => |some| try fun(arg, some.key, some.value),
else => {},
}
}
diff --git a/zlox/src/value.zig b/zlox/src/value.zig
@@ -10,31 +10,32 @@ pub const Value = union(enum) {
nil: void,
obj: *Obj,
- pub const Tag = std.meta.Tag(@This());
+ const Self = @This();
+ pub const Tag = std.meta.Tag(Self);
- pub fn print(self: @This()) void {
+ pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
switch (self) {
- .number => |val| std.debug.print("{d}", .{val}),
- .char => |val| std.debug.print("'{s}'", .{&[_]u8{val}}),
- .bool => |val| std.debug.print("{s}", .{if (val) "true" else "false"}),
- .nil => std.debug.print("nil", .{}),
- .obj => |o| o.print(),
+ .number => |val| try writer.print("{d}", .{val}),
+ .char => |val| try writer.writeAll(&[_]u8{val}),
+ .bool => |val| try writer.writeAll(if (val) "true" else "false"),
+ .nil => try writer.writeAll("nil"),
+ .obj => |o| try o.format(fmt, options, writer),
}
}
pub fn tagNameOf(T: type) []const u8 {
- return @tagName(utils.tagFromType(@This(), T));
+ return @tagName(utils.tagFromType(Self, T));
}
- pub fn typeName(self: @This()) []const u8 {
+ pub fn typeName(self: Self) []const u8 {
return switch (self) {
.obj => |o| @tagName(o.type),
inline else => |tp| tagNameOf(@TypeOf(tp)),
};
}
- pub fn init(val: anytype) @This() {
- return @unionInit(@This(), tagNameOf(@TypeOf(val)), val);
+ pub fn init(val: anytype) Self {
+ return @unionInit(Self, tagNameOf(@TypeOf(val)), val);
}
@@ -45,32 +46,32 @@ pub const Value = union(enum) {
from;
}
- pub fn is(self: @This(), comptime tag: anytype) bool {
+ pub fn is(self: Self, comptime tag: anytype) bool {
return switch (self) {
toTag(tag) => @TypeOf(tag) == Tag or self.obj.is(tag),
else => false,
};
}
- pub fn get(self: @This(), comptime tag: anytype) tagType(tag) {
+ pub fn get(self: Self, comptime tag: anytype) tagType(tag) {
return @field(self, @tagName(toTag(tag)));
}
- pub fn set(self: *@This(), comptime tag: anytype, value: tagType(tag)) void {
+ pub fn set(self: *Self, comptime tag: anytype, value: tagType(tag)) void {
@field(self, @tagName(toTag(tag))) = value;
}
pub fn tagType(comptime tag: anytype) type {
- return utils.typeFromTag(@This(), toTag(tag));
+ return utils.typeFromTag(Self, toTag(tag));
}
pub const ParseNumberError = std.fmt.ParseFloatError;
- pub fn parseNumber(str: []const u8) ParseNumberError!@This() {
- return @This(){ .number = try std.fmt.parseFloat(tagType(Value.number), str) };
+ pub fn parseNumber(str: []const u8) ParseNumberError!Self {
+ return Self{ .number = try std.fmt.parseFloat(tagType(Value.number), str) };
}
- pub fn isTruthy(self: @This()) bool {
+ pub fn isTruthy(self: Self) bool {
return switch (self) {
.nil => false,
.bool => |val| val,
@@ -78,7 +79,7 @@ pub const Value = union(enum) {
};
}
- pub fn eql(self: @This(), other: @This()) bool {
+ pub fn eql(self: Self, other: Self) bool {
if (@intFromEnum(self) != @intFromEnum(other)) return false;
return switch (self) {
.number => |x| x == other.number,
diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig
@@ -135,9 +135,7 @@ pub const VM = struct {
std.debug.print(" ", .{});
var stackPtr: [*]Value = &self.stack;
while (stackPtr != self.stackTop) : (stackPtr += 1) {
- std.debug.print("[ ", .{});
- stackPtr[0].print();
- std.debug.print(" ]", .{});
+ std.debug.print("[{s}]", .{stackPtr[0]});
}
std.debug.print("\n", .{});
_ = try debug.disassembleInstruction(self.chunk.*, self.instruction_idx());
@@ -145,8 +143,7 @@ pub const VM = struct {
const instruction: u8 = self.read_byte();
switch (instruction) {
@intFromEnum(OP.PRINT) => {
- self.pop().print();
- std.debug.print("\n", .{});
+ std.debug.print("{s}\n", .{self.pop()});
},
@intFromEnum(OP.RETURN) => return,
@intFromEnum(OP.POP) => _ = self.pop(),