finish impl for local vars
This commit is contained in:
parent
26d299cd23
commit
d7b78e09e3
3 changed files with 39 additions and 13 deletions
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
20
src/vm.zig
20
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
|
||||
|
|
Loading…
Reference in a new issue