All files / src/edits patchAst.js

97.44% Statements 38/39
91.67% Branches 11/12
100% Functions 6/6
97.44% Lines 38/39

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 651x       151x     151x         92x 92x 92x 92x 92x 117x 117x 117x 117x 117x           165x 165x 165x 151x   165x 151x     165x   165x 165x 294x 92x 92x 92x 92x 92x   202x     165x 151x   165x 112x 112x 23x       142x 142x 142x    
import {assert} from '../utils';
 
// defaultdict with empty list
function addIndex(container, k, v) {
  Iif (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;
}