Bynary/implementation.js

An implementation of Bynary written in node js by User:Conor O'Brien. Make sure you npm install readwrite before running.
== Implementation ==
 const rw = require("readwrite");
 
 const error = (str) => (console.log("\n error: " + str), process.exit())
 
 const bynary = (str) => {
 let regs = new Map([
 ["a", 0],
 ["b", 0],
 ["c", 0],
 ["d", 0],
 ["e", 0],
 ["f", 0],
 ["g", 0],
 ["h", 0]
 ]);
 
 // parse
 let lines = str.split(/\r?\n/).map(e => {
 e = [...e];
 let parse = []
 for(let i = 0; i < e.length; i++){
 if(/[a-z]:/i.test(e[i] + e[i + 1])){
 parse.push(e[i] + ":");
 } else if(/[0-9]/.test(e[i])){
 let build = "";
 while(/[0-9]/.test(e[i])){
 build += e[i++];
 }
 i--;
 parse.push(build);
 } else if(/[a-h]/.test(e[i])){
 parse.push(e[i]);
 }
 }
 return parse;
 });
 
 let index = 0;
 
 let tr = (c) => regs.has(c) ? regs.get(c) : +!!Number(c);
 
 let commands = new Map([
 ["v:", (a, b) => regs.set(a, tr(b))],
 ["d:", (a, b) => +!(regs.get(a)&tr(b))],
 ["i:", (a) => +!(regs.get(a))],
 ["p:", (a) => rw.log(
 (+a ? String.fromCharCode : x => x)(
 parseInt([...regs.values()].join(""), 2)
 ).toString()
 )],
 ["r:", (n) => {
 let nextLine = lines[++index];
 if(typeof n === "undefined")
 n = parseInt([...regs.values()].join(""), 2);
 
 n = Number(n);
 while(n --> 0){
 exec(nextLine);
 }
 }]
 ]);
 
 const exec = (c, lines, index) => {
 if(!c.length) return 0;
 let cp = c.map(e => e);
 let cmd = cp.shift();
 if(!commands.has(cmd))
 error(`unrecognized command ${cmd} at ${c}`);
 
 let efc = commands.get(cmd).bind({
 lines: lines,
 index: index
 });
 
 let n = efc.length;
 let args = [];
 while(n--){
 let next = cp.shift();
 if(typeof next === "undefined"){
 if(cmd !== "r:"){
 error(`insufficient arguments passed to "${cmd}"; expected ${cmd.length}, received ${args.length}`);
 } else {
 break;
 }
 }
 if(next.endsWith(":")){
 let [res, rem] = exec(cp);
 args.push(res);
 cp = rem;
 } else {
 args.push(next);
 }
 }
 
 return [efc(...args), c];
 }
 
 for(index = 0; index < lines.length; index++){
 let line = lines[index];
 if(line && line.length)
 exec(line);
 }
 }
 
 bynary.of = (str) => {
 let bytes = [...str].map(e =>
 [...("00000000" + 
 e.charCodeAt().toString(2)
 ).slice(-8)].map(Number));
 
 let states = [0,0,0,0,0,0,0,0];
 let comp = "";
 let re = "abcdefgh";
 for(let byt of bytes){
 for(let i = 0; i < byt.length; i++){
 if(byt[i] !== states[i]){
 comp += `v:${re[i]},${byt[i]}\n`;
 states[i] = byt[i];
 }
 }
 comp += "p:1\n";
 }
 return comp;
 }
 
 let args = process.argv.slice(2);
 let ind = args.findIndex(e => e === "/c" || e === "-c");
 if(ind >= 0){
 args.splice(ind, 1);
 console.log(bynary.of(args.join(" ")));
 } else {
 let name = args.shift();
 let file = rw.read(name);
 bynary(file);
 }
== Running ==
 node Bynary.js <filename>
or, to convert strings to Bynary:
 node Bynary.js /c "my text"
or
 node Bynary.js -c "my text"
== Notes ==
The example seems to be incorrect, yielding 0x90 0xD0, roughly (unprintable)Ð.
=== Implementation-specific features ===
When no arguments are given to r:, it repeats for the number of times as the number represented in abcdefgh.
== Hello, World! ==
 v:b,1
 v:e,1
 p:1
 v:c,1
 v:e,0
 v:f,1
 v:h,1
 p:1
 v:e,1
 v:h,0
 p:1
 p:1
 v:g,1
 v:h,1
 p:1
 v:b,0
 v:g,0
 v:h,0
 p:1
 v:e,0
 v:f,0
 p:1
 v:b,1
 v:c,0
 v:d,1
 v:f,1
 v:g,1
 v:h,1
 p:1
 v:c,1
 v:d,0
 v:e,1
 p:1
 v:d,1
 v:e,0
 v:f,0
 v:h,0
 p:1
 v:d,0
 v:e,1
 v:f,1
 v:g,0
 p:1
 v:e,0
 p:1
 v:b,0
 v:f,0
 v:h,1
 p:1
This outputs Hello, World!.
Category:Implementations