UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

170 lines (169 loc) 4.5 kB
import { find } from "../find/module.f.js"; import { fold, concat, next } from "../../list/module.f.js"; import { map } from "../../nullable/module.f.js"; const path = (tail) => (n) => { switch (n.length) { case 1: { return [n[0], { first: null, tail }]; } case 2: { return [n[0], { first: [n[1]], tail }]; } case 3: { return path({ first: [0, n], tail })(n[0]); } case 5: { return path({ first: [0, n], tail })(n[0]); } } }; const reduceValue0 = (a) => (n) => { const [, v1, n2] = n; if (a.length === 1) { switch (n2.length) { case 3: { return [[a[0], v1, ...n2]]; } case 5: { return [[a[0], v1, n2[0]], n2[1], [n2[2], n2[3], n2[4]]]; } default: { throw 'invalid node'; } } } else { return [a, v1, n2]; } }; const reduceValue2 = (a) => (n) => { const [n0, v1,] = n; if (a.length === 1) { switch (n0.length) { case 3: { return [[...n0, v1, a[0]]]; } case 5: { return [[n0[0], n0[1], n0[2]], n0[3], [n0[4], v1, a[0]]]; } default: { throw 'invalid node'; } } } else { return [n0, v1, a]; } }; const initValue0 = (a) => (n) => { const [, v1, n2] = n; if (a === null) { switch (n2.length) { case 1: { return [[v1, ...n2]]; } case 2: { return [[v1], n2[0], [n2[1]]]; } default: { throw 'invalid node'; } } } else { return [a, v1, n2]; } }; const initValue1 = (a) => (n) => { const [n0, v1] = n; if (a === null) { switch (n0.length) { case 1: { return [[...n0, v1]]; } case 2: { return [[n0[0]], n0[1], [v1]]; } default: { throw 'invalid node'; } } } else { return [n0, v1, a]; } }; const reduceX = (ms) => ([i, n]) => (a) => { const [m0, m2] = ms; const f = m => { const ra = m(a); return n.length === 3 ? ra(n) : [...ra([n[0], n[1], n[2]]), n[3], n[4]]; }; switch (i) { case 0: { return f(m0); } case 2: { return f(m2); } case 4: { return [n[0], n[1], ...m2(a)([n[2], n[3], n[4]])]; } } }; const reduce = fold(reduceX([reduceValue0, reduceValue2])); const initReduce = reduceX([initValue0, initValue1]); export const nodeRemove = (c) => (node) => { const f = () => { const { first, tail } = find(c)(node); const branch = n => f => { const [v, p] = path(null)(n); return { first: p.first, tail: concat(p.tail)({ first: f(v), tail }) }; }; const [i, n] = first; switch (i) { case 1: { switch (n.length) { case 1: { return { first: null, tail }; } case 2: { return { first: [n[1]], tail }; } case 3: { return branch(n[2])(v => [2, [n[0], v, n[2]]]); } case 5: { return branch(n[2])(v => [2, [n[0], v, n[2], n[3], n[4]]]); } } } case 3: { switch (n.length) { case 2: { return { first: [n[0]], tail }; } case 5: { return branch(n[4])(v => [4, [n[0], n[1], n[2], v, n[4]]]); } } } default: { return null; } } }; const r = f(); if (r === null) { return node; } const { first, tail } = r; const tailR = next(tail); if (tailR === null) { return first; } const { first: tf, tail: tt } = tailR; const result = reduce(initReduce(tf)(first))(tt); return result.length === 1 ? result[0] : result; }; export const remove = c => map(nodeRemove(c));