@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
210 lines • 8.52 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processS7NewGeneric = processS7NewGeneric;
const known_call_handling_1 = require("../known-call-handling");
const logger_1 = require("../../../../../logger");
const linker_1 = require("../../../../linker");
const common_1 = require("../common");
const unpack_argument_1 = require("../argument/unpack-argument");
const r_argument_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-argument");
const edge_1 = require("../../../../../graph/edge");
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
const assert_1 = require("../../../../../../util/assert");
const identifier_1 = require("../../../../../environments/identifier");
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
const r_value_1 = require("../../../../../eval/values/r-value");
const vertex_1 = require("../../../../../graph/vertex");
const range_1 = require("../../../../../../util/range");
const built_in_proc_name_1 = require("../../../../../environments/built-in-proc-name");
/**
* Process an S7 new generic dispatch call like `new_generic` or `setGeneric`.
*/
function processS7NewGeneric(name, args, rootId, data, config) {
if (args.length < 1) {
logger_1.dataflowLogger.warn('empty s7 new_generic, skipping');
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
}
const params = {
[config.args.name]: 'name',
};
if (config.args.dispatchArg) {
params[config.args.dispatchArg] = 'dispatchArg';
}
params[config.args.fun] = 'fun';
params['...'] = '...';
const argMaps = (0, linker_1.pMatch)((0, common_1.convertFnArguments)(args), params);
const genName = (0, unpack_argument_1.unpackArg)(r_argument_1.RArgument.getWithId(args, argMaps.get('name')?.[0]));
if (!genName) {
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
}
const n = (0, alias_tracking_1.resolveIdToValue)(genName.info.id, { environment: data.environment, resolve: data.ctx.config.solver.variables, idMap: data.completeAst.idMap, full: true, ctx: data.ctx });
const accessedIdentifiers = [];
if (n.type === 'set') {
for (const elem of n.elements) {
if (elem.type === 'string' && (0, r_value_1.isValue)(elem.value)) {
accessedIdentifiers.push(elem.value.str);
}
}
}
if (accessedIdentifiers.length === 0) {
logger_1.dataflowLogger.warn('s7 new_generic non-resolvable skipping');
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
}
data = { ...data, currentS7name: accessedIdentifiers };
let funArg = (0, unpack_argument_1.unpackArg)(r_argument_1.RArgument.getWithId(args, argMaps.get('fun')?.[0]))?.info.id;
const effectiveArgs = args.slice();
if (!funArg) {
const dispatchArg = (0, unpack_argument_1.unpackArg)(r_argument_1.RArgument.getWithId(args, argMaps.get('dispatchArg')?.[0]));
const newFun = makeS7DispatchFDef(name, [dispatchArg?.lexeme ?? undefined], rootId, args.length, data.completeAst.idMap);
// fake it 'function([dispatch_args],...) S7_dispatch()'
effectiveArgs.push(newFun[0]);
funArg = newFun[1];
}
const info = (0, known_call_handling_1.processKnownFunctionCall)({ name, forceArgs: 'all', args: effectiveArgs, rootId, data, origin: built_in_proc_name_1.BuiltInProcName.S7NewGeneric }).information;
info.graph.addEdge(rootId, funArg, edge_1.EdgeType.Returns);
info.entryPoint = funArg;
const fArg = info.graph.getVertex(funArg);
if (fArg?.tag === vertex_1.VertexType.FunctionDefinition) {
fArg.mode ??= ['s4', 's7'];
}
return info;
}
// 'function([dispatch_args],...) S7_dispatch()'; returns the value id
function makeS7DispatchFDef(name, names, rootId, args, idMap) {
const argNameId = rootId + '-s7-new-generic-fun-arg-name';
const r = name.location ?? range_1.SourceRange.invalid();
const argName = {
type: type_1.RType.Symbol,
lexeme: 'fun',
content: 'fun',
info: {
id: argNameId,
nesting: name.info.nesting,
role: "arg-n" /* RoleInParent.ArgumentName */,
fullRange: r,
adToks: undefined,
file: name.info.file,
parent: rootId,
index: 0
},
location: r,
};
idMap.set(argNameId, argName);
const funcNameId = rootId + '-s7-new-generic-fun-name';
const funcName = {
type: type_1.RType.Symbol,
lexeme: 'S7_dispatch',
info: {
id: funcNameId,
nesting: name.info.nesting,
role: "call-name" /* RoleInParent.FunctionCallName */,
fullRange: r,
adToks: undefined,
file: name.info.file,
parent: rootId,
index: 0
},
location: r,
content: identifier_1.Identifier.make('S7_dispatch', 's7'),
};
const funcBody = {
type: type_1.RType.FunctionCall,
location: r,
lexeme: 'S7_dispatch',
named: true,
functionName: funcName,
arguments: [],
info: {
id: rootId + '-s7-new-generic-fun-body',
nesting: name.info.nesting,
role: "fun-b" /* RoleInParent.FunctionDefinitionBody */,
fullRange: r,
adToks: undefined,
file: name.info.file,
parent: rootId,
index: 0
}
};
const fdefId = rootId + '-s7-new-generic-fun-fdef';
const argValue = {
type: type_1.RType.FunctionDefinition,
info: {
file: name.info.file,
id: fdefId,
nesting: name.info.nesting,
role: "arg-v" /* RoleInParent.ArgumentValue */,
parent: rootId,
index: args + 1,
adToks: undefined,
fullRange: r,
},
lexeme: 'function',
location: r,
parameters: [...names.filter(assert_1.isNotUndefined), '...'].map((n, i) => {
const paramId = fdefId + `-param-${i}`;
const paramNameId = paramId + '-name';
const paramName = {
type: type_1.RType.Symbol,
lexeme: n,
content: n,
info: {
id: paramNameId,
nesting: name.info.nesting,
role: "param-n" /* RoleInParent.ParameterName */,
fullRange: r,
adToks: undefined,
file: name.info.file,
index: i,
parent: paramId
},
location: r,
};
const param = {
type: type_1.RType.Parameter,
location: r,
lexeme: n,
name: paramName,
defaultValue: undefined,
special: n === '...',
info: {
id: paramId,
nesting: name.info.nesting,
role: "param" /* RoleInParent.FunctionDefinitionParameter */,
parent: fdefId,
index: i,
adToks: undefined,
file: name.info.file,
fullRange: r,
}
};
idMap.set(paramNameId, paramName);
idMap.set(paramId, param);
return param;
}),
body: funcBody,
};
idMap.set(funcNameId, funcName);
idMap.set(funcBody.info.id, funcBody);
idMap.set(fdefId, argValue);
const argId = rootId + '-s7-new-generic-fun-arg';
const argument = {
type: type_1.RType.Argument,
lexeme: 'fun',
location: r,
info: {
id: argId,
nesting: name.info.nesting,
role: "call-arg" /* RoleInParent.FunctionCallArgument */,
fullRange: r,
adToks: undefined,
file: name.info.file,
parent: rootId,
index: args + 1
},
name: argName,
value: argValue
};
idMap.set(argument.info.id, argument);
return [argument, argValue.info.id];
}
//# sourceMappingURL=built-in-s-seven-new-generic.js.map