import { add, emptySet, forEach } from "../structures/set.js"; import { deepEqual } from "../util/util.js"; import {inspect} from "node:util"; import { compareSlots } from "../compare/versioning.js"; // UUID -> Value -> Slot export const newSlot = uuid => value => ({ overwrites: uuid, value, depth: 1, [inspect.custom]: (depth, options, inspect) => `newSlot(${inspect(uuid)}, ${inspect(value)})`, }); // Slot -> Value -> Slot 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 -> Slot -> MergeResult 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 -> MergeResult -> MergeResult 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; };