Skip to content

Instantly share code, notes, and snippets.

@0xF6
Last active June 20, 2024 16:22
Show Gist options
  • Save 0xF6/2c3c731ee9490b9bb4e07ed5579e6b23 to your computer and use it in GitHub Desktop.
Save 0xF6/2c3c731ee9490b9bb4e07ed5579e6b23 to your computer and use it in GitHub Desktop.
Minimal Virtual Machine realization in typescript
enum Instructions {
NOP, // nope operation
ADD, // addtive operation (sum two stack values)
SUB, // substract
DIV, // divide
MUL, // multiple
LD_ARGS, // load from args into stack (load data value with offset from args into stack)
LDS_NUM, // load constant value into stack
RET // return
}
type StackType = "number";
interface IVMStack {
val: number;
type: StackType;
}
interface IInvocation {
args: IVMStack[];
code: Int32Array;
retValue: IVMStack;
}
function exec_code(invocation: IInvocation) {
let sp_offset = 0;
let sp = [] as IVMStack[];
let ip = 0;
let ip_end = invocation.code.length;
let { code, args } = invocation;
while(1)
{
if (ip == ip_end)
throw "end of executable memory";
console.log(Instructions[ip], sp);
switch(code[ip])
{
case Instructions.NOP:
ip++;
break;
case Instructions.ADD:
ip++;
--sp_offset; --sp_offset;
sp[sp_offset].val = sp[sp_offset].val + sp[sp_offset + 1].val;
break;
case Instructions.SUB:
ip++;
--sp_offset; --sp_offset;
sp[sp_offset].val = sp[sp_offset].val - sp[sp_offset + 1].val;
break;
case Instructions.DIV:
ip++;
--sp_offset; --sp_offset;
sp[sp_offset].val = sp[sp_offset].val / sp[sp_offset + 1].val;
break;
case Instructions.MUL:
ip++;
--sp_offset; --sp_offset;
sp[sp_offset].val = sp[sp_offset].val * sp[sp_offset + 1].val;
break;
case Instructions.LD_ARGS:
ip++;
sp[sp_offset] = args[code[ip]];
sp_offset++;
ip++;
break;
case Instructions.LDS_NUM:
ip++;
sp_offset++;
sp[sp_offset] = { type: "number", val: code[ip] };
ip++;
sp_offset++;
break;
case Instructions.RET:
ip++;
invocation.retValue = sp[sp_offset];
return;
}
}
}
console.log("Huita ebanya!");
let invocation: IInvocation = {
args: [
{type: "number", val: 1488 },
{type: "number", val: 228 }
],
code: new Int32Array([
Instructions.NOP,
Instructions.LD_ARGS,
0,
Instructions.LD_ARGS,
1,
Instructions.ADD,
Instructions.LDS_NUM,
2,
Instructions.MUL,
Instructions.RET
]),
retValue: { type: "number", val: 0 }
};
console.time('exec');
exec_code(invocation);
console.timeEnd('exec');
console.log(`Success, return value: ${invocation.retValue.val}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment