diff --git a/src/chunk.zig b/src/chunk.zig index bcfc23e..a244bd2 100644 --- a/src/chunk.zig +++ b/src/chunk.zig @@ -88,6 +88,17 @@ fn constantLongInstruction( return offset + 4; } +fn byteInstruction( + stdout: var, + name: []const u8, + chunk: *Chunk, + index: usize, +) !usize { + var slot: u8 = chunk.code[index + 1]; + try stdout.print("{} {}", name, slot); + return index + 2; +} + pub const ConstantIndexTag = enum { Small, Long, @@ -254,6 +265,10 @@ pub const Chunk = struct { return try constantInstruction(stdout, "OP_SETGLOBAL", self, index); } else if (instruction == OpCode.SetGlobalLong) { return try constantLongInstruction(stdout, "OP_SETGLOBAL_LONG", self, index); + } else if (instruction == OpCode.GetLocal) { + return try byteInstruction(stdout, "OP_GETLOCAL", self, index); + } else if (instruction == OpCode.SetLocal) { + return try byteInstruction(stdout, "OP_GETLOCAL", self, index); } else { try stdout.print("Unknown opcode: {}\n", instruction); return index + 1; diff --git a/src/compiler.zig b/src/compiler.zig index 7b51ca4..398741b 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -287,6 +287,9 @@ pub const Compiler = struct { var idx = @intCast(usize, i); var local = &self.locals[idx]; if (std.mem.eql(u8, name.lexeme, local.name.lexeme)) { + if (local.depth == -1) { + self.errorCurrent("Cannot read local variable in its own initializer."); + } return i; } } @@ -453,7 +456,8 @@ pub const Compiler = struct { self.localCount += 1; var local: *Local = &self.locals[@intCast(usize, self.localCount)]; local.name = name; - local.depth = self.scopeDepth; + //local.depth = self.scopeDepth; + local.depth = -1; } fn declareVariable(self: *Compiler) void { @@ -502,8 +506,17 @@ pub const Compiler = struct { } } + fn markInitialized(self: *Compiler) void { + if (self.scopeDepth == 0) return; + var idx = @intCast(usize, self.localCount); + self.locals[idx].depth = self.scopeDepth; + } + fn defineVariable(self: *Compiler, global: chunks.ConstantIndex) !void { - if (self.scopeDepth > 0) return; + if (self.scopeDepth > 0) { + self.markInitialized(); + return; + } try self.emitConstWithIndex( chunks.OpCode.DefineGlobal, diff --git a/src/vm.zig b/src/vm.zig index d2b923d..b3e3942 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -294,26 +294,24 @@ pub const VM = struct { chunk.OpCode.Pop => blk: { _ = self.pop(); - break :blk; + }, + + chunk.OpCode.GetLocal => blk: { + var slot = self.readByte(); + try self.push(self.stack[slot]); + }, + chunk.OpCode.SetLocal => blk: { + var slot = self.readByte(); + self.stack[slot] = self.peek(0); }, chunk.OpCode.GetGlobal => blk: { try self.doGetGlobal(self.readString()); - break :blk; }, - chunk.OpCode.GetGlobalLong => blk: { - try self.doGetGlobal(self.readStringLong()); - break :blk; - }, - chunk.OpCode.SetGlobal => blk: { try self.doSetGlobal(self.readString()); break :blk; }, - chunk.OpCode.SetGlobalLong => blk: { - try self.doSetGlobal(self.readStringLong()); - break :blk; - }, // extracting the name is different depending of the // op code since one just uses a single byte, the other