Skip to content

Instantly share code, notes, and snippets.

@frangio
Created July 4, 2023 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frangio/f4c07d0078895d14aa2990cc37a36412 to your computer and use it in GitHub Desktop.
Save frangio/f4c07d0078895d14aa2990cc37a36412 to your computer and use it in GitHub Desktop.
C3 linearization debugger based on https://github.com/federicobond/c3-linearization
"use strict";
const defaultOptions = {
reverse: true,
python: false
}
function merge(sequences) {
let result = [];
sequences = sequences.map(s => s.slice());
while (sequences.length > 0) {
let found = false;
let head;
for (let seq of sequences) {
head = seq[0];
function isBadHead(s) {
return s !== seq && s.slice(1).includes(head);
}
if (!sequences.find(isBadHead)) {
found = true;
result.push(head);
for (let seq of sequences) {
const index = seq.indexOf(head);
if (index > -1) {
seq.splice(index, 1);
}
}
break;
}
}
sequences = sequences.filter(s => s.length > 0);
if (!found) {
throw new Error("cannot find C3-linearization for input");
}
}
return result;
}
function _linearize(graph, head, results, visiting, options) {
if (results.hasOwnProperty(head)) {
return results[head];
}
if (visiting.has(head)) {
throw new Error('circular dependency found');
}
visiting.add(head);
let parents = graph[head];
if (!parents || parents.length === 0) {
const res = [head];
results[head] = res;
return res;
}
if (options.reverse === true) {
parents = parents.slice().reverse();
}
let sequences = parents.map(x => _linearize(graph, x, results, visiting, options));
if (options.python === true) {
sequences = sequences.concat([parents]);
}
const res = [head].concat(merge(sequences));
results[head] = res;
visiting.delete(head);
return res;
}
function linearize(graph, options) {
options = Object.assign({}, defaultOptions, options)
const results = {};
const visiting = new Set();
const heads = Object.keys(graph);
for (let head of heads) {
_linearize(graph, head, results, visiting, options);
}
return results;
}
module.exports.linearize = linearize;
if (require.main === module) {
const contracts = process.argv.slice(2);
const graph = Object.fromEntries(
contracts.map(c => {
const [p, g] = c.split(':');
const gs = g.split(',');
return [p, gs];
})
);
for (const [p, gs] of Object.entries(linearize(graph))) {
console.log(`${p}: ${gs.join(',')}`);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment