UNPKG

@thi.ng/pointfree

Version:

Pointfree functional composition / Forth style stack execution engine

50 lines (49 loc) 1.51 kB
import { isArray } from "@thi.ng/checks/is-array"; import { isFunction } from "@thi.ng/checks/is-function"; import { compL } from "@thi.ng/compose/comp"; import { $ } from "./safe.js"; import { tos } from "./stack.js"; const $stackFn = (f) => isArray(f) ? defWord(f) : f; const __compile = (prog) => prog.length > 0 ? compL.apply( null, prog.map( (w) => !isFunction(w) ? (ctx) => (ctx[0].push(w), ctx) : w ) ) : (ctx) => ctx; const unwrap = ([stack], n = 1) => n === 1 ? tos(stack) : stack.slice(Math.max(0, stack.length - n)); const defWord = (prog, env, mergeEnv = true) => { const w = __compile(prog); return env ? mergeEnv ? (ctx) => (w([ctx[0], ctx[1], { ...ctx[2], ...env }]), ctx) : (ctx) => (w([ctx[0], ctx[1], { ...env }]), ctx) : w; }; const defWordU = (prog, n = 1, env, mergeEnv = true) => { const w = __compile(prog); return env ? mergeEnv ? (ctx) => unwrap(w([ctx[0], ctx[1], { ...ctx[2], ...env }]), n) : (ctx) => unwrap(w([ctx[0], ctx[1], { ...env }]), n) : (ctx) => unwrap(w(ctx), n); }; const exec = (ctx) => ($(ctx[0], 1), $stackFn(ctx[0].pop())(ctx)); const $try = (ctx) => { const stack = ctx[0]; $(stack, 2); const err = stack.pop(); try { return exec(ctx); } catch (e) { stack.push(e, err); return exec(ctx); } }; const execjs = (ctx) => { const stack = ctx[0]; $(stack, 1); const [fn, ...args] = stack.pop(); stack.push(fn(...args)); return ctx; }; export { $stackFn, $try, defWord, defWordU, exec, execjs, unwrap };