-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
98 lines (72 loc) · 1.87 KB
/
index.js
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"use strict";
const defaultOptions = {
reverse: false,
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;