functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
170 lines (169 loc) • 4.5 kB
JavaScript
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));