From 088674bf0b17cf494a4f57aba7685a73d14017df Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 1 Jun 2019 15:45:30 -0300 Subject: [PATCH] vm: add dynamically-sized growing stack --- src/main.zig | 2 +- src/vm.zig | 60 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/main.zig b/src/main.zig index 8cd531f..b43afc1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -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(); } diff --git a/src/vm.zig b/src/vm.zig index 990f81f..467651a 100644 --- a/src/vm.zig +++ b/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]; }