Explorar o código

Simplify single_model.tsx

Joeri Exelmans %!s(int64=2) %!d(string=hai) anos
pai
achega
25a6bea890

+ 5 - 5
src/frontend/demos/demo_bm.tsx

@@ -152,7 +152,7 @@ export function getDemoBM() {
                     }
                 },
             }));
-            const onionCorr = corr.useCorrespondence(onionCs.reducer, onionAs.reducer);
+            const onionCorr = corr.useCorrespondence(onionCs, onionAs);
             return {onionCs, onionCorr, autoParse, setAutoParse, autoRender, setAutoRender};
         });
 
@@ -188,22 +188,22 @@ export function getDemoBM() {
 
                 <Grid.Col span={1}>
                     <Group position="right">
-                        {onions[0].onionCorr.components.getCaptionWithParseButton(onions[0].autoParse, onions[0].setAutoParse, css[0].cs.getCurrentVersion())}
+                        {onions[0].onionCorr.components.getCaptionWithParseButton(onions[0].autoParse, onions[0].setAutoParse)}
                     </Group>
                 </Grid.Col>
                 <Grid.Col span={1}>
                 </Grid.Col>
                 <Grid.Col span={1}>
                     <Group position="apart">
-                        {onions[0].onionCorr.components.getCaptionWithRenderButton(onions[0].autoRender, onions[0].setAutoRender, as.getCurrentVersion(), setManualRendererState)}
-                        {onions[1].onionCorr.components.getCaptionWithRenderButton(onions[1].autoRender, onions[1].setAutoRender, as.getCurrentVersion(), setManualRendererState, "right")}
+                        {onions[0].onionCorr.components.getCaptionWithRenderButton(onions[0].autoRender, onions[0].setAutoRender, setManualRendererState)}
+                        {onions[1].onionCorr.components.getCaptionWithRenderButton(onions[1].autoRender, onions[1].setAutoRender, setManualRendererState, "right")}
                     </Group>
                 </Grid.Col>
                 <Grid.Col span={1}>
                 </Grid.Col>
                 <Grid.Col span={1}>
                     <Group position="left">
-                        {onions[1].onionCorr.components.getCaptionWithParseButton(onions[1].autoParse, onions[1].setAutoParse, css[1].cs.getCurrentVersion(), "left")}
+                        {onions[1].onionCorr.components.getCaptionWithParseButton(onions[1].autoParse, onions[1].setAutoParse, "left")}
                     </Group>
                 </Grid.Col>
 

+ 3 - 3
src/frontend/demos/demo_corr.tsx

@@ -142,7 +142,7 @@ export function getDemoCorr() {
             },
         }));
 
-        const onionCorr = corr.useCorrespondence(onionCs.reducer, onionAs.reducer);
+        const onionCorr = corr.useCorrespondence(onionCs, onionAs);
 
         const [autoParse, setAutoParse] = React.useState<boolean>(true);
         const [autoRender, setAutoRender] = React.useState<boolean>(false);
@@ -161,7 +161,7 @@ export function getDemoCorr() {
                     <Group position="apart">
                         <Title order={4}>Concrete Syntax</Title>
                         {onionCorr.components.getCaptionWithParseButton(
-                            autoParse, setAutoParse, cs.getCurrentVersion())}
+                            autoParse, setAutoParse)}
                     </Group>
                     <Space h="sm"/>
                     <Stack>
@@ -198,7 +198,7 @@ export function getDemoCorr() {
                 <div>
                     <Group position="apart">
                         {onionCorr.components.getCaptionWithRenderButton(
-                            autoRender, setAutoRender, as.getCurrentVersion(), setManualRendererState)}
+                            autoRender, setAutoRender, setManualRendererState)}
                         <Title order={4}>Abstract Syntax</Title>
                     </Group>
                     <Space h="sm"/>

+ 1 - 1
src/frontend/demos/demo_le.tsx

@@ -51,7 +51,7 @@ export function getDemoLE() {
                 listNodeCreation,
                 primitiveRegistry.newEdgeCreation(listNodeCreation, "next", listNodeCreation),
                 primitiveRegistry.newEdgeCreation(listNodeCreation, "prev", listNodeCreation),
-            ], "createList", onion.initialState.version);
+            ], "createList", versionRegistry.initialVersion);
         }, []);
 
         const listNode = onion.graphState.nodes.get(listNodeId.value) as INodeState;

+ 1 - 1
src/frontend/demos/demo_live.tsx

@@ -80,7 +80,7 @@ export function getDemoLive() {
         const newVersion = reducer.createAndGotoNewVersion([
             modelCreation,
             primitiveRegistry.newEdgeCreation(modelCreation, "type", "DesignModel"),
-          ], "createDesignModel", onion.initialState.version,
+          ], "createDesignModel", versionRegistry.initialVersion,
           newDesignVersion => new Map([
             ["design", {version: newDesignVersion, overridings: new Map()}],
           ]));

+ 11 - 8
src/frontend/versioned_model/correspondence.tsx

@@ -38,13 +38,16 @@ export function newCorrespondence({primitiveRegistry, generateUUID, versionRegis
   const corrVersions = new Set<Version>([versionRegistry.initialVersion]);
   const isPartOfThisCorrespondence = v => corrVersions.has(v);
 
-  function useCorrespondence(csReducer, asReducer) {
+  function useCorrespondence(
+    {state: {version: csVersion}, reducer: csReducer},
+    {state: {version: asVersion}, reducer: asReducer},
+  ) {
     // "override" gotoVersion from corr-onion.
     const gotoVersion = (version: Version) => {
       const csVersion = version.embeddings.get("cs")?.version;
       const asVersion = version.embeddings.get("as")?.version;
 
-      if (version === onion.versionRegistry.initialVersion) {
+      if (version === versionRegistry.initialVersion) {
         reducer.gotoVersion(version);
         csReducer.gotoVersion(version);
         asReducer.gotoVersion(version);        
@@ -246,7 +249,7 @@ export function newCorrespondence({primitiveRegistry, generateUUID, versionRegis
 
     // React components
 
-    const getParseButton = (csVersion, dir: "left"|"right" = "right") => {
+    const getParseButton = (dir: "left"|"right" = "right") => {
       return <Mantine.Button compact
           disabled={(csVersion.reverseEmbeddings.get("cs") || []).some(v => corrVersions.has(v))}
           onClick={() => parseExistingVersion(csVersion)}
@@ -254,7 +257,7 @@ export function newCorrespondence({primitiveRegistry, generateUUID, versionRegis
           leftIcon={dir === "left" ? <Icons.IconChevronsLeft/>: null}
         >Parse</Mantine.Button>;
     };
-    const getRenderButton = (asVersion, setManualRendererState, dir: "left"|"right" = "left") => {
+    const getRenderButton = (setManualRendererState, dir: "left"|"right" = "left") => {
       return <Mantine.Button compact
           disabled={(asVersion.reverseEmbeddings.get("as") || []).some(v => corrVersions.has(v))}
           onClick={() => renderExistingVersion(asVersion, setManualRendererState)}
@@ -262,13 +265,13 @@ export function newCorrespondence({primitiveRegistry, generateUUID, versionRegis
           leftIcon={dir === "left" ? <Icons.IconChevronsLeft/>: null}
         >Render</Mantine.Button>;
     };
-    const getCaptionWithParseButton = (autoParseState, setAutoParseState, csVersion, dir: "left"|"right" = "right") => {
+    const getCaptionWithParseButton = (autoParseState, setAutoParseState, dir: "left"|"right" = "right") => {
       const sw = <Mantine.Switch label="Auto"
         labelPosition={dir}
         checked={autoParseState}
         onChange={(event) => setAutoParseState(event.currentTarget.checked)}
       />;
-      const button = getParseButton(csVersion, dir);
+      const button = getParseButton(dir);
       if (dir === "left") {
         return <Mantine.Group>{button}{sw}</Mantine.Group>;
       }
@@ -276,13 +279,13 @@ export function newCorrespondence({primitiveRegistry, generateUUID, versionRegis
         return <Mantine.Group>{sw}{button}</Mantine.Group>;
       }
     };
-    const getCaptionWithRenderButton = (autoRenderState, setAutoRenderState, asVersion, setManualRendererState, dir: "left"|"right" = "left") => {
+    const getCaptionWithRenderButton = (autoRenderState, setAutoRenderState, setManualRendererState, dir: "left"|"right" = "left") => {
       const sw = <Mantine.Switch label="Auto"
         labelPosition={dir}
         checked={autoRenderState}
         onChange={(event) => setAutoRenderState(event.currentTarget.checked)}
       />
-      const button = getRenderButton(asVersion, setManualRendererState, dir);
+      const button = getRenderButton(setManualRendererState, dir);
       if (dir === "left") {
         return <Mantine.Group>{button}{sw}</Mantine.Group>;
       }

+ 62 - 78
src/frontend/versioned_model/single_model.tsx

@@ -66,14 +66,6 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
   let x = 0;
   let y = 0;
 
-  const initialState: VersionedModelState = {
-    version: versionRegistry.initialVersion,
-    graph: emptyGraph,
-    historyGraph: initialHistoryGraph(versionRegistry.initialVersion),
-    deltaGraphL1: emptyGraph,
-    deltaGraphL0: emptyGraph,
-  }
-
   // The "current version" is both part of the React state (for rendering undo/redo buttons) and a local variable here, such that we can get the current version (synchronously), even outside of a setState-callback.
   let currentVersion = versionRegistry.initialVersion;
   function getCurrentVersion() {
@@ -81,7 +73,11 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
   }
 
   function useOnion(overridenCallbacks: (any) => VersionedModelCallbacks) {
-    const [state, setState] = React.useState<VersionedModelState>(initialState);
+    const [version, setVersion] = React.useState<Version>(versionRegistry.initialVersion);
+    const [graph, setGraph] = React.useState<D3OnionGraphData>(emptyGraph);
+    const [historyGraph, setHistoryGraph] = React.useState<HistoryGraphState>(initialHistoryGraph(versionRegistry.initialVersion));
+    const [deltaGraphL1, setDeltaGraphL1] = React.useState<DeltaGraphState>(emptyGraph);
+    const [deltaGraphL0, setDeltaGraphL0] = React.useState<DeltaGraphState>(emptyGraph);
 
     // Reducer
 
@@ -100,19 +96,9 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
 
         const newVersion = versionRegistry.createVersion(parentVersion, composite, embeddings);
 
-        setState(({historyGraph, deltaGraphL1, deltaGraphL0, ...rest}) => {
-          return {
-            // add new version to history graph:
-            historyGraph: historyGraphReducer(historyGraph, {type: 'addVersion', version: newVersion}),
-            // add the composite delta to the L1-graph + highlight it as 'active':
-            deltaGraphL1: composite.deltas.length > 0 ? deltaGraphReducer(deltaGraphL1, {type: 'addDelta', delta: composite, active: false}) : deltaGraphL1, // never add an empty composite
-            // add the primitive L0-deltas to the L0-graph + highlight them as 'active':
-            deltaGraphL0: composite.deltas.reduce(
-              (graph, delta) => deltaGraphReducer(graph, {type: 'addDelta', delta, active: false}),
-              deltaGraphL0),
-            ...rest,
-          };
-        });
+        setHistoryGraph(historyGraph => historyGraphReducer(historyGraph, {type: 'addVersion', version: newVersion}));
+        setDeltaGraphL1(deltaGraphL1 => composite.deltas.length > 0 ? deltaGraphReducer(deltaGraphL1, {type: 'addDelta', delta: composite, active: false}) : deltaGraphL1);
+        setDeltaGraphL0(deltaGraphL0 => composite.deltas.reduce((graph, delta) => deltaGraphReducer(graph, {type: 'addDelta', delta, active: false}), deltaGraphL0));
 
         return newVersion;
       }
@@ -124,7 +110,7 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
     };
     // Idempotent
     const appendVersions = (versions: Version[]) => {
-      setState(({historyGraph, ...rest}) => {
+      setHistoryGraph(historyGraph => {
         const versionsToAdd: Version[] = [];
         const addIfDontHaveYet = version => {
           if (!(historyGraph.nodes.some(n => n.obj === version) || versionsToAdd.includes(version))) {
@@ -145,57 +131,57 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
         for (const v of versions) {
           collectVersions(v);
         }
-        return {
-          historyGraph: versionsToAdd.reduceRight((historyGraph, version) => historyGraphReducer(historyGraph, {type: 'addVersion', version}), historyGraph),
-          ...rest,
-        };
-      });
+        return versionsToAdd.reduceRight((historyGraph, version) => historyGraphReducer(historyGraph, {type: 'addVersion', version}), historyGraph);
+      })
     }
-
-    // helper
-    const setGraph = callback =>
-      setState(({graph, ...rest}) => ({graph: callback(graph), ...rest}));
+    // // Idempotent
+    // const appendDelta = (delta: CompositeDelta) => {
+    //   setState(({deltaGraphL0, deltaGraphL1, ...rest}) => {
+    //     return {
+    //         deltaGraphL1: deltaGraphReducer(deltaGraphL1, {type: 'addDelta', delta, active: false}),
+    //         deltaGraphL0: delta.reduce(
+    //           (graph, delta) => deltaGraphReducer(deltaGraphL0, {type: 'addDelta', delta, active: false}),
+    //           deltaGraphL0),
+    //       ...rest,
+    //     };
+    //   });
+    // }
 
     const undoWithoutUpdatingHistoryGraph = (deltaToUndo) => {
       const d3Updater = new D3GraphUpdater(setGraph, x, y);
       graphState.unexec(deltaToUndo, d3Updater);
-      setState(({deltaGraphL0: prevDeltaGraphL0, deltaGraphL1: prevDeltaGraphL1, ...rest}) => ({
-        deltaGraphL1: deltaGraphReducer(prevDeltaGraphL1, {type: 'setDeltaInactive', delta: deltaToUndo}),
-        deltaGraphL0: deltaToUndo.deltas.reduce((prevDeltaGraphL0, delta) => deltaGraphReducer(prevDeltaGraphL0, {type: 'setDeltaInactive', delta}),prevDeltaGraphL0),
-        ...rest,
-      }));
+
+      setDeltaGraphL0(deltaGraphL0 => deltaToUndo.deltas.reduce((deltaGraphL0, delta) => deltaGraphReducer(deltaGraphL0, {type: 'setDeltaInactive', delta}), deltaGraphL0));
+      setDeltaGraphL1(deltaGraphL1 => deltaGraphReducer(deltaGraphL1, {type: 'setDeltaInactive', delta: deltaToUndo}));
     };
     const redoWithoutUpdatingHistoryGraph = (deltaToRedo) => {
       const d3Updater = new D3GraphUpdater(setGraph, x, y);
       graphState.exec(deltaToRedo, d3Updater);
-      setState(({deltaGraphL0: prevDeltaGraphL0, deltaGraphL1: prevDeltaGraphL1, ...rest}) => ({
-        deltaGraphL1: deltaGraphReducer(prevDeltaGraphL1, {type: 'setDeltaActive', delta: deltaToRedo}),
-        deltaGraphL0: deltaToRedo.deltas.reduce((prevDeltaGraphL0, delta) => deltaGraphReducer(prevDeltaGraphL0, {type: 'setDeltaActive', delta}),
-          prevDeltaGraphL0),
-        ...rest,
-      }));
+
+      setDeltaGraphL0(deltaGraphL0 => deltaToRedo.deltas.reduce((deltaGraphL0, delta) => deltaGraphReducer(deltaGraphL0, {type: 'setDeltaActive', delta}), deltaGraphL0));
+      setDeltaGraphL1(deltaGraphL1 => deltaGraphReducer(deltaGraphL1, {type: 'setDeltaActive', delta: deltaToRedo}));
     };
     const undo = (parentVersion, deltaToUndo) => {
       undoWithoutUpdatingHistoryGraph(deltaToUndo);
       currentVersion = parentVersion;
-      setState(({historyGraph: prevHistoryGraph, version: prevVersion, ...rest}) => ({
-        version: parentVersion,
-        historyGraph: historyGraphReducer(historyGraphReducer(prevHistoryGraph,
-            {type: 'highlightVersion', version: prevVersion, bold: false}),
-            {type: 'highlightVersion', version: parentVersion, bold: true}),
-        ...rest,
-      }));
+
+      setVersion(prevVersion => {
+        setHistoryGraph(historyGraph => historyGraphReducer(historyGraphReducer(historyGraph,
+              {type: 'highlightVersion', version: prevVersion, bold: false}),
+              {type: 'highlightVersion', version: parentVersion, bold: true}));
+        return parentVersion;
+      });
     };
     const redo = (childVersion, deltaToRedo) => {
       redoWithoutUpdatingHistoryGraph(deltaToRedo);
       currentVersion = childVersion;
-      setState(({historyGraph: prevHistoryGraph, version: prevVersion, ...rest}) => ({
-        version: childVersion,
-        historyGraph: historyGraphReducer(historyGraphReducer(prevHistoryGraph,
-          {type: 'highlightVersion', version: prevVersion, bold: false}),
-          {type: 'highlightVersion', version: childVersion, bold: true}),
-        ...rest,
-      }));
+
+      setVersion(prevVersion => {
+        setHistoryGraph(historyGraph => historyGraphReducer(historyGraphReducer(historyGraph,
+            {type: 'highlightVersion', version: prevVersion, bold: false}),
+            {type: 'highlightVersion', version: childVersion, bold: true}));
+        return childVersion;
+      });
     };
     const gotoVersion = (chosenVersion: Version) => {
       const path = currentVersion.findPathTo(chosenVersion);
@@ -211,13 +197,12 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
         }
       }
       currentVersion = chosenVersion;
-      setState(({historyGraph, version: oldVersion, ...rest}) => ({
-        version: chosenVersion,
-        historyGraph: historyGraphReducer(historyGraphReducer(historyGraph,
-          {type: 'highlightVersion', version: oldVersion, bold: false}),
-          {type: 'highlightVersion', version: chosenVersion, bold: true}),
-        ...rest,
-      }));
+      setVersion(prevVersion => {
+        setHistoryGraph(historyGraph => historyGraphReducer(historyGraphReducer(historyGraph,
+            {type: 'highlightVersion', version: prevVersion, bold: false}),
+            {type: 'highlightVersion', version: chosenVersion, bold: true}));
+        return chosenVersion;
+      });
     };
 
     const reducer = {
@@ -242,10 +227,10 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
     const callbacks = Object.assign({}, defaultCallbacks, overridenCallbacks(reducer));
 
     const graphStateComponent = readonly ? 
-          <GraphView graphData={state.graph} help={helpText.graphEditorReadonly} mouseUpHandler={()=>{}} />
+          <GraphView graphData={graph} help={helpText.graphEditorReadonly} mouseUpHandler={()=>{}} />
         : <InfoHoverCardOverlay contents={helpText.graphEditor}>
             <D3GraphEditable
-              graph={state.graph}
+              graph={graph}
               graphState={graphState}
               forces={defaultGraphForces}
               setNextNodePosition={(newX,newY) => {x = newX; y = newY;}}
@@ -262,11 +247,11 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
         }
       },
     };
-    const deltaGraphL0Component = <GraphView<Delta,null> graphData={state.deltaGraphL0} {...deltaComponentProps} />;
-    const deltaGraphL1Component = <GraphView<Delta,null> graphData={state.deltaGraphL1} {...deltaComponentProps} />;
+    const deltaGraphL0Component = <GraphView<Delta,null> graphData={deltaGraphL0} {...deltaComponentProps} />;
+    const deltaGraphL1Component = <GraphView<Delta,null> graphData={deltaGraphL1} {...deltaComponentProps} />;
 
     const historyComponentWithMerge = <MergeView
-      history={state.historyGraph}
+      history={historyGraph}
       forces={defaultGraphForces}
       versionRegistry={versionRegistry}
       onMerge={outputs => callbacks.onMerge?.(outputs)}
@@ -277,7 +262,7 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
 
     const rountangleEditor = <InfoHoverCardOverlay contents={helpText.rountangleEditor}>
       <RountangleEditor
-        graph={state.graph}
+        graph={graph}
         graphState={graphState}
         onUserEdit={callbacks.onUserEdit}
       />
@@ -301,8 +286,8 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
         </Mantine.Menu>;
 
     }
-    const undoButton = makeUndoOrRedoButton(state.version.parents, "Undo", <Icons.IconChevronLeft/>, null, callbacks.onUndoClicked);
-    const redoButton = makeUndoOrRedoButton(state.version.children, "Redo", null, <Icons.IconChevronRight/>, callbacks.onRedoClicked);
+    const undoButton = makeUndoOrRedoButton(version.parents, "Undo", <Icons.IconChevronLeft/>, null, callbacks.onUndoClicked);
+    const redoButton = makeUndoOrRedoButton(version.children, "Redo", null, <Icons.IconChevronRight/>, callbacks.onRedoClicked);
 
     const undoRedoButtons = <>
       {undoButton}
@@ -310,7 +295,7 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
       {redoButton}
     </>;
 
-    const stackedUndoButtons = state.version.parents.map(([parentVersion,deltaToUndo]) => {
+    const stackedUndoButtons = version.parents.map(([parentVersion,deltaToUndo]) => {
       return (
         <div key={fullVersionId(parentVersion)}>
           <Mantine.Button fullWidth={true} compact={true} leftIcon={<Icons.IconChevronLeft size={18}/>} onClick={callbacks.onUndoClicked?.bind(null, parentVersion, deltaToUndo)}>
@@ -320,7 +305,7 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
         </div>
       );
     });
-    const stackedRedoButtons = state.version.children.map(([childVersion,deltaToRedo]) => {
+    const stackedRedoButtons = version.children.map(([childVersion,deltaToRedo]) => {
       return (
         <div key={fullVersionId(childVersion)}>
           <Mantine.Button style={{width: "100%"}} compact={true} rightIcon={<Icons.IconChevronRight size={18}/>} onClick={callbacks.onRedoClicked?.bind(null, childVersion, deltaToRedo)}>
@@ -367,7 +352,9 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
 
 
     return {
-      state,
+      state: {
+        version,
+      },
       reducer,
       components: {
         graphStateComponent,
@@ -385,10 +372,7 @@ export function newOnion({readonly, primitiveRegistry, versionRegistry}) {
   }
 
   return {
-    initialState,
     graphState,
-    versionRegistry,
-    getCurrentVersion,
     useOnion,
   }
 }

+ 17 - 20
src/onion/version.ts

@@ -156,11 +156,7 @@ export class Version {
   }
 
   // Serialize a path of Deltas from a Version in alreadyHave, to fully reconstruct this version.
-  // WARNING: Always make sure initialVersion is element of alreadyHave, or an Exception will be thrown.
-  serialize(alreadyHave: Set<Version> = new Set([initialVersion])): any {
-    if (!alreadyHave.has(initialVersion)) {
-      throw new Error("Must call Version.serialize() always with 'initialVersion'");
-    }
+  serialize(alreadyHave: Set<Version> = new Set()): any {
     const deltas = [];
     const versions = [];
     this.serializeInternal(new Set(alreadyHave), new Set<Delta>(), deltas, versions);
@@ -186,28 +182,29 @@ export class Version {
       embeddings[guestId] = {v: version.hash.toString('base64'), ovr};
     }
 
-    const [parentVersion, delta] = this.parents[0];
-    if (!alreadyHaveDeltas.has(delta)) {
-      deltas.push(delta.serialize());
-      alreadyHaveDeltas.add(delta);
+    if (this.parents.length > 0) {
+      const [parentVersion, delta] = this.parents[0];
+      if (!alreadyHaveDeltas.has(delta)) {
+        deltas.push(delta.serialize());
+        alreadyHaveDeltas.add(delta);
+      }
+      parentVersion.serializeInternal(alreadyHaveVersions, alreadyHaveDeltas, deltas, versions);
+      // return parentVersion.serializeUnsafe(alreadyHave).concat(delta.serialize());
+
+      versions.push({
+        id: this.hash.toString('base64'),
+        parent: parentVersion.hash.toString('base64'),
+        delta: delta.getHash().toString('base64'),
+        embeddings,
+      })
     }
-    parentVersion.serializeInternal(alreadyHaveVersions, alreadyHaveDeltas, deltas, versions);
-    // return parentVersion.serializeUnsafe(alreadyHave).concat(delta.serialize());
-
-    versions.push({
-      id: this.hash.toString('base64'),
-      parent: parentVersion.hash.toString('base64'),
-      delta: delta.getHash().toString('base64'),
-      embeddings,
-    })
   }
 }
 
 const initialHash = Buffer.alloc(32); // all zeros
-const initialVersion = new Version([], initialHash, 0, () => new Map());
 
 export class VersionRegistry {
-  readonly initialVersion: Version = initialVersion;
+  readonly initialVersion: Version = new Version([], initialHash, 0, () => new Map());
 
   // Maps version ID (as string, because a Buffer cannot be a map key) to Version
   readonly versionMap: Map<string, Version> = new Map([

+ 5 - 1
todo.txt

@@ -28,4 +28,8 @@ Todo, when I find the time:
 - Think: should self-embedding really be used for 'tagging'?
    Pro: Self-embedding already exists implicitly, why not allow it explicitly as well?
    Con: Makes several parts (e.g., merging) of the codebase more complex (need explicit tests to prevent infinite recursion)
-   Con: Do we even need tagging? A global operation like "give me all versions with tag X" will never scale as the number of versions goes up. Everything should be scoped. A tag should only have meaning within a well-defined scope.
+   Con: Do we even need tagging? A global operation like "give me all versions with tag X" will never scale as the number of versions goes up. Everything should be scoped. A tag should only have meaning within a well-defined scope.
+
+
+- Think: Introduce read-dependencies
+