aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbqn.js47
-rw-r--r--docs/bqn.js70
2 files changed, 67 insertions, 50 deletions
diff --git a/bqn.js b/bqn.js
index d544a015..3ec00774 100755
--- a/bqn.js
+++ b/bqn.js
@@ -6,12 +6,13 @@ let fs = require('fs');
let bqn = require("./docs/bqn.js");
module.exports = bqn;
-let {fmt,fmtErr,sysvals}=bqn;
+let {fmt,fmtErr,sysvals,sysargs,bqns}=bqn;
let {has,list,str,unstr,dynsys,req1str,makens}=bqn.util;
let show = x => console.log(fmt(x));
sysvals.show = (x,w) => { show(x); return x; };
sysvals.out = (x,w) => { console.log(req1str("•Out",x,w)); return x; };
+sysvals.exit = (x,w) => process.exit(Number.isInteger(x)?x:0);
let dir = f=>f==='/'?f:f+'/'; // BQN uses trailing slash
let getres = p => {
@@ -20,7 +21,7 @@ let getres = p => {
else { res = (e,f) => { if (!path.isAbsolute(f)) throw Error(e+": Paths must be absolute when not running from a file"); return f; }; }
return e => (x,w) => res(e,req1str(e,x,w));
}
-let withres = (e,fn) => dynsys(() => fn(getres(sysvals.path)(e)));
+let withres = (e,fn) => dynsys(state => fn(state.resolve(e), state));
let ff = (fr,fw,o) => resolve => (x,w) => {
let f = resolve(has(w)?w:x);
if (has(w)) { fs.writeFileSync(f,fw(x),o); return str(f); }
@@ -33,8 +34,8 @@ sysvals.fchars = withres("•FChars",fchars);
sysvals.flines = withres("•FLines",flines);
sysvals.fbytes = withres("•FBytes",fbytes);
-sysvals.file = dynsys(() => {
- let p = sysvals.path;
+sysvals.file = dynsys(state => {
+ let p = state.path;
let res = getres(p);
let files = {
// Paths and parsing
@@ -106,19 +107,24 @@ sysvals.file = dynsys(() => {
return makens(Object.keys(files), Object.values(files));
});
-let set_state = w => {
- w = w||[]; sysvals.state=list(w);
- sysvals.path=w[0]&&str(getres(sysvals.path)("Setting •path")(w[0]));
- sysvals.name=w[1]; sysvals.args=w[2];
+sysargs.resolve=getres();
+let update_state = (st,w) => {
+ w=w||[];
+ st.path=w[0]&&str(st.resolve("Setting •path")(w[0]));
+ st.resolve=getres(st.path);
+ st.state=list(w); st.name=w[1]; st.args=w[2];
}
-let bqn_state = (x,w) => { set_state(w); return bqn(x); }
-bqn.setreqexec((s,x,w) => { set_state(w); return req1str(s,x); });
-sysvals.exit = (x,w) => process.exit(Number.isInteger(x)?x:0);
-let bqn_file = (f,t,w) => bqn_state(
- t, [ str(dir(path.dirname(f))), str(path.basename(f)), w ]
+let new_state = (st,w) => { st={...st}; update_state(st,w); return st; }
+sysvals.path=dynsys(s=>s.path);
+sysvals.name=dynsys(s=>s.name);
+sysvals.args=dynsys(s=>s.args);
+let bqn_state = (st,x,w) => bqns(new_state(st,w))(x);
+bqn.setexec(update_state);
+let bqn_file = (st,f,t,w) => bqn_state(
+ st, t, [ str(dir(path.dirname(f))), str(path.basename(f)), w ]
);
let imports = {};
-sysvals.import = withres("•Import", resolve => (x,w) => {
+sysvals.import = withres("•Import", (resolve,state) => (x,w) => {
let f = resolve(x);
let save = r=>r;
if (!has(w)) {
@@ -126,7 +132,7 @@ sysvals.import = withres("•Import", resolve => (x,w) => {
save = r => (imports[f]=r);
w=list([]);
}
- return save(bqn_file(f, fs.readFileSync(f,'utf-8'), w));
+ return save(bqn_file(state, f, fs.readFileSync(f,'utf-8'), w));
});
if (!module.parent) {
@@ -134,7 +140,8 @@ if (!module.parent) {
let arg0 = args[0];
let cl_state = () => {
let s = str("");
- return [str(dir(path.resolve('.'))), s, list([],s)];
+ let w = [str(dir(path.resolve('.'))), s, list([],s)];
+ return new_state(sysargs, w);
}
let exec = fn => src => {
try {
@@ -144,7 +151,7 @@ if (!module.parent) {
}
}
if (!has(arg0) || arg0==='-r') {
- set_state(cl_state());
+ let st = cl_state();
let stdin = process.stdin, repl = sysvals.makerepl();
let e = exec(s=>show(repl(str(s))));
stdin.on('end', () => { process.exit(); });
@@ -155,9 +162,9 @@ if (!module.parent) {
});
} else if (arg0[0] !== '-' || (arg0==='-f'&&(arg0=(args=args.slice(1))[0],1))) {
let f=arg0, a=list(args.slice(1).map(str));
- exec(s=>bqn_file(path.resolve(f),s,a))(fs.readFileSync(f,'utf-8'));
+ exec(s=>bqn_file(sysargs, path.resolve(f),s,a))(fs.readFileSync(f,'utf-8'));
} else if (arg0 === '-e') {
- let st=cl_state();
- args.slice(1).map(exec(s=>show(bqn_state(s,st))));
+ let ev=bqns(cl_state());
+ args.slice(1).map(exec(s=>show(ev(s))));
}
}
diff --git a/docs/bqn.js b/docs/bqn.js
index cc9feaed..4684f939 100644
--- a/docs/bqn.js
+++ b/docs/bqn.js
@@ -407,24 +407,32 @@ let compgen_raw = run(
,[[0,1,0],[0,0,1],[1,0,2],[1,1,3],[0,0,[[],[4]]],[0,0,[[],[5]]],[0,0,[[],[6]]],[0,0,[[],[7]]],[0,0,[[],[8]]],[0,0,[[],[9]]],[0,0,10],[0,0,11],[0,0,12],[0,0,13],[0,0,[[],[14]]],[0,0,[[],[15]]],[2,1,16],[0,0,17],[2,1,18],[0,0,19],[1,0,20],[0,0,21],[0,0,[[],[22]]],[0,0,23],[0,0,24],[0,0,25],[2,1,26]]
,[[0,0],[3,43],[573,5],[592,5],[716,57],[2922,23],[3747,188],[11352,19],[11598,3],[11606,3],[11646,3],[11665,3],[11706,3],[11725,3],[11744,3],[11772,3],[11808,3],[11844,6],[11981,3],[12053,3],[12103,5],[12129,3],[12151,3],[12209,3],[12262,3],[12324,3],[12349,3]]
);
-let compgen = gl => {
- let comp = compgen_raw(list(gl.map(str)));
- return (src, rt) => {
- let s=str(src), c;
- try { c=comp(s,rt); } catch(e) { if (typeof e.message!=="string") e.message.src=s; throw e; }
- c.push(s); return c;
+let compgen = sys => {
+ let gl = sys.glyphs, rt = sys.runtime;
+ let comp = compgen_raw(list(gl));
+ return sysargs.comps = sysargs => {
+ let system = (x,w) => {
+ let r = table(s=>sysvals[unstr(s)])(x);
+ if (r.some(v=>!has(v))) {
+ 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(sysargs):v)(r);
+ }
+ let rts = list([rt, system].concat(sysargs.addrt||[]));
+ return src => {
+ let s=str(src), c;
+ try { c=comp(s,rts); } catch(e) { if (typeof e.message!=="string") e.message.src=s; throw e; }
+ c.push(s); return c;
+ }
}
}
-let compile = compgen(glyphs);
+let sysargs = {runtime, glyphs:glyphs.map(str)};
+let compile = compgen(sysargs)(sysargs);
+let andrun = c => src => run(...c(src));
+let bqn = andrun(compile);
+let bqns = st => andrun(st.comps(st));
runtime[42] = rtAssert;
-let system = sysargs => (x,w) => {
- let r = table(s=>sysvals[unstr(s)])(x);
- if (r.some(v=>!has(v))) {
- 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(sysargs):v)(r);
-}
// Formatter
let fmtnum = x => str(x==Infinity ? "∞" : x==-Infinity ? "¯∞"
@@ -482,7 +490,14 @@ let dojs = (x,w) => {
return toBQN(r);
}
-let reqexec = req1str; // Modified by Node version to handle •state
+let update_state = (st,w)=>w; // Modified by Node version to handle •state
+let makebqn = (e,fn) => st_old => {
+ let st={...st_old}; st.addrt=[];
+ return (x,w) => {
+ let src = req1str(e,x,update_state(st,w));
+ return fn(st.comps(st)(src));
+ }
+}
let rebqn = dynsys(state => (x,w) => {
let req = (r,s) => { if (!r) throw Error("•ReBQN: "+s) };
req(!has(w), "𝕨 not allowed");
@@ -503,21 +518,19 @@ let rebqn = dynsys(state => (x,w) => {
pr[k].push(gl); rt[k].push(val);
});
state = {...state};
- state.compile = compgen(state.glyphs = pr);
+ state.glyphs = pr.map(str);
state.runtime = list([].concat(...rt));
+ compgen(state);
}
- let comp = state.compile;
- let rts = list([state.runtime, system(state)]);
- let cmp = (x,w) => comp(reqexec("•ReBQN evaluation",x,w), rts);
- let ex = c => run.apply(null, c);
+ let cmp = makebqn("•ReBQN evaluation", r=>r)(state);
if (!has(repl) || (repl=unstr(repl))==="none") {
- return (x,w) => ex(cmp(x,w));
+ return (x,w) => run(...cmp(x,w));
} else {
let rd = repl==="strict" ? 0 : -1;
req(rd==0||repl==="loose", "invalid value for 𝕩.repl")
let vars = [], names = [], redef = [];
- rts = list(rts.concat([names,redef]));
+ state.addrt = [names,redef];
return (x,w) => {
names.sh=redef.sh=[names.length];
let c = cmp(x,w);
@@ -527,7 +540,7 @@ let rebqn = dynsys(state => (x,w) => {
redef.push(...newv.map(i=>rd));
vars .push(...newv.map(i=>null));
c.push(vars);
- return ex(c);
+ return run(...c);
}
}
});
@@ -537,7 +550,7 @@ let primitives = dynsys(state => {
});
let sysvals = {
- bqn:(x,w)=> bqn(reqexec("•BQN",x,w)), rebqn, primitives, js:dojs,
+ bqn:dynsys(makebqn("•BQN",r=>run(...r))), rebqn, primitives, js:dojs,
type, glyph, decompose, fmt:fmt1, repr, unixtime, listkeys,
listsys: dynsys(_ => list(Object.keys(sysvals).sort().map(str))),
math: obj2ns(Math,("LN10 LN2 LOG10E LOG2E cbrt expm1 hypot log10 log1p log2 round trunc atan2 cos cosh sin sinh tan tanh").split(" "), f=>typeof f==="function"?runtime[60](f,0):f)
@@ -565,13 +578,10 @@ if (typeof process!=='undefined') {
});
}
-let sysargs = {compile,runtime,glyphs:glyphs.map(str)};
-let rt_sys = list([runtime, system(sysargs)]);
-let bqn = src => run.apply(null,compile(str(src),rt_sys));
-
if (typeof module!=='undefined') { // Node.js
bqn.fmt=fmt; bqn.fmtErr=fmtErr; bqn.compile=compile; bqn.run=run;
+ bqn.sysargs=sysargs; bqn.bqns=bqns;
bqn.sysvals=sysvals; bqn.util={has,list,str,unstr,dynsys,req1str,makens};
- bqn.setreqexec = re => { reqexec=re; }
+ bqn.setexec = f => { update_state=f; }
module.exports=bqn;
}