DzLox

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

commit b2f59867f59d26a2dbdf0a10b0142057053d4849
parent bdf60511df5e35856bb557b5d5946b7b2349f8d4
Author: Szymon Mikulicz <szymon.mikulicz@aptiv.com>
Date:   Sun, 11 Aug 2024 12:17:27 +0200

Function declaration

Diffstat:
Mzlox/src/compiler.zig | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mzlox/src/obj/function.zig | 6++----
Mzlox/src/obj/list.zig | 12++++++++----
Mzlox/src/vm/callbacks.zig | 2+-
4 files changed, 78 insertions(+), 27 deletions(-)

diff --git a/zlox/src/compiler.zig b/zlox/src/compiler.zig @@ -33,7 +33,6 @@ const Precedence = enum { } }; - pub fn Compiler(size: comptime_int) type { return struct { current: scanner.Token, @@ -42,7 +41,7 @@ pub fn Compiler(size: comptime_int) type { lastError: CompilerError, hadError: bool, panicMode: bool, - function: *Obj.Function, + currentFunction: *Obj.Function, objects: *Obj.List, locals: [size]Local, localCount: usize, @@ -151,7 +150,7 @@ pub fn Compiler(size: comptime_int) type { } fn currentChunk(self: *Self) *Chunk { - return self.function.chunk; + return self.currentFunction.chunk; } fn emitByte(self: *Self, byte: u8) void { @@ -180,7 +179,7 @@ pub fn Compiler(size: comptime_int) type { fn end(self: *Self) *Obj.Function { self.emitReturn(); - return self.function; + return self.currentFunction; } fn emitReturn(self: *Self) void { @@ -203,7 +202,7 @@ pub fn Compiler(size: comptime_int) type { const canAssign = precedence.lessOrEq(Precedence.ASSIGNMENT); self.advance(); - if (getRule(self.previous.type catch unreachable).prefix) |prefixRule| { + if (getRule(self.previous.type catch return).prefix) |prefixRule| { prefixRule(self, canAssign); } else { self.lastError = CompilerError.NotAnExpression; @@ -303,12 +302,11 @@ pub fn Compiler(size: comptime_int) type { } fn parseLiteralString(self: *Self) !Value { - return Value.init(try self.objects.emplace(.String, &.{self.previous.lexeme[1 .. self.previous.lexeme.len - 1]})); + return Value.init(try self.objects.emplace_cast(.String, &.{self.previous.lexeme[1 .. self.previous.lexeme.len - 1]})); } fn parseLiteralTable(self: *Self) CompilerError!Value { - var ret = try self.objects.emplace(.Table, {}); - var tabl = ret.cast(.Table) catch unreachable; + var tabl = try self.objects.emplace(.Table, {}); while (!self.match(Token.RIGHT_BRACKET)) { const key = try self.parseLiteralValue(); self.consume(Token.COLON, "Expect ':' after key in table initalizer"); @@ -325,7 +323,7 @@ pub fn Compiler(size: comptime_int) type { break; self.consume(Token.COMMA, "Expect ',' after value in table initalizer"); } - return Value.init(ret); + return Value.init(tabl.cast()); } fn table(self: *Self, _: bool) void { @@ -477,7 +475,9 @@ pub fn Compiler(size: comptime_int) type { } fn declaration(self: *Self) void { - if (self.match(Token.VAR)) { + if (self.match(Token.FUN)) { + self.funDeclaration(); + } else if (self.match(Token.VAR)) { self.varDeclaration(); } else if (self.match(Token.CON)) { self.conDeclaration(); @@ -488,6 +488,55 @@ pub fn Compiler(size: comptime_int) type { if (self.panicMode) self.synchronize(); } + fn funDeclaration(self: *Self) void { + const global = self.parseVariable("Expect function name.", true) catch return; + self.markInitialized(); + self.function(self.previous.lexeme, Obj.Function.Type.Function); + self.defineVariable(global, true); + } + + fn function(self: *Self, name: []const u8, tp: Obj.Function.Type) void { + var fun = self.objects.emplace(Obj.Type.Function, tp) catch |err| { + self.errorAtPrevious("Couldn't allocate function"); + self.lastError = err; + return; + }; + fun.name = self.objects.emplace(Obj.Type.String, &.{name}) catch |err| { + self.errorAtPrevious("Couldn't allocate function name"); + self.lastError = err; + return; + }; + + var compiler = Self.init(self.scanner, self.objects, fun); + compiler.current = self.current; + compiler.beginScope(); + + compiler.consume(Token.LEFT_PAREN, "Expect '(' after function name"); + if (!compiler.check(Token.RIGHT_PAREN)) { + while (true) { + if (fun.arity == std.math.maxInt(@TypeOf(fun.arity))) { + self.errorAtCurrent("Too many arguments to a function"); + return; + } + fun.arity += 1; + compiler.defineVariable(compiler.parseVariable("Expect parameter name.", true) catch return, true); + if (!compiler.match(Token.COMMA)) break; + } + } + compiler.consume(Token.RIGHT_PAREN, "Expect ')' after parameters"); + compiler.consume(Token.LEFT_BRACE, "Expect '{' before function body"); + + compiler.block(); + + self.current = compiler.current; + + if (compiler.hadError) { + self.lastError = compiler.lastError; + } else { + self.emit(OP.CONSTANT, self.makeConstant(Value.init(compiler.end().cast()))); + } + } + fn varDeclaration(self: *Self) void { const global = self.parseVariable("Expect variable name.", false) catch return; @@ -524,7 +573,7 @@ pub fn Compiler(size: comptime_int) type { } fn identifierConstant(self: *Self, tok: scanner.Token) !u8 { - return self.makeConstant(Value.init(self.objects.emplace(.String, &.{tok.lexeme}) catch |err| { + return self.makeConstant(Value.init(self.objects.emplace_cast(.String, &.{tok.lexeme}) catch |err| { self.lastError = err; self.errorAtPrevious("Couldn't allocate identifier"); return err; @@ -563,6 +612,7 @@ pub fn Compiler(size: comptime_int) type { } fn markInitialized(self: *Self) void { + if(self.scopeDepth == 0) return; self.locals[self.localCount-1].depth = self.scopeDepth; } @@ -614,12 +664,11 @@ pub fn Compiler(size: comptime_int) type { fn switchStatement(self: *Self) void { self.consume(Token.LEFT_PAREN, "Expect '(' after 'switch'."); - var ret = self.objects.emplace(.Table, {}) catch |err| { + var tabl = self.objects.emplace(.Table, {}) catch |err| { self.lastError = err; return; }; - var tabl = ret.cast(.Table) catch unreachable; - self.emitConstant(Value.init(ret)); + self.emitConstant(Value.init(tabl.cast())); self.expression(); @@ -841,7 +890,7 @@ pub fn Compiler(size: comptime_int) type { self.emitOP(OP.PRINT); } - fn init(scan: *scanner.Scanner, objects: *Obj.List, function: *Obj.Function) Self { + fn init(scan: *scanner.Scanner, objects: *Obj.List, fun: *Obj.Function) Self { return Self{ .scanner = scan, .current = scanner.Token.Empty, @@ -849,7 +898,7 @@ pub fn Compiler(size: comptime_int) type { .panicMode = false, .hadError = false, .lastError = scanner.ScannerError.EmptyToken, - .function = function, + .currentFunction = fun, .objects = objects, .locals = [_]Local{Local{.name = scanner.Token.Empty, .depth = 0, .con = true}} ** size, .localCount = 1, @@ -859,8 +908,8 @@ pub fn Compiler(size: comptime_int) type { pub fn compile(source: []const u8, objects: *Obj.List) CompilerError!*Obj.Function { var scan = try scanner.Scanner.init(source); - var function = try objects.emplace(Obj.Type.Function, Obj.Function.Type.Script); - var self = Self.init(&scan, objects, function.cast(.Function) catch unreachable); + const fun = try objects.emplace(Obj.Type.Function, Obj.Function.Type.Script); + var self = Self.init(&scan, objects, fun); self.advance(); diff --git a/zlox/src/obj/function.zig b/zlox/src/obj/function.zig @@ -17,7 +17,7 @@ pub const Function = packed struct { obj: Super, arity: u8, chunk: *chunk.Chunk, - name: ?*String, + name: ?*const String, type: Type, pub fn init(tp: Arg, allocator: std.mem.Allocator) Error!*Self { @@ -52,9 +52,7 @@ pub const Function = packed struct { _ = try writer.writeAll(">"); } - pub fn eql(self: *const Self, other: *const Self) bool { - _ = self; - _ = other; + pub fn eql(_: *const Self, _: *const Self) bool { return false; } diff --git a/zlox/src/obj/list.zig b/zlox/src/obj/list.zig @@ -27,16 +27,20 @@ pub const List = struct { self.tip = new_tip; } - pub fn emplace(self: *Self, comptime tp: Type, arg: tp.get().Arg) Error!*Super { + pub fn emplace(self: *Self, comptime tp: Type, arg: tp.get().Arg) Error!*tp.get() { var newObj = true; const obj = switch (tp) { - .String => (try String.intern(arg, &self.table, &newObj, self.allocator)).cast(), - else => try Super.init(tp, arg, self.allocator), + .String => try String.intern(arg, &self.table, &newObj, self.allocator), + else => try tp.get().init(arg, self.allocator), }; - if (newObj) try self.push(obj); + if (newObj) try self.push(obj.cast()); return obj; } + pub fn emplace_cast(self: *Self, comptime tp: Type, arg: tp.get().Arg) Error!*Super { + return (try self.emplace(tp, arg)).cast(); + } + pub fn pop(self: *Self) ?*Element { if (self.tip) |tip| { self.tip = tip.next; diff --git a/zlox/src/vm/callbacks.zig b/zlox/src/vm/callbacks.zig @@ -27,7 +27,7 @@ pub fn concatenate(objects: *Obj.List) Type(Obj.Type.String, Obj.Type.String) { const Ret = Type(Obj.Type.String, Obj.Type.String); const ret = Ret{ .objects = objects, ._call = struct { pub fn concatenate(self: *const Ret, lhs: *Obj, rhs: *Obj) Error!*Obj { - return try self.objects.emplace(.String, &.{ (lhs.cast(.String) catch unreachable).slice(), (rhs.cast(.String) catch unreachable).slice() }); + return try self.objects.emplace_cast(.String, &.{ (lhs.cast(.String) catch unreachable).slice(), (rhs.cast(.String) catch unreachable).slice() }); } }.concatenate }; return ret;