read-dependencies now correctly recorded (i think)

This commit is contained in:
Joeri Exelmans 2025-04-16 16:32:06 +02:00
parent 7a5b9d4f38
commit 614e6c0fdb

View file

@ -1,99 +1,130 @@
import { pretty } from "../util/pretty.js"; import { pretty } from "../util/pretty.js";
import { inspect } from "node:util"; import { deepEqual } from "../util/util.js";
// UUID -> Computation<a> -> Slot<a> // UUID -> Computation<a> -> Slot<a>
const newSlot = uuid => computation => ({ const newSlot = uuid => computation => ({
overwrites: uuid, overwrites: uuid,
computation, computation,
// depth: 1, // depth: 1,
// [inspect.custom]: (depth, options, inspect) => options.stylize(`newSlot(${inspect(uuid)})(${inspect(computation)})`, 'special'),
}); });
// a -> Computation<a> // a -> Computation<a>
const newValue = val => ({ const newValue = val => ({
kind: "value", kind: "value",
out: val, out: val,
// [inspect.custom]: (depth, options, inspect) => options.stylize(`newValue(${val})`, 'special'),
}); });
const id = x => x;
// Slot<a> -> Computation<a> // Slot<a> -> Computation<a>
const read = slot => ({ const read = slot => ({
kind: "transformation", kind: "read",
in: slot, slot,
fn: {
kind: "value",
out: id,
},
out: slot.computation.out, out: slot.computation.out,
// [inspect.custom]: (depth, options, inspect) => options.stylize(`read(${inspect(slot)})`, 'special'),
}); });
// Computation<a> -> Computation<a -> b> -> Computation<b> // Computation<a> -> Computation<a -> b> -> Computation<b>
const transform = input => fn => { const transform = input => fn => {
// console.log("transform...", "input:", pretty(input), "fn:", pretty(fn));
const output = fn.out(input.out); const output = fn.out(input.out);
if (input.kind === "value") { if (input.kind === "value") {
// our input had no read dependency, thus likewise our output does not: // optimization: sandwich everything together
return { return {
kind: "value", kind: "value",
out: output, out: output,
}; };
} }
else { else {
// console.log("transforming the transformation...");
return { return {
kind: "transformation", kind: "transformation",
in: input.in, in: input,
// transform the transformation: fn,
fn: transform(input.fn)(newValue(origFn => {
const descr = `${fn.out.name}${origFn.name}`;
return { [descr]: x => fn.out(origFn(x)) }[descr];
})),
out: output, out: output,
}; };
} }
}; };
const counterOne = newSlot(Symbol('counter'))(newValue(1)); 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 valueOne = read(counterOne); 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),
]);
}
}
console.log(pretty({valueOne}));
const inc = x => x + 1; const inc = x => x + 1;
const onePlusOne = transform(valueOne)(newValue(inc)); // 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}));
console.log(pretty({onePlusOne})); // verifyComputation(valueOne);
// verifyComputation(onePlusOne);
// verifyComputation(onePlusOnePlusOne);
const onePlusOnePlusOne = transform(onePlusOne)(newValue(inc));
console.log(pretty({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);
// const price = newSlot(Symbol('price'))(newValue(20.66)); console.log("getReadDependencies(totalPlusOne):", getReadDependencies(totalPlusOne));
// const tax = newSlot(Symbol('tax'))(newValue(4.34));
// console.log(pretty({price}));
// const total =
// transform(read(price))(
// transform(read(tax))(
// newValue(tax => price => price + tax)));
// console.log(pretty({total}))
// const totalPlusOne = transform(total)(newValue(x => x + 1));
// console.log(pretty({totalPlusOne}));
// const getReadDependencies = computation => new Set([
// ...(computation.kind === "value" ? [] : [computation.in, ...getReadDependencies(computation.fn)]),
// ]);
// console.log("getReadDependencies(total):", getReadDependencies(total));