UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

100 lines 4.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.processQuote = processQuote; const known_call_handling_1 = require("../known-call-handling"); const node_id_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id"); const vertex_1 = require("../../../../../graph/vertex"); const logger_1 = require("../../../../../logger"); const df_helper_1 = require("../../../../../graph/df-helper"); const edge_1 = require("../../../../../graph/edge"); const built_in_proc_name_1 = require("../../../../../environments/built-in-proc-name"); const graph_1 = require("../../../../../graph/graph"); /** * Process a call to `quote` or similar nse/substitution functions. */ function processQuote(name, args, rootId, data, config) { const startEnv = data.environment; let lastEnv = startEnv; const { information, processedArguments, fnRef } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: config.forceArgs, origin: built_in_proc_name_1.BuiltInProcName.Quote, patchData(data, index) { if (index === config.quoteArgumentsWithIndex) { lastEnv = data.environment; return { ...data, environment: data.ctx.env.makeCleanEnv() }; } else { return { ...data, environment: lastEnv }; } } }); let inRefs = [fnRef]; let outRefs = []; let unknownRefs = []; for (let i = 0; i < args.length; i++) { const processedArg = processedArguments[i]; if (processedArg && i !== config?.quoteArgumentsWithIndex) { inRefs = inRefs.concat(processedArg.in); outRefs = outRefs.concat(processedArg.out); unknownRefs = unknownRefs.concat(processedArg.unknownReferences); } else if (processedArg) { information.graph.addEdge(rootId, processedArg.entryPoint, edge_1.EdgeType.NonStandardEvaluation); /* nse actually affects _everything_ within that argument! */ for (const [vtx] of processedArg.graph.vertices(true)) { information.graph.addEdge(rootId, vtx, edge_1.EdgeType.NonStandardEvaluation); } } } if (config?.envArgIndex !== undefined) { const envProcessed = processedArguments[config.envArgIndex]; const exprProcessed = processedArguments[config.quoteArgumentsWithIndex]; if (envProcessed && exprProcessed) { try { // traverse the env processed DFG to find list calls (prefix-aware handling) df_helper_1.Dataflow.visitDfg(envProcessed.graph, envProcessed.entryPoint, (vtx) => { if (vtx.tag !== vertex_1.VertexType.FunctionCall) { return; } if (!vtx.origin.includes(built_in_proc_name_1.BuiltInProcName.List)) { return true; } const useMap = new Map(); for (const vType of [vertex_1.VertexType.Use, vertex_1.VertexType.FunctionCall]) { for (const [useId] of exprProcessed.graph.verticesOfType(vType)) { const rn = (0, node_id_1.recoverName)(useId, exprProcessed.graph.idMap); if (rn) { const arr = useMap.get(rn) ?? []; arr.push(useId); useMap.set(rn, arr); } } } if (useMap.size === 0) { return true; } const listFields = vtx.args.filter(graph_1.FunctionArgument.isNamed); for (const field of listFields) { const uses = useMap.get(field.name); if (uses) { for (const useId of uses) { information.graph.addEdge(useId, field.nodeId, edge_1.EdgeType.Reads); } } } return true; }); } catch (e) { logger_1.dataflowLogger.warn('Failed to apply substitute-style env list replacement in quote-like call', { error: e }); } } } return { ...information, environment: startEnv, in: inRefs, out: outRefs, unknownReferences: unknownRefs }; } //# sourceMappingURL=built-in-quote.js.map