UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

101 lines 3.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.visitCfgInReverseOrder = visitCfgInReverseOrder; exports.visitCfgInOrder = visitCfgInOrder; exports.canReach = canReach; const control_flow_graph_1 = require("./control-flow-graph"); /** * Visit all nodes reachable from the start node in the control flow graph, traversing the dependencies but ignoring cycles. * @param graph - The control flow graph. * @param startNodes - The nodes to start the traversal from. * @param visitor - The visitor function to call for each node, if you return true the traversal from this node will be stopped. * * This function is of type {@link SimpleCfgVisitor}. * @see {@link visitCfgInOrder} for a traversal in order */ function visitCfgInReverseOrder(graph, startNodes, // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -- void is used to indicate that the return value is ignored/we never stop visitor) { const visited = new Set(); const queue = startNodes.slice(); const hasBb = graph.mayHaveBasicBlocks(); while (queue.length > 0) { const current = queue.pop(); if (visited.has(current)) { continue; } visited.add(current); if (visitor(current)) { continue; } else if (hasBb) { const get = graph.getVertex(current); if (control_flow_graph_1.CfgVertex.isBlock(get)) { const elems = control_flow_graph_1.CfgVertex.getBasicBlockElements(get); for (const e of elems.toReversed()) { queue.push(control_flow_graph_1.CfgVertex.getId(e)); } } } const incoming = graph.outgoingEdges(current); if (incoming) { for (const c of incoming.keys()) { queue.push(c); } } } } /** * Visit all nodes reachable from the start node in the control flow graph, traversing the dependencies in execution order but ignoring cycles. * @param graph - The control flow graph. * @param startNodes - The nodes to start the traversal from. * @param visitor - The visitor function to call for each node, if you return true the traversal from this node will be stopped. * * This function is of type {@link SimpleCfgVisitor}. * @see {@link visitCfgInReverseOrder} for a traversal in reversed order */ function visitCfgInOrder(graph, startNodes, // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -- void is used to indicate that the return value is ignored/we never stop visitor) { const visited = new Set(); const queue = startNodes.slice(); const hasBb = graph.mayHaveBasicBlocks(); while (queue.length > 0) { const current = queue.shift(); if (visited.has(current)) { continue; } visited.add(current); if (visitor(current)) { continue; } else if (hasBb) { const get = graph.getVertex(current); if (control_flow_graph_1.CfgVertex.isBlock(get)) { const elems = control_flow_graph_1.CfgVertex.getBasicBlockElements(get); for (const e of elems.toReversed()) { queue.push(control_flow_graph_1.CfgVertex.getId(e)); } } } const outgoing = graph.ingoingEdges(current) ?? []; for (const [to] of outgoing) { queue.push(to); } } return visited; } /** * Check if a node can reach another node in the control flow graph. */ function canReach(graph, from, to) { let reached = false; visitCfgInOrder(graph, from, node => { if (node === to) { reached = true; return true; } }); return reached; } //# sourceMappingURL=simple-visitor.js.map