@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
66 lines • 2.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.lineageCommand = void 0;
exports.getLineage = getLineage;
const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipelines");
const retriever_1 = require("../../../r-bridge/retriever");
const parse_1 = require("../../../slicing/criterion/parse");
const edge_1 = require("../../../dataflow/graph/edge");
const assert_1 = require("../../../util/assert");
function splitAt(str, idx) {
return [str.slice(0, idx), str.slice(idx)];
}
async function getDfg(parser, remainingLine) {
return await (0, default_pipelines_1.createDataflowPipeline)(parser, {
request: (0, retriever_1.requestFromInput)(remainingLine.trim())
}).allRemainingSteps();
}
function filterRelevantEdges(edge) {
return (0, edge_1.edgeIncludesType)(edge_1.EdgeType.DefinedBy | edge_1.EdgeType.DefinedByOnCall | edge_1.EdgeType.Returns | edge_1.EdgeType.Reads, edge.types);
}
function pushRelevantEdges(queue, outgoingEdges) {
queue.push(...[...outgoingEdges].filter(([_, edge]) => filterRelevantEdges(edge)));
}
/**
* Get the lineage of a node in the dataflow graph
*
* @param criterion - The criterion to get the lineage of
* @param graph - The dataflow graph to search in
* @param idMap - The ID map to use for resolving the criterion (will default to that shipped with the dfgraph)
* @returns The lineage of the node represented as a set of node ids
*/
function getLineage(criterion, graph, idMap) {
idMap ??= graph.idMap;
(0, assert_1.guard)(idMap !== undefined, 'The ID map is required to get the lineage of a node');
const src = graph.get((0, parse_1.slicingCriterionToId)(criterion, idMap));
(0, assert_1.guard)(src !== undefined, 'The ID pointed to by the criterion does not exist in the dataflow graph');
const [vertex, outgoingEdges] = src;
const result = new Set([vertex.id]);
const edgeQueue = [];
pushRelevantEdges(edgeQueue, outgoingEdges);
while (edgeQueue.length > 0) {
const [target] = edgeQueue.shift();
if (result.has(target)) {
continue;
}
result.add(target);
const outgoingEdges = graph.outgoingEdges(target);
if (outgoingEdges !== undefined) {
pushRelevantEdges(edgeQueue, outgoingEdges);
}
}
return result;
}
exports.lineageCommand = {
description: 'Get the lineage of an R object',
usageExample: ':lineage',
aliases: ['lin'],
script: false,
fn: async (output, shell, remainingLine) => {
const [criterion, rest] = splitAt(remainingLine, remainingLine.indexOf(' '));
const { dataflow: dfg } = await getDfg(shell, rest);
const lineageIds = getLineage(criterion, dfg.graph);
output.stdout([...lineageIds].join('\n'));
}
};
//# sourceMappingURL=repl-lineage.js.map