BrainCurses/implementation.js
Jump to navigation
Jump to search
This is an implementation of BrainCurses in node.js, written by User:Conor O'Brien.
Implementation
Remember to npm install readwrite before running.
const rw = require("readwrite");
class Dequeue extends Array {
pop(){
if(this.length === 0) return 0;
return super.pop();
}
get top(){
let v = this.pop();
this.push(v);
return v;
}
set top(v){
return this[this.length - 1] = v;
}
inject(value){
return this.unshift(value);
}
eject(){
return this.shift();
}
}
class BrainCurses {
constructor(program){
this.code = program.match(/'.|\[\$|./g);
this.A = 0;
this.Dequeue = new Dequeue();
this.instructions = new Map([
["!", () => this.Dequeue.push(this.A)],
["@", () => this.A = this.Dequeue.pop()],
["^", () => this.Dequeue.inject(this.Dequeue.pop())],
["#", () => this.Dequeue.push(this.Dequeue.eject())],
["+", () => this.A++],
["-", () => this.A--],
[":", (output, input) => output(this.A)],
[";", (output, input) => this.A = input()],
["%", () => [this.A, this.Dequeue.top] = [this.Dequeue.top, this.A]],
["*", () => this.Dequeue.top = this.A],
["&", () => this.A = this.Dequeue.top],
["[", () => {
if(this.A !== 0) return;
let i, depth;
for(i = this.index + 1, depth = 1; depth && i < this.code.length; i++){
if(this.code[i][0] === "[") depth++;
else if(this.code[i] === "]") depth--;
}
this.index = i - 1;
}],
["[$", () => {
if(this.Dequeue.top !== 0) return;
let i, depth;
for(i = this.index + 1, depth = 1; depth && i < this.code.length; i++){
if(this.code[i][0] === "[") depth++;
else if(this.code[i] === "]") depth--;
}
this.index = i - 1;
}],
["]", () => {
let i, depth;
for(i = this.index - 1, depth = 1; depth && i >= 0; --i){
if(this.code[i][0] === "[") depth--;
else if(this.code[i] === "]") depth++;
}
this.index = i;
}],
["_", (output, input) => output(String.fromCharCode(this.A))]
]);
}
execute(output, input){
for(this.index = 0; this.index < this.code.length; this.index++){
let cmd = this.code[this.index];
// console.log(cmd, this.Dequeue);
if(this.instructions.has(cmd)){
this.instructions.get(cmd)(output, input);
} else if(cmd[0] === "'"){
this.A = cmd.charCodeAt(1);
}
}
return this;
}
static eval(code, input){
let iar = input.reduce((p,c)=>p.concat(...c),[]).map(e => e.charCodeAt());
let BCinst = new BrainCurses(code);
return BCinst.execute(rw.log, () => iar.length && iar.shift());
}
}
let args = process.argv.slice(2);
let debug = false;
if(args[0] === "-d" || args[0] === "/d"){
debug = true;
args.shift();
}
let res = BrainCurses.eval(rw.read(args.shift()), args);
if(debug) console.log(res.Dequeue);
Usage
node BrainCurses.js <filename> <input>
or
node BrainCurses.js /d <filename> <input>
or
node BrainCurses.js -d <filename> <input>
The latter two print the contents of the dequeue at program termination.
Assumptions
:outputsAas a number;- input reads from left to right
Notices
The string reversal example given on the page ([;!]#[$@_#]) seems to be incorrect, at least, as per this implementation; the correct way of doing it would be this:
;[!;][$@_]