import { pretty } from "../util/pretty.js"; import { deepEqual } from "../util/util.js"; // UUID -> Computation -> Slot const newSlot = uuid => computation => ({ overwrites: uuid, computation, // depth: 1, }); // a -> Computation const newValue = val => ({ kind: "value", out: val, }); // Slot -> Computation const read = slot => ({ kind: "read", slot, out: slot.computation.out, }); // Computation -> Computation b> -> Computation const transform = input => fn => { const output = fn.out(input.out); if (input.kind === "value") { // optimization: sandwich everything together return { kind: "value", out: output, }; } else { return { kind: "transformation", in: input, fn, out: output, }; } }; const verifyComputation = (computation, indent=0) => { const printIndent = (...args) => { console.log(" ".repeat(indent*2), ...args); } const compare = (a,b, kind) => { if (typeof a === 'function' && typeof b === 'function') { printIndent("cannot compare functions", `(${kind})`); } else if (deepEqual(a, b)) { printIndent(`ok (${kind})`); } else { printIndent(`bad (${kind})`); } } if (computation.kind === "value") { compare(1, 1, "value"); } else if (computation.kind === "read") { compare(computation.out, computation.slot.computation.out, "read"); } else if (computation.kind === "transformation") { compare(computation.fn.out(computation.in.out), computation.out, "transformation"); verifyComputation(computation.in, indent+1); verifyComputation(computation.fn, indent+1); } } const getReadDependencies = computation => { if (computation.kind === "value") { return new Set(); } else if (computation.kind === "read") { return new Set([computation.slot]); } else if (computation.kind === "transformation") { return new Set([ ...getReadDependencies(computation.in), ...getReadDependencies(computation.fn), ]); } } const inc = x => x + 1; // const counterOne = newSlot(Symbol('counter'))(newValue(1)); // const valueOne = read(counterOne); // console.log(pretty({valueOne})); // const onePlusOne = transform(valueOne)(newValue(inc)); // console.log(pretty({onePlusOne})); // const onePlusOnePlusOne = transform(onePlusOne)(newValue(inc)); // console.log(pretty({onePlusOnePlusOne})); // verifyComputation(valueOne); // verifyComputation(onePlusOne); // verifyComputation(onePlusOnePlusOne); const priceSlot = newSlot(Symbol('price'))(newValue(20.66)); const taxSlot = newSlot(Symbol('tax'))(newValue(4.34)); console.log(pretty({price: priceSlot})); const computeTotal = tax => { const addTax = price => price + tax; return addTax; }; const total = transform(read(priceSlot))( transform(read(taxSlot))( newValue(computeTotal))); console.log(pretty({total})) const totalPlusOne = transform(total)(newValue(inc)); console.log(pretty({totalPlusOne})); verifyComputation(totalPlusOne); console.log("getReadDependencies(totalPlusOne):", getReadDependencies(totalPlusOne));