@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
53 lines • 2.08 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");
/**
* Find all clusters in the given dataflow graph.
*/
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).toArray().reverse());
while (notReached.size > 0) {
const [startNode] = notReached;
notReached.delete(startNode);
clusters.push({
startNode: startNode,
members: Array.from(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 { nodeId } of info.exitPoints) {
if (notReached.delete(nodeId)) {
for (const m of makeCluster(graph, nodeId, notReached)) {
nodes.add(m);
}
}
}
}
// cluster adjacent edges
for (const edges of [graph.outgoingEdges(from), graph.ingoingEdges(from)]) {
for (const [dest, e] of edges ?? []) {
// don't cluster for function content if it isn't returned
if (edge_1.DfEdge.doesNotIncludeType(e, 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