diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-08-26 22:07:07 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-08-26 22:07:07 -0400 |
| commit | b2ee8443356492ba5bb4ea1bbe6154c339296068 (patch) | |
| tree | 5ae25a7da1d254ca5ac0bba60629148f8f6d1ea8 | |
| parent | 84c2a286c5975b2f3dc5dee524391984d10fb697 (diff) | |
Add state object for variable system values
| -rwxr-xr-x | bqn.js | 47 | ||||
| -rw-r--r-- | docs/bqn.js | 70 |
2 files changed, 67 insertions, 50 deletions
@@ -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; } |
