Bynary/implementation.js

From Esolang
Jump to navigation Jump to search

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!.