@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
101 lines • 4.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.processApply = processApply;
const known_call_handling_1 = require("../known-call-handling");
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
const logger_1 = require("../../../../../logger");
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
const vertex_1 = require("../../../../../graph/vertex");
const edge_1 = require("../../../../../graph/edge");
const identifier_1 = require("../../../../../environments/identifier");
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFunctionArgument, unquoteFunction, resolveInEnvironment, resolveValue }) {
/* as the length is one-based and the argument filter mapping is zero-based, we do not have to subtract 1 */
const forceArgsMask = new Array(indexOfFunction).fill(false);
forceArgsMask.push(true);
const { information, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({
name, args, rootId, data, forceArgs: forceArgsMask
});
let index = indexOfFunction;
/* search, if one of the arguments actually contains the argument name if given in the config */
if (nameOfFunctionArgument !== undefined) {
const mayFn = args.findIndex(arg => arg !== r_function_call_1.EmptyArgument && arg.name && arg.name.content === nameOfFunctionArgument);
if (mayFn >= 0) {
index = mayFn;
}
}
/* validate, that we indeed have so many arguments to fill this one :D */
if (index >= args.length) {
logger_1.dataflowLogger.warn(`Function argument at index ${index} not found, skipping`);
return information;
}
const arg = args[index];
if (arg === r_function_call_1.EmptyArgument || !arg.value || (!unquoteFunction && arg.value.type !== type_1.RType.Symbol)) {
logger_1.dataflowLogger.warn(`Expected symbol as argument at index ${index}, but got ${JSON.stringify(arg)} instead.`);
return information;
}
let functionId = undefined;
let functionName = undefined;
const val = arg.value;
if (unquoteFunction && val.type === type_1.RType.String) {
functionId = val.info.id;
functionName = val.content.str;
}
else if (val.type === type_1.RType.Symbol) {
functionId = val.info.id;
if (resolveValue) {
const resolved = (0, resolve_by_name_1.resolveValueOfVariable)(val.content, data.environment);
if (resolved?.length === 1 && typeof resolved[0] === 'string') {
functionName = resolved[0];
}
}
else {
functionName = val.content;
}
}
if (functionName === undefined || functionId === undefined) {
logger_1.dataflowLogger.warn(`Expected symbol or string as function argument at index ${index}, but got ${JSON.stringify(val)} instead.`);
return information;
}
const allOtherArguments = processedArguments.filter((_, i) => i !== index).map((arg, i) => {
const counterpart = args[i];
if (arg && counterpart !== r_function_call_1.EmptyArgument && counterpart.name) {
return {
name: counterpart.name.content,
controlDependencies: data.controlDependencies,
type: identifier_1.ReferenceType.Argument,
nodeId: arg.entryPoint
};
}
else {
return r_function_call_1.EmptyArgument;
}
});
/* identify it as a full-blown function call :) */
information.graph.updateToFunctionCall({
tag: vertex_1.VertexType.FunctionCall,
id: functionId,
name: functionName,
args: allOtherArguments,
environment: resolveInEnvironment === 'global' ? undefined : data.environment,
onlyBuiltin: resolveInEnvironment === 'global',
cds: data.controlDependencies
});
for (const arg of processedArguments) {
if (arg) {
information.graph.addEdge(functionId, arg.entryPoint, edge_1.EdgeType.Argument);
}
}
if (resolveInEnvironment === 'global') {
// remove from open ingoing references
return {
...information,
in: information.in.filter(ref => ref.nodeId !== functionId),
unknownReferences: information.unknownReferences.filter(ref => ref.nodeId !== functionId)
};
}
else {
return information;
}
}
//# sourceMappingURL=built-in-apply.js.map