Created
September 26, 2020 05:22
-
-
Save lancejpollard/3561afecd3d2593b335341beb47477c9 to your computer and use it in GitHub Desktop.
Virtual Machine Version 8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const START = 256 | |
const I_INSTRUCTION_POSITION = 0 | |
const I_PARAM_1 = 1 | |
const I_PARAM_2 = 2 | |
const I_PARAM_3 = 3 | |
const I_PARAM_4 = 4 | |
const I_PARAM_5 = 5 | |
const I_PARAM_6 = 6 | |
const I_PARAM_7 = 7 | |
const I_PARAM_8 = 8 | |
const I_SYSCALL_ARITY = 10 | |
const I_SYSCALL_HAS_RETURN_MULTIPLIER = 11 | |
const I_SYSCALL_CURRENT_PARAM = 12 | |
const I_SYSCALL_RETURN_VALUE = 13 | |
const I_SYSCALL_FETCH_STORAGE = 14 | |
const I_SYSCALL_BLOCK_START = 15 | |
const I_MEMORY_ARRAY = 32 | |
const I_MAIN_THRESHOLD_TIME = 26 | |
const I_MAIN_THRESHOLD_ITERATION = 27 | |
const I_MAIN_ITERATION_START_TIME = 28 | |
const I_MAIN_ITERATION_END_TIME = 29 | |
const I_MAIN_ITERATION = 30 | |
const I_MAIN_IS_PAST_TIME = 31 | |
const INST_SIZE_NATIVE = 0 | |
const INST_CONNECT_NATIVE = 1 | |
const INST_PUSH_NATIVE = 2 | |
const INST_CALL_NATIVE = 3 | |
const SYS_EXIT = 0 | |
const SYS_ADD = 1 | |
const SYS_SUB = 2 | |
const SYS_MUL = 3 | |
const SYS_LOG = 4 | |
const instructions = [ | |
inst_size_native, | |
inst_connect_native, | |
inst_push_native, | |
inst_call_native, | |
] | |
const syscall_types = [ | |
syscall0, | |
syscall1, | |
syscall2, | |
syscall3, | |
syscall4, | |
syscall5, | |
syscall6, | |
syscall7, | |
syscall0_with_return, | |
syscall1_with_return, | |
syscall2_with_return, | |
syscall3_with_return, | |
syscall4_with_return, | |
syscall5_with_return, | |
syscall6_with_return, | |
syscall7_with_return | |
] | |
const syscalls = [ | |
sys_exit, | |
sys_add, | |
sys_sub, | |
sys_mul, | |
sys_log | |
] | |
const db = new Uint32Array(65536) | |
// initialize memory | |
db[I_SYSCALL_CURRENT_PARAM] = 1 | |
db[I_SYSCALL_HAS_RETURN_MULTIPLIER] = 1 | |
db[0] = START + 32 // start instruction | |
// console.log(219) | |
db[START + 32] = INST_SIZE_NATIVE | |
db[START + 32 + 1] = 1 | |
db[START + 34] = INST_PUSH_NATIVE | |
db[START + 34 + 1] = 219 // input | |
db[START + 36] = INST_CALL_NATIVE | |
db[START + 36 + 1] = SYS_LOG | |
// exit(0) | |
db[START + 38] = INST_SIZE_NATIVE | |
db[START + 40 + 1] = 1 | |
db[START + 42] = INST_PUSH_NATIVE | |
db[START + 42 + 1] = 0 // input | |
db[START + 44] = INST_CALL_NATIVE | |
db[START + 44 + 1] = SYS_EXIT | |
start() | |
function start() { | |
db[I_MAIN_THRESHOLD_TIME] = 8 | |
db[I_MAIN_THRESHOLD_ITERATION] = 65536 | |
db[I_MAIN_ITERATION_START_TIME] = Date.now() | |
db[I_MAIN_ITERATION] = 0 | |
db[I_MAIN_IS_PAST_TIME] = 0 | |
// loop for a specific amount of time | |
while (!db[I_MAIN_IS_PAST_TIME]) { | |
// loop up to a specific number of iterations | |
while (db[I_MAIN_ITERATION] < db[I_MAIN_THRESHOLD_ITERATION]) { | |
db[I_MAIN_ITERATION]++ | |
step() | |
} | |
// check if we can break out of the main loop | |
// to allow for events to interrupt. | |
db[I_MAIN_ITERATION_END_TIME] = Date.now() | |
db[I_MAIN_IS_PAST_TIME] = db[I_MAIN_ITERATION_END_TIME] | |
- db[I_MAIN_ITERATION_START_TIME] | |
> db[I_MAIN_THRESHOLD_TIME] | |
} | |
// allow for events to interrupt. | |
setImmediate(start) | |
} | |
function step() { | |
let next = db[I_INSTRUCTION_POSITION] | |
let instruction = db[next] | |
let input = db[next + 1] | |
// console.log(`${instruction}(${input})`) | |
instructions[instruction](input) | |
db[I_INSTRUCTION_POSITION] = next + 2 | |
} | |
// create nested call stack | |
function inst_nest() { | |
db[I_SYSCALL_BLOCK_START + 1] = next | |
} | |
function inst_fetch(index) { | |
db[I_SYSCALL_FETCH_STORAGE] = index | |
} | |
function inst_store(index) { | |
db[index] = db[db[I_SYSCALL_FETCH_STORAGE]] | |
} | |
function inst_store_on_stack(index) { | |
db[db[I_SYSCALL_BLOCK_START] + index] = db[db[I_SYSCALL_FETCH_STORAGE]] | |
} | |
function allocate(size) { | |
db[MEMORY_START] | |
} | |
// size(2) | |
// connect(1) // returns | |
// push(1) | |
// push(100) | |
// call(100) | |
function inst_push_native(value) { | |
db[db[I_SYSCALL_CURRENT_PARAM]] = value | |
db[I_SYSCALL_CURRENT_PARAM]++ | |
} | |
function inst_size_native(x) { | |
db[I_SYSCALL_ARITY] = x | |
} | |
function inst_connect_native(multiplier) { | |
db[I_SYSCALL_HAS_RETURN_MULTIPLIER] = multiplier | |
} | |
function inst_call_native(index) { | |
const syscall_type = db[I_SYSCALL_ARITY] * db[I_SYSCALL_HAS_RETURN_MULTIPLIER] | |
syscall_types[syscall_type](index) | |
db[I_SYSCALL_CURRENT_PARAM] = 1 | |
db[I_SYSCALL_HAS_RETURN_MULTIPLIER] = 1 | |
} | |
function syscall0(index) { | |
syscalls[index]() | |
} | |
function syscall1(index) { | |
let i1 = db[I_PARAM_1] | |
syscalls[index](i1) | |
} | |
function syscall2(index) { | |
let i1 = db[I_PARAM_1] | |
let i2 = db[I_PARAM_2] | |
syscalls[index]() | |
} | |
function syscall3(index) { | |
let i1 = db[I_PARAM_1] | |
let i2 = db[I_PARAM_2] | |
let i3 = db[I_PARAM_3] | |
syscalls[index]() | |
} | |
function syscall4(index) { | |
// ... | |
syscalls[index]() | |
} | |
function syscall5(index) { | |
// ... | |
syscalls[index]() | |
} | |
function syscall6(index) { | |
// ... | |
syscalls[index]() | |
} | |
function syscall7(index) { | |
// ... | |
syscalls[index]() | |
} | |
function syscall0_with_return(index) { | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index]() | |
} | |
function syscall1_with_return(index) { | |
const i1 = db[I_PARAM_1] | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index](i1) | |
} | |
function syscall2_with_return(index) { | |
const i1 = db[I_PARAM_1] | |
const i2 = db[I_PARAM_2] | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index](i1, i2) | |
} | |
function syscall3_with_return(index) { | |
const i1 = db[I_PARAM_1] | |
const i2 = db[I_PARAM_2] | |
const i3 = db[I_PARAM_3] | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index](i1, i2, i3) | |
} | |
function syscall4_with_return(index) { | |
// ... | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index]() | |
} | |
function syscall5_with_return(index) { | |
// ... | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index]() | |
} | |
function syscall6_with_return(index) { | |
// ... | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index]() | |
} | |
function syscall7_with_return(index) { | |
// ... | |
db[I_SYSCALL_RETURN_VALUE] = syscalls[index]() | |
} | |
function sys_exit(code) { | |
process.exit(code) | |
} | |
function sys_add(a, b) { | |
return a + b | |
} | |
function sys_sub(a, b) { | |
return a - b | |
} | |
function sys_mul(a, b) { | |
return a * b | |
} | |
function sys_log(str) { | |
console.log(str) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment