From c04ec4914b6be77d29acc15915b60c072baa6849 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 14 Apr 2021 22:16:10 -0400 Subject: Allow running bqn.js on a file argument --- docs/bqn.js | 31 +++++++++++++++++++++++-------- docs/running.html | 2 +- running.md | 2 +- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/docs/bqn.js b/docs/bqn.js index 20b76b0c..4af176a6 100755 --- a/docs/bqn.js +++ b/docs/bqn.js @@ -316,10 +316,11 @@ let unixtime = (x,w) => Date.now()/1000; let req1str = (e,x,w) => { if (!isstr(x)) throw Error(e+" 𝕩: 𝕩 must be a string"); if (has(w)) throw Error(e+": 𝕨 not allowed"); + return x.join(""); } let dojs = (x,w) => { - req1str("•JS",x,w); - let r = Function("'use strict'; return ("+x.join("")+")")(); + let s = req1str("•JS",x,w); + let r = Function("'use strict'; return ("+s+")")(); let toBQN = x => { if (isnum(x)) return x; if (typeof x==='string') { if (Array.from(x).length!==1) throw Error("•JS: JS strings are one character; use Array.from for BQN strings"); return x; } @@ -330,7 +331,7 @@ let dojs = (x,w) => { return toBQN(r); } let sysvals = { - bqn:(x,w)=>{req1str("•BQN",x,w);return bqn(x);}, js:dojs, + bqn:(x,w)=> bqn(req1str("•BQN",x,w)), js:dojs, type, glyph, decompose, fmt:fmt1, unixtime, listsys: () => list(Object.keys(sysvals).map(str).sort()) }; @@ -364,16 +365,30 @@ if (typeof module!=='undefined') { // Node.js let show = x => console.log(fmt(x)); sysvals.show = (x,w) => { show(x); return x; }; - sysvals.out = (x,w) => { req1str("•Out",x,w);console.log(x.join("")); return x; }; + sysvals.out = (x,w) => { console.log(req1str("•Out",x,w)); return x; }; if (!module.parent) { let args = process.argv.slice(2); - args.map(a=>{ + let arg0 = args[0]; + let exec = fn => src => { try { - show(bqn(a)); + fn(bqn(src)); } catch(e) { - console.error(''+fmtErr(Array.from(a),e)+''); + console.error(''+fmtErr(Array.from(src),e)+''); } - }); + } + if (arg0[0] !== '-' || (arg0==='-f'&&(arg0=(args=args.slice(1))[0],1))) { + sysvals.args = list(args.slice(1).map(str)); + let res = require('path').resolve; + let fread = require('fs').readFileSync; + let path = res(arg0,'..'); + let read = f => fread(f,'utf-8'); + sysvals.path = str(path); + sysvals.flines = (x,w) => + list(read(res(path,req1str("•FLines",x,w))).split('\n').map(str)); + exec(r=>r)(read(res(arg0))); + } else if (arg0 === '-e') { + args.slice(1).map(exec(show)); + } } } diff --git a/docs/running.html b/docs/running.html index f2e46100..a7b7c2e4 100644 --- a/docs/running.html +++ b/docs/running.html @@ -7,7 +7,7 @@

How to run BQN

There are currently two active BQN implementations: the self-hosted one in this repository, and the independent dzaima/BQN. Neither is entirely complete but they are quite capable for pure programming tasks (say, implementing a compiler). For scripting, only dzaima/BQN has the required I/O such as file functions. I tend to develop parts of applications in the online REPL and move to dzaima/BQN scripts in order to run them.

BQN

-

The online REPL is here. The file docs/bqn.js is zero-dependency Javascript, and can be loaded from HTML or Node.js. It can also be called directly from the command line (using Node); in this case each argument is evaluated as BQN code and the result is printed. This notebook shows how to run it in an Observable notebook.

+

The online REPL is here. The file docs/bqn.js is zero-dependency Javascript, and can be loaded from HTML or Node.js. It can also be called directly from the command line (using Node): pass a file and •args or -e to execute all remaining arguments directly and print the results. This notebook shows how to run it in an Observable notebook.

The version of BQN in this repository is implemented mainly in BQN itself—the compiler is entirely self-hosted, while the runtime is built from a small number of starting functions using preprocessed BQN. It completely supports the core language except for block headers and multiple body syntax, and a few cases of structural Under (⌾). The Javascript-based compiler is also slow, taking about 0.05 seconds plus 1 second per kilobyte of source (this is purely due to the slow runtime, as dzaima+reference achieves 1ms/kB with the same compiler once warmed up).

Because self-hosted BQN requires only a simple virtual machine to run, it is fairly easy to embed it in another programming language by implementing this virtual machine. The way data is represented is part of the VM implementation: it can use native arrays or a custom data structure, depending on what the language supports. An initial implementation will be very slow, but can be improved by replacing functions from the BQN-based runtime with native code. As the VM system can be hard to work with if you're not familiar with it, I advise you to contact me to discuss this option it you are interested.

In progress VMs are CBQN in C, and ebqn in Erlang. Although both of these work (can compile and run code; only missing some fill support in CBQN), neither is considered useful for any purpose yet. CBQN is likely to become the main high-performance BQN implementation but is currently only a few times faster than Javascript and has an interface that's only useful for testing. ebqn is extremely slow—hours to compile.

diff --git a/running.md b/running.md index 00fd48b4..43808dda 100644 --- a/running.md +++ b/running.md @@ -6,7 +6,7 @@ There are currently two active BQN implementations: the self-hosted one in this ### BQN -The online REPL is [here](https://mlochbaum.github.io/BQN/try.html). The file [docs/bqn.js](docs/bqn.js) is zero-dependency Javascript, and can be loaded from HTML or Node.js. It can also be called directly from the command line (using Node); in this case each argument is evaluated as BQN code and the result is printed. [This notebook](https://observablehq.com/@lsh/bqn) shows how to run it in an Observable notebook. +The online REPL is [here](https://mlochbaum.github.io/BQN/try.html). The file [docs/bqn.js](docs/bqn.js) is zero-dependency Javascript, and can be loaded from HTML or Node.js. It can also be called directly from the command line (using Node): pass a file and `•args` or `-e` to execute all remaining arguments directly and print the results. [This notebook](https://observablehq.com/@lsh/bqn) shows how to run it in an Observable notebook. The version of BQN in this repository is implemented mainly in BQN itself—the compiler is entirely self-hosted, while the runtime is built from a small number of starting functions using preprocessed BQN. It completely supports the core language except for block headers and multiple body syntax, and a few cases of structural Under (`⌾`). The Javascript-based compiler is also slow, taking about 0.05 seconds plus 1 second per kilobyte of source (this is purely due to the slow runtime, as dzaima+reference achieves 1ms/kB with the same compiler once warmed up). -- cgit v1.2.3