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;
|
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 {
|
pub const ConstantIndexTag = enum {
|
||||||
Small,
|
Small,
|
||||||
Long,
|
Long,
|
||||||
|
@ -254,6 +265,10 @@ pub const Chunk = struct {
|
||||||
return try constantInstruction(stdout, "OP_SETGLOBAL", self, index);
|
return try constantInstruction(stdout, "OP_SETGLOBAL", self, index);
|
||||||
} else if (instruction == OpCode.SetGlobalLong) {
|
} else if (instruction == OpCode.SetGlobalLong) {
|
||||||
return try constantLongInstruction(stdout, "OP_SETGLOBAL_LONG", self, index);
|
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 {
|
} else {
|
||||||
try stdout.print("Unknown opcode: {}\n", instruction);
|
try stdout.print("Unknown opcode: {}\n", instruction);
|
||||||
return index + 1;
|
return index + 1;
|
||||||
|
|
|
@ -287,6 +287,9 @@ pub const Compiler = struct {
|
||||||
var idx = @intCast(usize, i);
|
var idx = @intCast(usize, i);
|
||||||
var local = &self.locals[idx];
|
var local = &self.locals[idx];
|
||||||
if (std.mem.eql(u8, name.lexeme, local.name.lexeme)) {
|
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;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,7 +456,8 @@ pub const Compiler = struct {
|
||||||
self.localCount += 1;
|
self.localCount += 1;
|
||||||
var local: *Local = &self.locals[@intCast(usize, self.localCount)];
|
var local: *Local = &self.locals[@intCast(usize, self.localCount)];
|
||||||
local.name = name;
|
local.name = name;
|
||||||
local.depth = self.scopeDepth;
|
//local.depth = self.scopeDepth;
|
||||||
|
local.depth = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declareVariable(self: *Compiler) void {
|
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 {
|
fn defineVariable(self: *Compiler, global: chunks.ConstantIndex) !void {
|
||||||
if (self.scopeDepth > 0) return;
|
if (self.scopeDepth > 0) {
|
||||||
|
self.markInitialized();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try self.emitConstWithIndex(
|
try self.emitConstWithIndex(
|
||||||
chunks.OpCode.DefineGlobal,
|
chunks.OpCode.DefineGlobal,
|
||||||
|
|
20
src/vm.zig
20
src/vm.zig
|
@ -294,26 +294,24 @@ pub const VM = struct {
|
||||||
|
|
||||||
chunk.OpCode.Pop => blk: {
|
chunk.OpCode.Pop => blk: {
|
||||||
_ = self.pop();
|
_ = 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: {
|
chunk.OpCode.GetGlobal => blk: {
|
||||||
try self.doGetGlobal(self.readString());
|
try self.doGetGlobal(self.readString());
|
||||||
break :blk;
|
|
||||||
},
|
},
|
||||||
chunk.OpCode.GetGlobalLong => blk: {
|
|
||||||
try self.doGetGlobal(self.readStringLong());
|
|
||||||
break :blk;
|
|
||||||
},
|
|
||||||
|
|
||||||
chunk.OpCode.SetGlobal => blk: {
|
chunk.OpCode.SetGlobal => blk: {
|
||||||
try self.doSetGlobal(self.readString());
|
try self.doSetGlobal(self.readString());
|
||||||
break :blk;
|
break :blk;
|
||||||
},
|
},
|
||||||
chunk.OpCode.SetGlobalLong => blk: {
|
|
||||||
try self.doSetGlobal(self.readStringLong());
|
|
||||||
break :blk;
|
|
||||||
},
|
|
||||||
|
|
||||||
// extracting the name is different depending of the
|
// extracting the name is different depending of the
|
||||||
// op code since one just uses a single byte, the other
|
// op code since one just uses a single byte, the other
|
||||||
|
|
Loading…
Reference in a new issue