UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

210 lines 8.52 kB
"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