branching and very basic merging of slots

This commit is contained in:
Joeri Exelmans 2025-04-17 09:19:41 +02:00
parent 614e6c0fdb
commit 3978f7f835
32 changed files with 684 additions and 420 deletions

96
versioning/slot.js Normal file
View file

@ -0,0 +1,96 @@
import { add, emptySet, forEach } from "../structures/set.js";
import { deepEqual } from "../util/util.js";
import {inspect} from "node:util";
// UUID -> Value<a> -> Slot<a>
export const newSlot = uuid => value => ({
overwrites: uuid,
value,
depth: 1,
[inspect.custom]: (depth, options, inspect) => `newSlot(${inspect(uuid)}, ${inspect(value)})`,
});
export const compareSlots = compareElems => slotA => slotB => {
if (slotA.depth < slotB.depth) {
return -1;
}
if (slotB.depth < slotA.depth) {
return 1;
}
return compareValues(compareElems)(slotA.value)(slotB.value);
};
export const compareValues = compareElems => valA => valB => {
if (valA.kind < valB.kind) {
return -1;
}
if (valB.kind < valA.kind) {
return 1;
}
if (valA.kind === "literal") {
return compareElems(valA.out)(valB.out);
}
if (valA.kind === "read") {
return compareSlots(compareElems)(valA.slot)(valB.slot);
}
if (valA.kind === "transformation") {
const cmpIn = compareValues(compareElems)(valA.in)(valB.in);
if (cmpIn !== 0) {
return cmpIn;
}
return compareValues(compareElems)(valA.fn)(valB.fn);
}
};
// Slot<a> -> Value<a> -> Slot<a>
export const overwrite = slot => value => ({
overwrites: slot,
value,
depth: slot.depth + 1,
// [inspect.custom]: (depth, options, inspect) => `overwrite(${inspect(slot)}, ${inspect(value)})`,
});
const findLCA = slotA => slotB => {
if (deepEqual(slotA, slotB)) {
return slotA;
}
if (slotA.depth > slotB.depth) {
return findLCA(slotA.overwrites)(slotB)
}
else {
return findLCA(slotB.overwrites)(slotA)
}
};
// Slot<a> -> Slot<a> -> MergeResult<a>
export const merge = compareElems => slotA => slotB => {
const lca = findLCA(slotA)(slotB);
if (lca === undefined) {
throw new Error("Could not find LCA");
}
if (deepEqual(lca, slotA)) {
return add(emptySet(compareSlots(compareElems)))(slotB);
// return new Set([slotB]); // B is successor of A -> fast-forward
}
if (deepEqual(lca, slotB)) {
return add(emptySet(compareSlots(compareElems)))(slotA);
// return new Set([slotA]); // A is successor of B -> fast-forward
}
return add(add(emptySet(compareSlots(compareElems)))(slotA))(slotB);
// return new Set([slotA, slotB]);
};
// MergeResult<a> -> MergeResult<a> -> MergeResult<a>
export const merge2 = compareElems => mA => mB => {
let result = emptySet(compareSlots(compareElems));
forEach(mA)(slotOfA => {
forEach(mB)(slotOfB => {
const merged = merge(compareElems)(slotOfA)(slotOfB);
forEach(merged)(merged => {
result = add(result)(merged);
});
});
});
return result;
};