vm: add dynamically-sized growing stack
This commit is contained in:
parent
3377d1675c
commit
088674bf0b
2 changed files with 36 additions and 26 deletions
|
@ -123,6 +123,6 @@ pub fn main() !void {
|
||||||
try chk.write(chunk.OpCode.Divide, 123);
|
try chk.write(chunk.OpCode.Divide, 123);
|
||||||
try chk.write(chunk.OpCode.Return, 123);
|
try chk.write(chunk.OpCode.Return, 123);
|
||||||
|
|
||||||
var vmach = vm.VM.init(stdout, &chk, true);
|
var vmach = try vm.VM.init(allocator, stdout, &chk, true);
|
||||||
_ = try vmach.interpret();
|
_ = try vmach.interpret();
|
||||||
}
|
}
|
||||||
|
|
60
src/vm.zig
60
src/vm.zig
|
@ -3,9 +3,9 @@ const chunk = @import("chunk.zig");
|
||||||
const value = @import("value.zig");
|
const value = @import("value.zig");
|
||||||
|
|
||||||
const Chunk = chunk.Chunk;
|
const Chunk = chunk.Chunk;
|
||||||
const StdOut = *std.io.OutStream(std.fs.File.WriteError);
|
const Value = value.Value;
|
||||||
|
|
||||||
pub const STACK_MAX = 256;
|
const StdOut = *std.io.OutStream(std.fs.File.WriteError);
|
||||||
|
|
||||||
pub const InterpretResult = enum {
|
pub const InterpretResult = enum {
|
||||||
Ok,
|
Ok,
|
||||||
|
@ -17,24 +17,30 @@ pub const VM = struct {
|
||||||
chk: *Chunk,
|
chk: *Chunk,
|
||||||
ip: usize = 0,
|
ip: usize = 0,
|
||||||
|
|
||||||
stack: [STACK_MAX]value.Value,
|
stack: []Value,
|
||||||
stackTop: usize = 0,
|
stackTop: usize = 0,
|
||||||
|
|
||||||
stdout: StdOut,
|
stdout: StdOut,
|
||||||
debug_flag: bool,
|
debug_flag: bool,
|
||||||
|
allocator: *std.mem.Allocator,
|
||||||
|
|
||||||
fn resetStack(self: *VM) void {
|
fn resetStack(self: *VM) void {
|
||||||
self.stackTop = 0;
|
self.stackTop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(stdout: StdOut, chk: *Chunk, debug_flag: bool) VM {
|
pub fn init(
|
||||||
|
allocator: *std.mem.Allocator,
|
||||||
|
stdout: StdOut,
|
||||||
|
chk: *Chunk,
|
||||||
|
debug_flag: bool,
|
||||||
|
) !VM {
|
||||||
var self = VM{
|
var self = VM{
|
||||||
.chk = chk,
|
.chk = chk,
|
||||||
|
|
||||||
// TODO move this to a nil value or something.
|
.stack = try allocator.alloc(Value, 256),
|
||||||
.stack = []value.Value{0} ** STACK_MAX,
|
|
||||||
.stdout = stdout,
|
.stdout = stdout,
|
||||||
.debug_flag = debug_flag,
|
.debug_flag = debug_flag,
|
||||||
|
.allocator = allocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.resetStack();
|
self.resetStack();
|
||||||
|
@ -54,11 +60,11 @@ pub const VM = struct {
|
||||||
return byte;
|
return byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readConst(self: *VM) value.Value {
|
fn readConst(self: *VM) Value {
|
||||||
return self.chk.constants.values[self.readByte()];
|
return self.chk.constants.values[self.readByte()];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readConstLong(self: *VM) value.Value {
|
fn readConstLong(self: *VM) Value {
|
||||||
const v3 = self.readByte();
|
const v3 = self.readByte();
|
||||||
const v2 = self.readByte();
|
const v2 = self.readByte();
|
||||||
const v1 = self.readByte();
|
const v1 = self.readByte();
|
||||||
|
@ -86,28 +92,28 @@ pub const VM = struct {
|
||||||
return self.pop();
|
return self.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doAdd(self: *VM) void {
|
fn doAdd(self: *VM) !void {
|
||||||
var b = self.popNum();
|
var b = self.popNum();
|
||||||
var a = self.popNum();
|
var a = self.popNum();
|
||||||
self.push(a + b);
|
try self.push(a + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doSub(self: *VM) void {
|
fn doSub(self: *VM) !void {
|
||||||
var b = self.popNum();
|
var b = self.popNum();
|
||||||
var a = self.popNum();
|
var a = self.popNum();
|
||||||
self.push(a * b);
|
try self.push(a * b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doMul(self: *VM) void {
|
fn doMul(self: *VM) !void {
|
||||||
var b = self.popNum();
|
var b = self.popNum();
|
||||||
var a = self.popNum();
|
var a = self.popNum();
|
||||||
self.push(a * b);
|
try self.push(a * b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doDiv(self: *VM) void {
|
fn doDiv(self: *VM) !void {
|
||||||
var b = self.popNum();
|
var b = self.popNum();
|
||||||
var a = self.popNum();
|
var a = self.popNum();
|
||||||
self.push(a / b);
|
try self.push(a / b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self: *VM) !InterpretResult {
|
fn run(self: *VM) !InterpretResult {
|
||||||
|
@ -122,12 +128,12 @@ pub const VM = struct {
|
||||||
switch (instruction) {
|
switch (instruction) {
|
||||||
chunk.OpCode.Constant => blk: {
|
chunk.OpCode.Constant => blk: {
|
||||||
var constant = self.readConst();
|
var constant = self.readConst();
|
||||||
self.push(constant);
|
try self.push(constant);
|
||||||
break :blk;
|
break :blk;
|
||||||
},
|
},
|
||||||
chunk.OpCode.ConstantLong => blk: {
|
chunk.OpCode.ConstantLong => blk: {
|
||||||
var constant = self.readConstLong();
|
var constant = self.readConstLong();
|
||||||
self.push(constant);
|
try self.push(constant);
|
||||||
break :blk;
|
break :blk;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -137,11 +143,11 @@ pub const VM = struct {
|
||||||
return InterpretResult.Ok;
|
return InterpretResult.Ok;
|
||||||
},
|
},
|
||||||
|
|
||||||
chunk.OpCode.Add => self.doAdd(),
|
chunk.OpCode.Add => try self.doAdd(),
|
||||||
chunk.OpCode.Subtract => self.doSub(),
|
chunk.OpCode.Subtract => try self.doSub(),
|
||||||
chunk.OpCode.Multiply => self.doMul(),
|
chunk.OpCode.Multiply => try self.doMul(),
|
||||||
chunk.OpCode.Divide => self.doDiv(),
|
chunk.OpCode.Divide => try self.doDiv(),
|
||||||
chunk.OpCode.Negate => self.push(-self.pop()),
|
chunk.OpCode.Negate => try self.push(-self.pop()),
|
||||||
else => blk: {
|
else => blk: {
|
||||||
std.debug.warn("Unknown instruction: {x}\n", instruction);
|
std.debug.warn("Unknown instruction: {x}\n", instruction);
|
||||||
return InterpretResult.RuntimeError;
|
return InterpretResult.RuntimeError;
|
||||||
|
@ -159,12 +165,16 @@ pub const VM = struct {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(self: *VM, val: value.Value) void {
|
pub fn push(self: *VM, val: Value) !void {
|
||||||
|
if (self.stackTop > 0 and self.stackTop - 1 > self.stack.len) {
|
||||||
|
self.stack = try self.allocator.realloc(self.stack, self.stack.len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
self.stack[self.stackTop] = val;
|
self.stack[self.stackTop] = val;
|
||||||
self.stackTop += 1;
|
self.stackTop += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop(self: *VM) value.Value {
|
pub fn pop(self: *VM) Value {
|
||||||
self.stackTop -= 1;
|
self.stackTop -= 1;
|
||||||
return self.stack[self.stackTop];
|
return self.stack[self.stackTop];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue