@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
100 lines • 4.65 kB
JavaScript
;
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