Okay so what it takes to build actual stack-based VM runtime for _dynamic_ language.
Basics:
You need a way to represent values in your system. I think almost everything were tried and common way to start is something like this tagged union:
Everything in the VM world would be represented with the Value type that carries the type information.
Next thing we need is the VM state itself. What instruction are we at? This is the minimal we can get away with:
Now the interesting part, how do you represent Instruction? Variable-length instructions or fixed-sized?
I would go for fixed-sized every time as it simplifies everything and it's better for CPU caches.
Well, this is getting too long so let's wrap this up here and continue later.
zig
// not using any fancy syntax here so it's more easier to read
const ValueTag = enum(u8) {
Uninitialized = 0,
Integer = 1,
Boolean = 2,
String = 3,
};
const Value = struct {
tag: ValueTag,
value: union {
boolean: bool,
integer: i64,
string: *VmString,
},
};zig
const Vm = struct {
ip: i32,
bytecode: []Instruction,
halted: bool,
};zig
pub const Op = enum(u8) {
Halt = 0,
Load_Const = 1,
Neg = 2,
Add = 3,
};
pub const Instruction = packed struct(u32) {
op: Op,
rest: u24 = 0,
};commit 60a5e69