vm: add getglobal support

This commit is contained in:
Luna 2019-06-02 23:57:28 -03:00
parent 887cb1adea
commit 005981fbbd
3 changed files with 35 additions and 3 deletions

View file

@ -223,6 +223,10 @@ pub const Chunk = struct {
return try simpleInstruction(stdout, "OP_DEFGLOBAL", index);
} else if (instruction == OpCode.DefineGlobalLong) {
return try simpleInstruction(stdout, "OP_DEFGLOBAL_LONG", index);
} else if (instruction == OpCode.GetGlobal) {
return try simpleInstruction(stdout, "OP_GETGLOBAL", index);
} else if (instruction == OpCode.GetGlobalLong) {
return try simpleInstruction(stdout, "OP_GETGLOBAL_LONG", index);
} else {
try stdout.print("Unknown opcode: {}\n", instruction);
return index + 1;

View file

@ -262,7 +262,7 @@ pub const Compiler = struct {
}
fn variable(self: *Compiler) !void {
try self.namedVariable(self.parser.previous);
try self.namedVariable(&self.parser.previous);
}
/// Emits bytecode for a given unary.

View file

@ -230,6 +230,25 @@ pub const VM = struct {
_ = self.pop();
}
fn readString(self: *VM) []u8 {
return self.readConst().as.Object.value.String;
}
fn readStringLong(self: *VM) []u8 {
return self.readConstLong().as.Object.value.String;
}
fn doGetGlobal(self: *VM, name: []u8) !void {
var kv_opt = self.globals.get(name);
if (kv_opt) |kv| {
try self.push(kv.value);
} else {
self.runtimeError("Undefined variable '{}'.", name);
return InterpretResult.RuntimeError;
}
}
fn run(self: *VM) !void {
while (true) {
if (self.debug_flag) {
@ -271,15 +290,24 @@ pub const VM = struct {
break :blk;
},
chunk.OpCode.GetGlobal => blk: {
try self.doGetGlobal(self.readString());
break :blk;
},
chunk.OpCode.GetGlobalLong => blk: {
try self.doGetGlobal(self.readStringLong());
break :blk;
},
// extracting the name is different depending of the
// op code since one just uses a single byte, the other
// uses three bytes since its a u24.
chunk.OpCode.DefineGlobal => blk: {
try self.defGlobal(self.readConst().as.Object.value.String);
try self.defGlobal(self.readString());
break :blk;
},
chunk.OpCode.DefineGlobalLong => blk: {
try self.defGlobal(self.readConstLong().as.Object.value.String);
try self.defGlobal(self.readStringLong());
break :blk;
},