UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

61 lines 3.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.linkReadsForArgument = linkReadsForArgument; exports.processFunctionArgument = processFunctionArgument; const processor_1 = require("../../../processor"); const model_1 = require("../../../../r-bridge/lang-4.x/ast/model/model"); const graph_1 = require("../../../graph/graph"); const type_1 = require("../../../../r-bridge/lang-4.x/ast/model/type"); const edge_1 = require("../../../graph/edge"); const vertex_1 = require("../../../graph/vertex"); /** * Links all reads that occur before the argument to the argument root node. */ function linkReadsForArgument(root, ingoingRefs, graph) { const rid = root.info.id; const allIdsBeforeArguments = new Set(model_1.RNode.collectAllIdsWithStop(root, n => n.type === type_1.RType.Argument && n.info.id !== rid)); const ingoingBeforeArgs = ingoingRefs.filter(r => allIdsBeforeArguments.has(r.nodeId)); for (const ref of ingoingBeforeArgs) { // link against the root reference currently I do not know how to deal with nested function calls otherwise graph.addEdge(rid, ref.nodeId, edge_1.EdgeType.Reads); } } /** * Processes the dataflow information for a function argument. */ function processFunctionArgument(argument, data) { const name = argument.name === undefined ? undefined : (0, processor_1.processDataflowFor)(argument.name, data); const value = argument.value === undefined ? undefined : (0, processor_1.processDataflowFor)(argument.value, data); // we do not keep the graph of the name, as this is no node that should ever exist const graph = value?.graph ?? new graph_1.DataflowGraph(data.completeAst.idMap); const argumentName = argument.name?.content; let entryPoint = value?.entryPoint; if (argumentName) { graph.addVertex({ tag: vertex_1.VertexType.Use, id: argument.info.id, cds: data.cds }, data.ctx.env.makeCleanEnv()); entryPoint = argument.info.id; } const ingoingRefs = value ? value.unknownReferences.concat(value.in, name?.in ?? []) : name?.in; if (entryPoint && argument.value?.type === type_1.RType.FunctionDefinition) { graph.addEdge(entryPoint, argument.value.info.id, edge_1.EdgeType.Reads); } else if (argumentName && ingoingRefs) { // we only need to link against those which are not already bound to another function call argument linkReadsForArgument(argument, value ? ingoingRefs.concat(value.out /* value may perform definitions */) : ingoingRefs, graph); } return { unknownReferences: [], // active nodes of the name will be lost as they are only used to reference the corresponding parameter in: ingoingRefs?.filter(r => r.name !== undefined) ?? [], out: [...value?.out ?? [], ...(name?.out ?? [])], graph: graph, environment: value?.environment ?? data.environment, entryPoint: entryPoint ?? argument.info.id, exitPoints: value?.exitPoints ?? name?.exitPoints ?? [{ nodeId: argument.info.id, type: 0 /* ExitPointType.Default */, cds: data.cds }], hooks: [] }; } //# sourceMappingURL=process-argument.js.map