aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2021-04-15 20:51:25 -0400
committerMarshall Lochbaum <mwlochbaum@gmail.com>2021-04-15 20:53:29 -0400
commit1ac78a69e09fb73cbcadc1dd16b94c78e75dc9c8 (patch)
tree9731be7f3e70125edf95c87930cbf4ec48c0c69a /docs
parentc358718f7585bfe615a2590a090d98002ab2a44e (diff)
File functions when running in Node.js
Diffstat (limited to 'docs')
-rwxr-xr-xdocs/bqn.js40
-rw-r--r--docs/running.html2
2 files changed, 27 insertions, 15 deletions
diff --git a/docs/bqn.js b/docs/bqn.js
index 4af176a6..741a7e68 100755
--- a/docs/bqn.js
+++ b/docs/bqn.js
@@ -91,6 +91,7 @@ let arr = (r,sh,fill) => {r.sh=sh;r.fill=fill;return r;}
let list = (l,fill) => arr(l,[l.length],fill);
let llst = l => list(l, l.length>0&&l.every(isnum)?0:undefined);
let str = s => list(Array.from(s), ' ');
+let unstr = s => s.join("");
let setrepr = (r,f) => {f.repr=r; return f;}
let ctrans = (c,t) => String.fromCodePoint(c.codePointAt(0)+t);
let plus = (x,w) => {
@@ -270,9 +271,9 @@ let compile = run(
);
runtime[42] = rtAssert;
let system = (x,w) => {
- let r = table(s=>sysvals[s.join("")])(x);
+ let r = table(s=>sysvals[unstr(s)])(x);
if (r.some(v=>!has(v))) {
- let m = x.filter((_,i)=>!has(r[i])).map(s=>"•"+s.join("")).join(" ");
+ let m = x.filter((_,i)=>!has(r[i])).map(s=>"•"+unstr(s)).join(" ");
throw Error("Unknown system values (see •listSys for available): "+m);
}
return table(v=>v.dynamic?v():v)(r);
@@ -288,7 +289,7 @@ let fmt1 = run(
,[runtime[0],runtime[1],runtime[2],runtime[6],runtime[7],runtime[9],runtime[11],runtime[12],runtime[13],runtime[14],runtime[15],runtime[16],runtime[18],runtime[19],runtime[20],runtime[21],runtime[22],runtime[23],runtime[24],runtime[25],runtime[26],runtime[27],runtime[29],runtime[30],runtime[32],runtime[35],runtime[36],runtime[43],runtime[44],runtime[45],runtime[46],runtime[47],runtime[49],runtime[50],runtime[51],runtime[52],runtime[53],runtime[54],runtime[55],runtime[56],runtime[58],runtime[59],runtime[61],0,-1,Infinity,1,2,5,4,127,32,3,10,'\0',' ','┐','↕','\"','␡','␀','·','*','0',str("@"),str("\'"),str("⟨⟩"),str("⟨"),str("⟩"),str("┌"),str("·─"),str("·╵╎┆┊"),str("┘"),str("┌┐"),str("└┘"),str(" "),str("‿"),str(""),str("array"),str("function"),str("1-modifier"),str("2-modifier"),str("00321111"),str("("),str(")"),str("{𝔽}")]
,[[0,1,0,0],[1,1,3,19],[0,0,399,3],[0,0,465,6],[0,0,565,3],[0,0,616,4],[0,0,655,3],[0,0,685,4],[0,0,808,3],[0,0,846,3],[0,0,885,3],[0,0,938,7],[0,0,1168,3],[0,0,1201,8],[0,0,1428,3],[0,0,1457,3],[0,0,1467,11],[0,0,1822,3],[0,0,1874,3]]
)(list([type, decompose, glyph, fmtnum]));
-let fmt = x => fmt1(x).join("");
+let fmt = x => unstr(fmt1(x));
let fmtErr = (s,e) => {
let r=e.src, w=e.message, loc=[];
@@ -316,7 +317,7 @@ 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("");
+ return unstr(x);
}
let dojs = (x,w) => {
let s = req1str("•JS",x,w);
@@ -330,12 +331,12 @@ let dojs = (x,w) => {
}
return toBQN(r);
}
+let dynsys = f => { f.dynamic=1; return f; }
let sysvals = {
bqn:(x,w)=> bqn(req1str("•BQN",x,w)), js:dojs,
type, glyph, decompose, fmt:fmt1, unixtime,
- listsys: () => list(Object.keys(sysvals).map(str).sort())
+ listsys: dynsys(() => list(Object.keys(sysvals).map(str).sort()))
};
-sysvals.listsys.dynamic = 1;
let make_timed = tfn => {
let timed = f => (x,w) => {
@@ -367,6 +368,22 @@ if (typeof module!=='undefined') { // Node.js
sysvals.show = (x,w) => { show(x); return x; };
sysvals.out = (x,w) => { console.log(req1str("•Out",x,w)); return x; };
+ let path = require('path');
+ let fs = require('fs');
+ let ff = (e,fr,fw,o) => dynsys(() => {
+ let p = sysvals.path;
+ let resolve = p ? (f=>path.resolve(unstr(p),f))
+ : (f => { if (!path.isAbsolute(f)) throw Error(e+": Paths must be absolute when not running from a file"); return f; });
+ return (x,w) => {
+ let f = resolve(req1str(e,has(w)?w:x));
+ if (has(w)) { fs.writeFileSync(f,fw(x),o); return str(f); }
+ else { return fr(fs.readFileSync(f,o)); }
+ }
+ });
+ sysvals.fchars = ff('•FChars',str,unstr,'utf-8');
+ sysvals.flines = ff('•FLines',s=>list(s.split('\n').map(str)),s=>s.map(unstr).join('\n'),'utf-8');
+ sysvals.fbytes = ff('•FBytes',s=>list(Array.from(s).map(c=>String.fromCodePoint(c))),s=>Buffer.from(s.map(c=>c.codePointAt(0))));
+
if (!module.parent) {
let args = process.argv.slice(2);
let arg0 = args[0];
@@ -378,15 +395,10 @@ if (typeof module!=='undefined') { // Node.js
}
}
if (arg0[0] !== '-' || (arg0==='-f'&&(arg0=(args=args.slice(1))[0],1))) {
+ sysvals.path = str(path.resolve(arg0,'..')+'/');
+ sysvals.name = str(path.basename(arg0));
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)));
+ exec(r=>r)(fs.readFileSync(arg0,'utf-8'));
} else if (arg0 === '-e') {
args.slice(1).map(exec(show));
}
diff --git a/docs/running.html b/docs/running.html
index a7b7c2e4..cd3eac79 100644
--- a/docs/running.html
+++ b/docs/running.html
@@ -5,7 +5,7 @@
</head>
<div class="nav"><a href="https://github.com/mlochbaum/BQN">BQN</a> / <a href="index.html">main</a></div>
<h1 id="how-to-run-bqn">How to run BQN</h1>
-<p>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.</p>
+<p>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). dzaima/BQN has good performance while self-hosted is about a thousand times slower. I tend to develop parts of applications in the online REPL and move to dzaima/BQN scripts in order to run them.</p>
<h3 id="bqn">BQN</h3>
<p>The online REPL is <a href="https://mlochbaum.github.io/BQN/try.html">here</a>. The file <a href="https://github.com/mlochbaum/BQN/blob/master/docs/bqn.js">docs/bqn.js</a> 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 <code><span class='Value'>•args</span></code> or <code><span class='Function'>-</span><span class='Value'>e</span></code> to execute all remaining arguments directly and print the results. <a href="https://observablehq.com/@lsh/bqn">This notebook</a> shows how to run it in an Observable notebook.</p>
<p>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 (<code><span class='Modifier2'>⌾</span></code>). 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).</p>