Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 1x | import {assert} from '../utils'; // defaultdict with empty list function addIndex(container, k, v) { if (container[k]) { container[k].push(v); } else { container[k] = [v]; } } function copyAllIds(oldTree, newTree) { const oldIter = oldTree.descendants()[Symbol.iterator](); const newIter = newTree.descendants()[Symbol.iterator](); let oldPtr = oldIter.next(); let newPtr = newIter.next(); while (!oldPtr.done) { assert(!newPtr.done); newPtr.value.id = oldPtr.value.id; newPtr.value.element = oldPtr.value.element; oldPtr = oldIter.next(); newPtr = newIter.next(); } } export default function unify(oldTree, newTree) { function loop(oldTree, newTree) { newTree.id = oldTree.id; const index = {}; for (const oldNode of oldTree.children()) { addIndex(index, oldNode.hash, oldNode); } for (const key in index) { index[key].reverse(); } const processed = new Set(); let partiallySuccess = false; const newLeftover = [...newTree.children()].filter(newNode => { if (index[newNode.hash]?.length > 0) { const oldNode = index[newNode.hash].pop(); copyAllIds(oldNode, newNode); partiallySuccess = true; processed.add(oldNode.id); return false; } else { return true; } }); const oldLeftover = [...oldTree.children()].filter(oldNode => { return !processed.has(oldNode.id); }); if (partiallySuccess || newLeftover.length <= 1) { const commonLength = Math.min(oldLeftover.length, newLeftover.length); for (let i = 0; i < commonLength; i++) { loop(oldLeftover[i], newLeftover[i]); } } } loop(oldTree, newTree); newTree.annotateNodes(); return newTree; } |