commit fbecd2575e66d296f3e940667efcff78e85c1ca2
parent e4a1d0de6da1c2569240e32806514596d6b78c70
Author: Szymon Mikulicz <szymon.mikulicz@posteo.net>
Date: Wed, 9 Sep 2026 17:54:04 +0200
Initializer finished
Diffstat:
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();