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.Return, 123);
|
||||
|
||||
var vmach = vm.VM.init(stdout, &chk, true);
|
||||
var vmach = try vm.VM.init(allocator, stdout, &chk, true);
|
||||
_ = 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 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 {
|
||||
Ok,
|
||||
|
@ -17,24 +17,30 @@ pub const VM = struct {
|
|||
chk: *Chunk,
|
||||
ip: usize = 0,
|
||||
|
||||
stack: [STACK_MAX]value.Value,
|
||||
stack: []Value,
|
||||
stackTop: usize = 0,
|
||||
|
||||
stdout: StdOut,
|
||||
debug_flag: bool,
|
||||
allocator: *std.mem.Allocator,
|
||||
|
||||
fn resetStack(self: *VM) void {
|
||||
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{
|
||||
.chk = chk,
|
||||
|
||||
// TODO move this to a nil value or something.
|
||||
.stack = []value.Value{0} ** STACK_MAX,
|
||||
.stack = try allocator.alloc(Value, 256),
|
||||
.stdout = stdout,
|
||||
.debug_flag = debug_flag,
|
||||
.allocator = allocator,
|
||||
};
|
||||
|
||||
self.resetStack();
|
||||
|
@ -54,11 +60,11 @@ pub const VM = struct {
|
|||
return byte;
|
||||
}
|
||||
|
||||
fn readConst(self: *VM) value.Value {
|
||||
fn readConst(self: *VM) Value {
|
||||
return self.chk.constants.values[self.readByte()];
|
||||
}
|
||||
|
||||
fn readConstLong(self: *VM) value.Value {
|
||||
fn readConstLong(self: *VM) Value {
|
||||
const v3 = self.readByte();
|
||||
const v2 = self.readByte();
|
||||
const v1 = self.readByte();
|
||||
|
@ -86,28 +92,28 @@ pub const VM = struct {
|
|||
return self.pop();
|
||||
}
|
||||
|
||||
fn doAdd(self: *VM) void {
|
||||
fn doAdd(self: *VM) !void {
|
||||
var b = 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 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 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 a = self.popNum();
|
||||
self.push(a / b);
|
||||
try self.push(a / b);
|
||||
}
|
||||
|
||||
fn run(self: *VM) !InterpretResult {
|
||||
|
@ -122,12 +128,12 @@ pub const VM = struct {
|
|||
switch (instruction) {
|
||||
chunk.OpCode.Constant => blk: {
|
||||
var constant = self.readConst();
|
||||
self.push(constant);
|
||||
try self.push(constant);
|
||||
break :blk;
|
||||
},
|
||||
chunk.OpCode.ConstantLong => blk: {
|
||||
var constant = self.readConstLong();
|
||||
self.push(constant);
|
||||
try self.push(constant);
|
||||
break :blk;
|
||||
},
|
||||
|
||||
|
@ -137,11 +143,11 @@ pub const VM = struct {
|
|||
return InterpretResult.Ok;
|
||||
},
|
||||
|
||||
chunk.OpCode.Add => self.doAdd(),
|
||||
chunk.OpCode.Subtract => self.doSub(),
|
||||
chunk.OpCode.Multiply => self.doMul(),
|
||||
chunk.OpCode.Divide => self.doDiv(),
|
||||
chunk.OpCode.Negate => self.push(-self.pop()),
|
||||
chunk.OpCode.Add => try self.doAdd(),
|
||||
chunk.OpCode.Subtract => try self.doSub(),
|
||||
chunk.OpCode.Multiply => try self.doMul(),
|
||||
chunk.OpCode.Divide => try self.doDiv(),
|
||||
chunk.OpCode.Negate => try self.push(-self.pop()),
|
||||
else => blk: {
|
||||
std.debug.warn("Unknown instruction: {x}\n", instruction);
|
||||
return InterpretResult.RuntimeError;
|
||||
|
@ -159,12 +165,16 @@ pub const VM = struct {
|
|||
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.stackTop += 1;
|
||||
}
|
||||
|
||||
pub fn pop(self: *VM) value.Value {
|
||||
pub fn pop(self: *VM) Value {
|
||||
self.stackTop -= 1;
|
||||
return self.stack[self.stackTop];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue