Skip to content

Instantly share code, notes, and snippets.

@Elyx0
Forked from frangio/c3-debugger.js
Created October 19, 2024 06:39
Show Gist options
  • Select an option

  • Save Elyx0/a7ba287fdca0cfc8e38778dc62d98882 to your computer and use it in GitHub Desktop.

Select an option

Save Elyx0/a7ba287fdca0cfc8e38778dc62d98882 to your computer and use it in GitHub Desktop.

Revisions

  1. @frangio frangio renamed this gist Jul 4, 2023. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. @frangio frangio created this gist Jul 4, 2023.
    112 changes: 112 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,112 @@
    "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(',')}`);
    }
    }