srecord noeq G22MeshMapper(G22Mesh mesh1, G22Mesh mesh2) > AbstractSteppable { // import the important classes delegate Anchor, Curve to G22Mesh. // MAPPING VARS // keys are the anchors from mesh1, values are the anchors from mesh2 new Map anchorMap; // keys are the curves from mesh1, values are the curves from mesh2 new Map mappedCurves; // EXCEPTIONS (e.g. meshes don't match in signature) // set to the reason why when a mapping is deemed impossible settable O rejectedBecause; bool rejected() { ret rejectedBecause != null; } // INTERNAL VARS bool prechecksDone; S sig1, sig2; // Anchors and curves in mesh1 that are not or only partially mapped. // This list is not complete at the beginning. Anchors and curves are // discovered by searching breadth-first from the visited anchors and // curves. new L mappableAnchors; // curves that are half-mapped (one end is mapped) indexed by the // unmapped anchor new MultiMap halfMappedCurves; // anchor lookup mesh 1 // MultiMap anchorsByArity1; // anchor lookup mesh 2 MultiMap anchorsByArity2; // First let's define the search procedure in a "normal" (native) // control flow. Then possibly convert to v-stack/coroutine. void searchForMapping { prechecks(); if (rejected()) ret; anchorsByArity2 = multiMapIndex(mesh2.anchors(), a -> a.arity()); Anchor anchor1 = first(mesh1.anchors()); for (anchor2 : anchorsByArity2.get(anchor1.arity())) { temp tempAssignAnchor(anchor1, anchor2); //while (nempty(mappableCurves)) } } AutoCloseable tempAssignAnchor(Anchor anchor1, Anchor anchor2) { var undoAnchorAssignment = tempMapPutStrictlyOrFail(anchorMap, anchor1, anchor2); // Check all curves connected to anchor1. They will now be at least // half mapped. for (curve : anchor1.curves()) { Curve curve2 = calculateCurveMapping(curve); if (curve2 != null) { halfMappedCurves.remove(anchor1, curve); mappedCurves.put(curve, curve2); } else halfMappedCurves.put(curve.anchorOpposite(anchor1), curve); } ret -> { _close(undoAnchorAssignment); for (curve : anchor1.curves()) { mappedCurves.remove(curve); if (nCurveAnchorsAssigned(curve) == 0) { halfMappedCurves.remove(anchor1, curve); } } }; } int nCurveAnchorsAssigned(Curve curve1) { // count twice if stat+end is same anchor ret zeroOrOne(anchorMap.containsKey(curve1.start())) + zeroOrOne(anchorMap.containsKey(curve1.end())); } Curve calculateCurveMapping(Curve curve1) { fail(); // TODO: there are possibly multiple choices here! } public bool step() { if (!prechecksDone) { prechecks(); ret !rejected(); } false; // TODO } protected void prechecks { set prechecksDone; sig1 = mesh1.signature(); sig2 = mesh1.signature(); if (!eq(sig1, sig2)) ret with rejectedBecause(G22SignatureMismatch(mesh1, mesh2)); } }