commit 28bc47f83eb783d32b2bf6188cecf3df9e8d27e2
parent 372a5c516991a81012d7b7031dc39f4b88b81db1
Author: Ashymad <szymon.mikulicz@posteo.net>
Date: Thu, 29 Feb 2024 22:41:37 +0100
Make TrieTable comptime
Diffstat:
6 files changed, 63 insertions(+), 63 deletions(-)
diff --git a/zlox/src/compiler.zig b/zlox/src/compiler.zig
@@ -3,9 +3,8 @@ const scanner = @import("scanner.zig");
pub const CompilerError = scanner.ScannerError;
-pub fn compile(source: []const u8, allocator: std.mem.Allocator) !void {
- var Scanner = try scanner.Scanner.init(source, allocator);
- defer Scanner.deinit();
+pub fn compile(source: []const u8) !void {
+ var Scanner = try scanner.Scanner.init(source);
var line: i32 = -1;
diff --git a/zlox/src/main.zig b/zlox/src/main.zig
@@ -15,7 +15,7 @@ pub fn main() anyerror!u8 {
defer std.process.argsFree(allocator, args);
if (args.len == 1) {
- try repl(allocator);
+ try repl();
} else if (args.len == 2) {
try runFile(allocator, args[1]);
} else {
@@ -34,7 +34,7 @@ pub fn runFile(allocator: std.mem.Allocator, path: []const u8) anyerror!void {
defer allocator.free(text);
}
-pub fn repl(allocator: std.mem.Allocator) anyerror!void {
+pub fn repl() anyerror!void {
var VM = vm.VM.init();
defer VM.deinit();
@@ -42,7 +42,7 @@ pub fn repl(allocator: std.mem.Allocator) anyerror!void {
while (Linenoise.linenoise("lox> ")) |line| {
defer Linenoise.linenoiseFree(line);
- try VM.interpret(std.mem.span(line), allocator);
+ try VM.interpret(std.mem.span(line));
_ = Linenoise.linenoiseHistoryAdd(line);
}
}
diff --git a/zlox/src/scanner.zig b/zlox/src/scanner.zig
@@ -56,29 +56,27 @@ pub const Token = struct {
};
pub const Scanner = struct {
- pub fn init(source: []const u8, allocator: std.mem.Allocator) !@This() {
- var this = @This(){ .start = source.ptr, .current = source.ptr, .end = source.ptr + source.len, .line = 0, .identifiers = try trie.TrieTable(TokenType).init(allocator) };
- try this.identifiers.put("and", TokenType.AND);
- try this.identifiers.put("class", TokenType.CLASS);
- try this.identifiers.put("else", TokenType.ELSE);
- try this.identifiers.put("false", TokenType.FALSE);
- try this.identifiers.put("for", TokenType.FOR);
- try this.identifiers.put("fun", TokenType.FUN);
- try this.identifiers.put("if", TokenType.IF);
- try this.identifiers.put("nil", TokenType.NIL);
- try this.identifiers.put("or", TokenType.OR);
- try this.identifiers.put("print", TokenType.PRINT);
- try this.identifiers.put("return", TokenType.RETURN);
- try this.identifiers.put("super", TokenType.SUPER);
- try this.identifiers.put("this", TokenType.THIS);
- try this.identifiers.put("true", TokenType.TRUE);
- try this.identifiers.put("var", TokenType.VAR);
- try this.identifiers.put("while", TokenType.WHILE);
- return this;
- }
-
- pub fn deinit(self: *@This()) void {
- self.identifiers.deinit();
+ const identifiers = trie.TrieTable(TokenType, .{
+ .{ "and", TokenType.AND },
+ .{ "class", TokenType.CLASS },
+ .{ "else", TokenType.ELSE },
+ .{ "false", TokenType.FALSE },
+ .{ "for", TokenType.FOR },
+ .{ "fun", TokenType.FUN },
+ .{ "if", TokenType.IF },
+ .{ "nil", TokenType.NIL },
+ .{ "or", TokenType.OR },
+ .{ "print", TokenType.PRINT },
+ .{ "return", TokenType.RETURN },
+ .{ "super", TokenType.SUPER },
+ .{ "this", TokenType.THIS },
+ .{ "true", TokenType.TRUE },
+ .{ "var", TokenType.VAR },
+ .{ "while", TokenType.WHILE },
+ });
+
+ pub fn init(source: []const u8) !@This() {
+ return @This(){ .start = source.ptr, .current = source.ptr, .end = source.ptr + source.len, .line = 0 };
}
pub fn scanToken(self: *@This()) ScannerError!Token {
@@ -161,7 +159,7 @@ pub const Scanner = struct {
}
fn identifierType(self: *const @This()) TokenType {
- if (self.identifiers.get(self.start[0..(@intFromPtr(self.current) - @intFromPtr(self.start))])) |tok| {
+ if (identifiers.get(self.start[0..(@intFromPtr(self.current) - @intFromPtr(self.start))])) |tok| {
return tok;
} else {
return TokenType.IDENTIFIER;
@@ -204,7 +202,6 @@ pub const Scanner = struct {
return Token{ .type = tokentype, .lexeme = self.start[0..(@intFromPtr(self.current) - @intFromPtr(self.start))], .line = self.line };
}
- identifiers: trie.TrieTable(TokenType),
start: [*]const u8,
current: [*]const u8,
end: [*]const u8,
diff --git a/zlox/src/test.zig b/zlox/src/test.zig
@@ -35,13 +35,7 @@ test "testChunk" {
}
test "testTrie" {
- var allocator = std.heap.GeneralPurposeAllocator(.{}){};
- defer std.debug.assert(allocator.deinit() == std.heap.Check.ok);
-
- var tr = try Trie(u8).init(allocator.allocator());
- defer tr.deinit();
-
- try tr.put("test", 16);
+ const tr = Trie(u8, .{.{ "test", 16 }});
try std.testing.expectEqual(tr.get("test").?, 16);
try std.testing.expectEqual(tr.get("tes"), null);
diff --git a/zlox/src/trie.zig b/zlox/src/trie.zig
@@ -1,36 +1,50 @@
const std = @import("std");
-pub fn TrieTable(comptime T: type) type {
- return struct {
+pub fn TrieTable(comptime T: type, comptime list: anytype) type {
+ const TrieLeaf = struct {
value: ?T,
data: [26]?*@This(),
- allocator: ?std.heap.ArenaAllocator,
+ };
- pub fn init(allocator: std.mem.Allocator) !@This() {
- return @This(){ .value = null, .data = [_]?*@This(){null} ** 26, .allocator = std.heap.ArenaAllocator.init(allocator) };
+ const max_len = comptime blk: {
+ var ret = 0;
+ for (list) |el| {
+ ret += el.@"0".len;
}
+ break :blk ret;
+ };
- pub fn put(self: *@This(), word: []const u8, value: T) !void {
- var this = self;
- const allo = self.allocator.?.allocator();
- for (word) |ch| {
+ const precomputed = comptime blk: {
+ var allocated = [_]TrieLeaf{TrieLeaf{ .value = null, .data = [_]?*TrieLeaf{null} ** 26 }} ** max_len;
+ var allocated_i = 0;
+ var tip = TrieLeaf{ .value = null, .data = [_]?*TrieLeaf{null} ** 26 };
+
+ for (list) |el| {
+ var leaf = &tip;
+ for (el.@"0") |ch| {
const idx = ch - 'a';
- if (this.data[idx]) |val| {
- this = val;
+ if (leaf.data[idx]) |val| {
+ leaf = val;
} else {
- var new = try allo.create(@This());
+ var new = &allocated[allocated_i];
+ allocated_i += 1;
new.value = null;
- new.data = [_]?*@This(){null} ** 26;
- new.allocator = null;
- this.data[idx] = new;
- this = new;
+ new.data = [_]?*TrieLeaf{null} ** 26;
+ leaf.data[idx] = new;
+ leaf = new;
}
}
- this.value = value;
+ leaf.value = el.@"1";
}
+ break :blk .{ .allocated = allocated, .tip = tip };
+ };
+
+ return struct {
+ const allocated = precomputed.allocated;
+ const tip = precomputed.tip;
- pub fn get(self: *const @This(), word: []const u8) ?T {
- var this = self;
+ pub fn get(word: []const u8) ?T {
+ var this = &tip;
for (word) |ch| {
if (ch < 'a' or ch > 'z') return null;
const idx = ch - 'a';
@@ -42,9 +56,5 @@ pub fn TrieTable(comptime T: type) type {
}
return this.value;
}
-
- pub fn deinit(self: *@This()) void {
- self.allocator.?.deinit();
- }
};
}
diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig
@@ -35,8 +35,8 @@ pub const VM = struct {
try self.run(true);
}
- pub fn interpret(self: *@This(), source: []const u8, allocator: std.mem.Allocator) !void {
- try compiler.compile(source, allocator);
+ pub fn interpret(self: *@This(), source: []const u8) !void {
+ try compiler.compile(source);
self.resetStack();
}