jorts/src/vm.zig

97 lines
2.6 KiB
Zig
Raw Normal View History

2019-06-01 17:55:11 +00:00
const std = @import("std");
const chunk = @import("chunk.zig");
const value = @import("value.zig");
const Chunk = chunk.Chunk;
const StdOut = *std.io.OutStream(std.fs.File.WriteError);
pub const InterpretResult = enum {
Ok,
CompileError,
RuntimeError,
};
pub const VM = struct {
2019-06-01 17:55:11 +00:00
chk: *Chunk,
ip: usize,
stdout: StdOut,
2019-06-01 18:01:39 +00:00
debug_flag: bool,
2019-06-01 17:55:11 +00:00
2019-06-01 18:01:39 +00:00
pub fn init(stdout: StdOut, chk: *Chunk, debug_flag: bool) VM {
2019-06-01 17:55:11 +00:00
return VM{
.stdout = stdout,
.chk = chk,
.ip = 0,
2019-06-01 18:01:39 +00:00
.debug_flag = debug_flag,
2019-06-01 17:55:11 +00:00
};
}
2019-06-01 18:01:39 +00:00
pub fn debug(self: *VM, comptime fmt: []const u8, args: ...) void {
if (self.debug_flag) {
std.debug.warn(fmt, args);
}
}
2019-06-01 17:55:11 +00:00
fn readByte(self: *VM) u8 {
var byte: u8 = self.chk.code[self.ip];
self.ip += 1;
return byte;
}
fn readConst(self: *VM) value.Value {
return self.chk.constants.values[self.readByte()];
}
fn readConstLong(self: *VM) value.Value {
const v3 = self.readByte();
const v2 = self.readByte();
const v1 = self.readByte();
const const_idx = (@intCast(u24, v3) << 16) |
(@intCast(u24, v2) << 8) |
v1;
return self.chk.constants.values[const_idx];
}
fn run(self: *VM) !InterpretResult {
while (true) {
2019-06-01 18:01:39 +00:00
if (self.debug_flag) {
_ = try self.chk.disassembleInstruction(self.stdout, self.ip);
}
2019-06-01 17:55:11 +00:00
var instruction = self.readByte();
switch (instruction) {
chunk.OpCode.Constant => blk: {
var constant = self.readConst();
try value.printValue(self.stdout, constant);
2019-06-01 18:01:39 +00:00
try self.stdout.write("\n");
2019-06-01 17:55:11 +00:00
break :blk;
},
chunk.OpCode.ConstantLong => blk: {
var constant = self.readConstLong();
try value.printValue(self.stdout, constant);
2019-06-01 18:01:39 +00:00
try self.stdout.write("\n");
2019-06-01 17:55:11 +00:00
break :blk;
},
chunk.OpCode.Return => blk: {
return InterpretResult.Ok;
},
else => blk: {
std.debug.warn("Unknown instruction: {x}\n", instruction);
return InterpretResult.RuntimeError;
},
}
}
}
2019-06-01 17:55:11 +00:00
pub fn interpret(self: *VM) !InterpretResult {
self.ip = 0;
2019-06-01 18:01:39 +00:00
self.debug("VM start\n");
var res = try self.run();
self.debug("VM end\n");
return res;
2019-06-01 17:55:11 +00:00
}
};