finish impl for local vars

This commit is contained in:
Luna 2019-06-03 16:24:54 -03:00
parent 26d299cd23
commit d7b78e09e3
3 changed files with 39 additions and 13 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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