@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
46 lines • 1.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.findAllClusters = findAllClusters;
const edge_1 = require("./graph/edge");
const vertex_1 = require("./graph/vertex");
const assert_1 = require("../util/assert");
function findAllClusters(graph) {
const clusters = [];
// we reverse the vertices since dependencies usually point "backwards" from later nodes
const notReached = new Set([...graph.vertices(true)].map(([id]) => id).reverse());
while (notReached.size > 0) {
const [startNode] = notReached;
notReached.delete(startNode);
clusters.push({
startNode: startNode,
members: [...makeCluster(graph, startNode, notReached)],
hasUnknownSideEffects: graph.unknownSideEffects.has(startNode)
});
}
return clusters;
}
function makeCluster(graph, from, notReached) {
const info = graph.getVertex(from);
(0, assert_1.guard)(info !== undefined, () => `Vertex ${from} not found in graph`);
const nodes = new Set([from]);
// cluster function def exit points
if (info.tag === vertex_1.VertexType.FunctionDefinition) {
for (const sub of info.exitPoints) {
if (notReached.delete(sub)) {
makeCluster(graph, sub, notReached).forEach(n => nodes.add(n));
}
}
}
// cluster adjacent edges
for (const [dest, { types }] of [...graph.outgoingEdges(from) ?? [], ...graph.ingoingEdges(from) ?? []]) {
// don't cluster for function content if it isn't returned
if ((0, edge_1.edgeDoesNotIncludeType)(types, edge_1.EdgeType.Returns) && info.onlyBuiltin && info.name == '{') {
continue;
}
if (notReached.delete(dest)) {
makeCluster(graph, dest, notReached).forEach(n => nodes.add(n));
}
}
return nodes;
}
//# sourceMappingURL=cluster.js.map