random-stuff/esolangs-interpreter-race/orig.js

178 lines
3.9 KiB
JavaScript
Raw Normal View History

2020-08-12 18:16:20 +00:00
const { regex, sequenceOf, char, choice, many1, many, str, coroutine, possibly } = require("arcsecond")
const readline = require("readline-sync")
const spaces = regex(/^ */)
const whitespace = regex(/^[ \n\t]*/)
const name = regex(/^[^ \n\t():]+/)
const code = many(coroutine(function*() {
yield spaces
return yield choice([
coroutine(function*() {
yield char("(")
const x = yield code
yield spaces
yield char(")")
return x
}),
name
])
}))
const program = sequenceOf([
many1(coroutine(function*() {
yield whitespace
const n = yield name
yield whitespace
yield str(":=")
const c = yield code
return { code: c, name: n }
})),
possibly(whitespace)
]).map(([x, _]) => x)
const parsed = program.run(`_mulloop := (pop warp new new new new new new new new new new warp _mulloop)
10* := warp new enter warp _mulloop exit pop warp exit send warp enter
[ := new enter
0 := 10*
1 := 10* new
2 := 10* new new
3 := 10* new new new
4 := 10* new new new new
5 := 10* new new new new new
6 := 10* new new new new new new
7 := 10* new new new new new new new
8 := 10* new new new new new new new new
9 := 10* new new new new new new new new new
] := exit
. := ] write [
main := [ 7 2 . 1 0 1 . 1 0 8 . 1 0 8 . 1 1 1 . 4 4 . 3 2 . 1 1 9 . 1 1 1 . 1 1 4 . 1 0 8 . 1 0 0 . 3 3 . 1 0 . ]
`).result
//const parsed = program.run(`main := read write main`).result
// ---------
let stackL = {depth: 0, children: []}, stackR = {depth: 0, children: []};
let currentIsLeft = true;
function depthDelta(x) {
if(currentIsLeft)
stackL["depth"]+=x;
else
stackR["depth"]+=x;
}
function currentStack() {
let depth, currentStack;
if(currentIsLeft) {
depth = stackL["depth"];
currentStack = stackL["children"];
} else {
depth = stackR["depth"];
currentStack = stackR["children"];
}
for(let i = 0; i < depth; i++) {
const s = currentStack.length - 1
currentStack = currentStack[s];
}
return currentStack;
}
// ---------
function wrap_new() {
currentStack().push([]);
}
function wrap_pop() {
currentStack().pop();
}
function wrap_enter() {
depthDelta(1)
}
function wrap_exit() {
depthDelta(-1)
}
function wrap_warp() {
currentIsLeft = !currentIsLeft;
}
function wrap_send() {
let toMove = currentStack().pop();
wrap_warp();
currentStack().push(toMove);
wrap_warp()
}
function wrap_read(n) {
let thisStack = [];
for(let i = 0; i < n; i++) {
thisStack.push([]);
}
currentStack().push(thisStack);
}
function wrap_write() {
return currentStack().pop().length;
}
// ---------
const env = {
warp: wrap_warp,
read: () => {
wrap_read(readline.question("input char: ").codePointAt(0))
},
write: () => {
console.log("output char:", String.fromCodePoint(wrap_write()))
},
send: wrap_send,
exit: wrap_exit,
enter: wrap_enter,
pop: wrap_pop,
new: wrap_new,
}
for (const def of parsed) {
env[def.name] = def.code
}
const DEBUG = false
const execute = code => {
for (const fn of code) {
//console.log("stacks", stackL, stackR)
// is bracketed, run if stack not empty
if (Array.isArray(fn)) {
if (currentStack().length !== 0) {
if (DEBUG) console.log("brackets", fn)
execute(fn)
}
// is a regular function call or whatever, run it
} else {
const v = env[fn]
if (!v) {
throw new Error(fn + " is undefined")
}
if (typeof v === "function") {
if (DEBUG) console.log("builtin", fn)
v()
} else {
if (DEBUG) console.log("normal", fn)
execute(v)
}
}
}
}
execute(env.main)