@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
87 lines • 4.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.processGet = processGet;
const known_call_handling_1 = require("../known-call-handling");
const unpack_argument_1 = require("../argument/unpack-argument");
const make_argument_1 = require("../argument/make-argument");
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
const logger_1 = require("../../../../../logger");
const retriever_1 = require("../../../../../../r-bridge/retriever");
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
const edge_1 = require("../../../../../graph/edge");
const identifier_1 = require("../../../../../environments/identifier");
const built_in_proc_name_1 = require("../../../../../environments/built-in-proc-name");
const built_in_envir_utils_1 = require("./built-in-envir-utils");
const range_1 = require("../../../../../../util/range");
/**
* Processes a built-in 'get' function call.
*
* When an `envir` argument is present and resolves to a variable with a tracked environment
* state (set up by `new.env()` + `assign(..., envir=...)`), the lookup is performed inside
* that environment so that the correct definition is found and the returned {@link DataflowInformation}
* contains the right read edges.
*/
function processGet(name, args, rootId, data) {
/* use the custom environment for resolution when envir points to a tracked env */
const resolution = (0, built_in_envir_utils_1.resolveEnvirArg)(args, data);
/* the first arg must be a string naming the variable to retrieve */
const firstArg = args.length >= 1 ? args[0] : undefined;
const retrieve = firstArg !== undefined && firstArg !== r_function_call_1.EmptyArgument
? (0, unpack_argument_1.unpackNonameArg)(firstArg)
: undefined;
let treatTargetAsSymbol = undefined;
if (retrieve !== undefined && retrieve.type === type_1.RType.String) {
treatTargetAsSymbol = {
type: type_1.RType.Symbol,
info: retrieve.info,
content: (0, retriever_1.removeRQuotes)(retrieve.lexeme),
lexeme: retrieve.lexeme,
location: retrieve.location
};
}
else if (retrieve !== undefined) {
const resolvedName = (0, built_in_envir_utils_1.resolveConstantString)(retrieve, data);
if (resolvedName !== undefined) {
const synthId = rootId + '-get-name';
const synthSymbol = {
type: type_1.RType.Symbol,
info: { ...retrieve.info, id: synthId },
content: resolvedName,
lexeme: resolvedName,
location: retrieve.location ?? name.location ?? range_1.SourceRange.invalid()
};
data.completeAst.idMap.set(synthId, synthSymbol);
treatTargetAsSymbol = synthSymbol;
}
}
if (treatTargetAsSymbol === undefined) {
logger_1.dataflowLogger.warn(`symbol access with ${identifier_1.Identifier.toString(name.content)} has not 1 string argument, skipping`);
// dynamic, unresolvable name: reached-but-unknown rather than dropped
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default', hasUnknownSideEffect: true }).information;
}
/* resolve in the custom environment if one was found, else the global one.
* Pass remaining original args (e.g. envir=e) so they appear as Use vertices in the graph. */
const { information, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({
name,
args: [...(0, make_argument_1.wrapArgumentsUnnamed)([treatTargetAsSymbol], data.completeAst.idMap), ...args.slice(1)],
rootId,
data: resolution ? resolution.envirData : data,
origin: built_in_proc_name_1.BuiltInProcName.Get
});
const firstProcessed = processedArguments[0];
if (firstProcessed) {
information.graph.addEdge(rootId, firstProcessed.entryPoint, edge_1.EdgeType.Returns | edge_1.EdgeType.Reads);
}
if (resolution) {
information.graph.addEdge(rootId, resolution.envirNodeId, edge_1.EdgeType.Reads);
}
const isolatedTarget = resolution?.envirData.environment.current.builtInEnv === true;
const readsToDrop = isolatedTarget && firstProcessed ? new Set([firstProcessed.entryPoint]) : undefined;
/* restore the caller's (global) environment so we don't leak envState upward */
return {
...information,
in: readsToDrop ? information.in.filter(({ nodeId }) => !readsToDrop.has(nodeId)) : information.in,
environment: data.environment
};
}
//# sourceMappingURL=built-in-get.js.map