sameNames

tcmts.cli.main.sameNames · #eb35udj5 · term · runs anywhere

Two renderings of a line of code, alike but for some names (a definition written alone, and written with others, where a name it had alone was taken): each name in a that's another in b, added to names.

export function sameNames(a: string, b: string, names: Map<string, string>) {
  const tokens = (s: string) => s.match(/[A-Za-z_$][\w$]*|\d[\w.]*|\s+|[^\s\w$]/g) ?? [];
  const x = tokens(a);
  const y = tokens(b);
  const ident = /^[A-Za-z_$]/;
  // the two aligned: a name where the other has another name, the rest the same (or only in one: `{ x: x_1 }`)
  const lcs = Array.from({ length: x.length + 1 }, () =>
    Array.from({ length: y.length + 1 }, () => 0),
  );
  for (let i = x.length - 1; i >= 0; i--)
    for (let j = y.length - 1; j >= 0; j--)
      lcs[i]![j] =
        x[i] === y[j] ? lcs[i + 1]![j + 1]! + 1 : Math.max(lcs[i + 1]![j]!, lcs[i]![j + 1]!);
  let i = 0;
  let j = 0;
  while (i < x.length && j < y.length) {
    if (x[i] === y[j]) {
      i++;
      j++;
    } else if (ident.test(x[i]!) && ident.test(y[j]!) && lcs[i + 1]![j + 1]! === lcs[i]![j]!) {
      if (!names.has(x[i]!)) names.set(x[i]!, y[j]!);
      i++;
      j++;
    } else if (lcs[i + 1]![j]! >= lcs[i]![j + 1]!) i++;
    else j++;
  }
}

used by