DzLox

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

commit 6a04bf164625fc290aad19d49c88f28c9d44a408
parent bb0372fa9cd599acb5a2a6ed771ff4f994fae1fe
Author: Szymon Mikulicz <szymon.mikulicz@posteo.net>
Date:   Tue,  1 Sep 2026 17:19:37 +0200

Fix upvalue bug

Diffstat:
Dzlox/fib.lox | 29-----------------------------
Mzlox/src/lib::list.zig | 47+++++++++++++++++++++++++++++------------------
Mzlox/src/obj::closure.zig | 3+--
Mzlox/src/obj::function.zig | 5++---
Mzlox/src/obj::native.zig | 5++---
Mzlox/src/obj::upvalue.zig | 2++
Mzlox/src/vm.zig | 1+
Mzlox/src/vm::native.zig | 13+++++++++++++
Azlox/test/closure.lox | 20++++++++++++++++++++
Azlox/test/fib.lox | 29+++++++++++++++++++++++++++++
Azlox/test/list.lox | 8++++++++
11 files changed, 107 insertions(+), 55 deletions(-)

diff --git a/zlox/fib.lox b/zlox/fib.lox @@ -1,29 +0,0 @@ -con fib = fun(n) { - if (n < 2) return n; - return fib(n - 2) + fib(n - 1); -}; - -con printf = fun(fmt, args) { - var args_i = 0; - for(var i = 0; fmt[i]; i = i + 1) { - if(fmt[i] == '{' and fmt[i+1] == '}') { - put(args[args_i]); - args_i = args_i + 1; - i = i + 1; - } else { - put(fmt[i]); - } - } - print ""; -}; - -con main = fun() { - con num = 28; - con start = clock(); - con result = fib(num); - con end = clock() - start; - - printf("fib({}) == {}, time: {} ms", [num, result, end]); -}; - -main(); diff --git a/zlox/src/lib::list.zig b/zlox/src/lib::list.zig @@ -41,16 +41,18 @@ pub fn List(T: type) type { return ret; } - pub fn add_prev(self: *Element, gpa: std.mem.Allocator, val: Value) !void { + pub fn add_prev(self: *Element, gpa: std.mem.Allocator, val: Value) !*Element { self.prev.next = try Element.init(gpa, self.prev, self, val); self.prev = self.prev.next; if (self.next == self) self.next = self.prev; + return self.prev; } - pub fn add_next(self: *Element, gpa: std.mem.Allocator, val: Value) !void { + pub fn add_next(self: *Element, gpa: std.mem.Allocator, val: Value) !*Element { self.next.prev = try Element.init(gpa, self, self.next, val); self.next = self.next.prev; if (self.prev == self) self.prev = self.next; + return self.next; } pub fn new(gpa: std.mem.Allocator, val: Value) !*Element { @@ -96,9 +98,9 @@ pub fn List(T: type) type { if (@"const") @compileError("Cannot call push() on a const Iterator"); if (self.this) |el| { - try self.super.insert(false, el, val); + self.super.retip(el, try self.super.insert(.prev, el, val)); } else if (self.super.tip) |el| { - try self.super.insert(true, el.prev, val); + _ = try self.super.insert(.prev, el, val); } else { try self.super.begin(val); } @@ -156,10 +158,10 @@ pub fn List(T: type) type { } fn at(self: *Self, idx: isize) Error!*Element { - return if (@abs(idx) >= self._len and idx < -self._len) - Error.IndexOutOfBounds + return if (-self._len <= idx and idx < self._len) + try self._at(idx) else - try self._at(idx); + Error.IndexOutOfBounds; } pub fn set(self: *Self, idx: isize, val: Value) Error!void { @@ -196,25 +198,34 @@ pub fn List(T: type) type { self._len = 1; } - fn insert(self: *Self, after: bool, anchor: *Element, val: Value) !void { - if (after) { - try anchor.add_next(self.gpa, val); - } else { + fn insert(self: *Self, dir: enum { next, prev }, anchor: *Element, val: Value) !*Element { + const new = if (dir == .next) + try anchor.add_next(self.gpa, val) + else try anchor.add_prev(self.gpa, val); - if (self.tip == anchor) self.tip = anchor.prev; - } - self._len += 1; + + return new; + } + + fn retip(self: *Self, old: ?*Element, new: *Element) void { + if (self.tip == old) self.tip = new; } pub fn push(self: *Self, idx: isize, val: Value) Error!void { - if (@abs(idx) > self._len and idx < -self._len - 1) { - return Error.IndexOutOfBounds; - } else { + const len1 = self._len + 1; + + if (-len1 <= idx and idx < len1) { const el = self._at(idx) catch return self.begin(val); - try self.insert(idx < 0, el, val); + const new = try self.insert(if (idx < 0) .next else .prev, el, val); + + if (idx == -len1 or idx == 0) { + self.tip = new; + } + } else { + return Error.IndexOutOfBounds; } } }; diff --git a/zlox/src/obj::closure.zig b/zlox/src/obj::closure.zig @@ -34,8 +34,7 @@ pub fn Closure(fields: anytype) type { } pub fn format(_: *const Self, writer: *std.Io.Writer) !void { - _ = try writer.write("<C: "); - _ = try writer.writeAll(">"); + _ = try writer.write("<Closure>"); } pub fn eql(_: *const Self, _: *const Self) bool { diff --git a/zlox/src/obj::function.zig b/zlox/src/obj::function.zig @@ -42,10 +42,9 @@ pub fn Function(fields: anytype) type { pub fn format(self: *const Self, writer: *std.Io.Writer) !void { switch (self.type) { - .Function => _ = try writer.write("<F: "), - .Script => _ = try writer.write("<S: "), + .Function => _ = try writer.write("<Function>"), + .Script => _ = try writer.write("<Script>"), } - _ = try writer.writeAll(">"); } pub fn eql(_: *const Self, _: *const Self) bool { diff --git a/zlox/src/obj::native.zig b/zlox/src/obj::native.zig @@ -57,10 +57,9 @@ pub fn Native(fields: anytype) type { pub fn format(self: *const Self, writer: *std.Io.Writer) !void { switch (self.type) { - .Builtin => _ = try writer.write("<B: "), - .Literal => _ = try writer.write("<L: "), + .Builtin => _ = try writer.write("<Builtin>"), + .Literal => _ = try writer.write("<Literal> "), } - _ = try writer.writeAll(">"); } pub fn eql(_: *const Self, _: *const Self) bool { diff --git a/zlox/src/obj::upvalue.zig b/zlox/src/obj::upvalue.zig @@ -49,6 +49,8 @@ pub fn Upvalue(fields: anytype) type { } pub fn free(self: *const Self, allocator: std.mem.Allocator) void { + if (self.closed) + self.location.destroy(allocator); allocator.destroy(self); } }; diff --git a/zlox/src/vm.zig b/zlox/src/vm.zig @@ -102,6 +102,7 @@ pub const VM = struct { try self.defineNative("table", 0, Obj.Native.ArityMax, native.table); try self.defineNative("list", 0, Obj.Native.ArityMax, native.list); try self.defineNative("rungc", 0, 0, native.rungc); + try self.defineNative("len", 1, 1, native.len); native.Clock.set_start(io); diff --git a/zlox/src/vm::native.zig b/zlox/src/vm::native.zig @@ -48,3 +48,16 @@ pub fn rungc(gc: *GC, _: []const Value) Error!Value { gc.collect(); return Value.init({}); } + +pub fn len(_: *GC, val: []const Value) Error!Value { + if (val[0].cast_if(Value.obj)) |obj| { + const ret = switch (obj.type) { + .String => (obj.cast(.String) catch unreachable).len, + .Table => (obj.cast(.Table) catch unreachable).table.ptr().count, + .List => (obj.cast(.List) catch unreachable).list.ptr().len(), + else => return Error.Native, + }; + return Value.init(@as(f64, @floatFromInt(ret))); + } + return Error.Native; +} diff --git a/zlox/test/closure.lox b/zlox/test/closure.lox @@ -0,0 +1,20 @@ +fun mk() { + var i = 0; + var l = []; + return fun() { + l[len(l)] = i = i + 1; + print l; + }; +} + +con f = mk(); + +f(); +f(); +f(); + +con f2 = mk(); + +f2(); +f2(); +f2(); diff --git a/zlox/test/fib.lox b/zlox/test/fib.lox @@ -0,0 +1,29 @@ +fun fib(n) { + if (n < 2) return n; + return fib(n - 2) + fib(n - 1); +} + +fun printf(fmt, args) { + var args_i = 0; + for(var i = 0; fmt[i]; i = i + 1) { + if(fmt[i] == '{' and fmt[i+1] == '}') { + put(args[args_i]); + args_i = args_i + 1; + i = i + 1; + } else { + put(fmt[i]); + } + } + print ""; +} + +fun main() { + con num = 28; + con start = clock(); + con result = fib(num); + con end = clock() - start; + + printf("fib({}) == {}, time: {} ms", [num, result, end]); +} + +main(); diff --git a/zlox/test/list.lox b/zlox/test/list.lox @@ -0,0 +1,8 @@ +con a = []; + +a[0] = 1; +print a; +a[1] = 2; +print a; +a[-3] = 0; +print a;