DzLox

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

commit fbecd2575e66d296f3e940667efcff78e85c1ca2
parent e4a1d0de6da1c2569240e32806514596d6b78c70
Author: Szymon Mikulicz <szymon.mikulicz@posteo.net>
Date:   Wed,  9 Sep 2026 17:54:04 +0200

Initializer finished

Diffstat:
Mzlox/src/compiler.zig | 18+++++++++++++-----
Mzlox/src/obj::function.zig | 12++++++------
Mzlox/src/obj::instance.zig | 2+-
Azlox/test/coffeemaker.lox | 15+++++++++++++++
Azlox/test/upvalue.lox | 17+++++++++++++++++
5 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/zlox/src/compiler.zig b/zlox/src/compiler.zig @@ -47,6 +47,7 @@ pub fn Compiler(size: comptime_int) type { hadError: bool, panicMode: bool, chunk: *Obj.Chunk, + initializer: bool, objects: *GC, locals: [size]Local, localCount: usize, @@ -183,7 +184,9 @@ pub fn Compiler(size: comptime_int) type { } fn emitReturn(self: *Self) void { - if (self.enclosing) |_| + if (self.initializer) + self.emit(OP.GET_LOCAL, 0) + else if (self.enclosing) |_| self.emitOP(OP.NIL); self.emitOP(OP.RETURN); @@ -583,22 +586,22 @@ pub fn Compiler(size: comptime_int) type { fn method(self: *Self) void { self.consume(Token.IDENTIFIER, "Expect method name"); const constant = self.identifierConstant(self.previous) catch return; - self.function(true); + self.function(true, self.previous.lexeme); self.emit(OP.METHOD, constant); } fn funDeclaration(self: *Self) void { const global = self.parseVariable("Expect function name.", true) catch return; self.markInitialized(); - self.function(false); + self.function(false, self.previous.lexeme); self.defineVariable(global, true); } fn funExpression(self: *Self, _: bool) void { - self.function(false); + self.function(false, "<anon>"); } - fn function(self: *Self, isMethod: bool) void { + fn function(self: *Self, isMethod: bool, name: []const u8) void { const chunk = self.objects.emplace(.Chunk, {}) catch |err| { self.errorAtPrevious("Couldn't allocate chunk"); self.lastError = err; @@ -611,6 +614,8 @@ pub fn Compiler(size: comptime_int) type { return; }; + compiler.initializer = isMethod and std.mem.eql(u8, name, "init"); + compiler.objects.push_callback(&gc_callback, &compiler) catch @panic("Couln't push callback"); defer compiler.objects.pop_callback(); @@ -813,6 +818,8 @@ pub fn Compiler(size: comptime_int) type { } if (self.match(Token.SEMICOLON)) { self.emitReturn(); + } else if (self.initializer) { + self.errorAtCurrent("Can't return a value from an initializer"); } else { self.expression(); self.consume(Token.SEMICOLON, "Expect ';' after return value"); @@ -1072,6 +1079,7 @@ pub fn Compiler(size: comptime_int) type { .upvalues = @splat(Upvalue{ .index = 0, .type = .local }), .upvaluesCount = 0, .currentClass = null, + .initializer = false, }; self.locals[0].depth = 0; diff --git a/zlox/src/obj::function.zig b/zlox/src/obj::function.zig @@ -53,12 +53,12 @@ pub fn Function(fields: anytype) type { } pub fn format(self: *const Self, writer: *std.Io.Writer) !void { - switch (self.type) { - .Function => _ = try writer.write("<Function>"), - .Script => _ = try writer.write("<Script>"), - .Closure => _ = try writer.write("<Closure>"), - .Method => _ = try writer.write("<Method>"), - } + _ = try writer.write(switch (self.type) { + .Function => "<Function>", + .Script => "<Script>", + .Closure => "<Closure>", + .Method => "<Method>", + }); } pub fn eql(_: *const Self, _: *const Self) bool { diff --git a/zlox/src/obj::instance.zig b/zlox/src/obj::instance.zig @@ -46,7 +46,7 @@ pub fn Instance(fields: anytype) type { var val = Value.init(self.cast()); const len = fun.upvalues.len(); if (len > 1) - @memcpy(fun.upvalues.ptr()[0 .. len - 2], met.upvalues.ptr()); + @memcpy(fun.upvalues.ptr()[0 .. len - 1], met.upvalues.ptr()); fun.upvalues.ptr()[len - 1] = try gc.emplace(.Upvalue, .{ .val = &val, diff --git a/zlox/test/coffeemaker.lox b/zlox/test/coffeemaker.lox @@ -0,0 +1,15 @@ +class CoffeeMaker { + init(coffee) { + this.coffee = coffee; + } + + brew() { + print "Enjoy your cup of " + this.coffee; + + // No reusing the grounds! + this.coffee = nil; + } +} + +var maker = CoffeeMaker("coffee and chicory"); +maker.brew(); diff --git a/zlox/test/upvalue.lox b/zlox/test/upvalue.lox @@ -0,0 +1,17 @@ +fun Test(inc) { + var upval = 0; + return class { + init() { + this.inc = inc; + } + method() { + print(upval); + upval = upval + inc; + } + }; +} + +con test = Test(3)(); + +test.method(); +test.method();