UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

124 lines 5.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.processS3Dispatch = processS3Dispatch; const processor_1 = require("../../../../../processor"); const info_1 = require("../../../../../info"); 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 alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking"); const r_value_1 = require("../../../../../eval/values/r-value"); const identifier_1 = require("../../../../../environments/identifier"); const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type"); const range_1 = require("../../../../../../util/range"); const r_argument_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-argument"); const built_in_proc_name_1 = require("../../../../../environments/built-in-proc-name"); /** * Process an S3 dispatch call like `UseMethod`. */ function processS3Dispatch(name, args, rootId, data, config) { if (args.length === 0 && !config.inferFromClosure) { logger_1.dataflowLogger.warn('empty s3, skipping'); return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information; } const params = { [config.args.generic]: 'generic', [config.args.object]: 'object', '...': '...' }; const argMaps = (0, linker_1.pMatch)((0, common_1.convertFnArguments)(args), params); const generic = (0, unpack_argument_1.unpackArg)(r_argument_1.RArgument.getWithId(args, argMaps.get('generic')?.[0])); if (!generic && !config.inferFromClosure) { return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information; } const obj = (0, unpack_argument_1.unpackArg)(r_argument_1.RArgument.getWithId(args, argMaps.get('object')?.[0])); const dfObj = obj ? (0, processor_1.processDataflowFor)(obj, data) : info_1.DataflowInformation.initialize(rootId, data); if ((0, info_1.alwaysExits)(dfObj)) { (0, common_1.patchFunctionCall)({ nextGraph: dfObj.graph, rootId, name, data, argumentProcessResult: [dfObj], origin: built_in_proc_name_1.BuiltInProcName.S3Dispatch }); return dfObj; } if (!generic) { (0, common_1.patchFunctionCall)({ nextGraph: dfObj.graph, rootId, name, data, argumentProcessResult: [dfObj], origin: built_in_proc_name_1.BuiltInProcName.S3DispatchNext }); const ingoing = dfObj.in.concat(dfObj.unknownReferences); ingoing.push({ nodeId: rootId, name: name.content, cds: data.cds, type: identifier_1.ReferenceType.Function }); return { hooks: dfObj.hooks, environment: dfObj.environment, exitPoints: dfObj.exitPoints, graph: dfObj.graph, entryPoint: rootId, in: ingoing, out: dfObj.out, unknownReferences: [] }; } const n = (0, alias_tracking_1.resolveIdToValue)(generic.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('s3 dispatch with non-resolvable generic, skipping'); return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information; } const dfGeneric = (0, processor_1.processDataflowFor)(generic, data); const symbol = { type: type_1.RType.Symbol, info: generic.info, content: accessedIdentifiers[0], lexeme: accessedIdentifiers[0], location: generic.location ?? range_1.SourceRange.invalid() }; (0, common_1.patchFunctionCall)({ nextGraph: dfGeneric.graph, rootId: generic.info.id, name: symbol, data, argumentProcessResult: [], // arguments will be attached by the accompanying enveloping function definition origin: built_in_proc_name_1.BuiltInProcName.S3Dispatch }); (0, common_1.patchFunctionCall)({ nextGraph: dfGeneric.graph, rootId, name, data, argumentProcessResult: [dfGeneric, dfObj], origin: built_in_proc_name_1.BuiltInProcName.Function }); const ingoing = dfObj.in.concat(dfGeneric.in, dfObj.unknownReferences, dfGeneric.unknownReferences); ingoing.push({ nodeId: rootId, name: name.content, cds: data.cds, type: identifier_1.ReferenceType.Function }); for (const id of accessedIdentifiers) { ingoing.push({ nodeId: generic.info.id, name: id, cds: data.cds, type: identifier_1.ReferenceType.S3MethodPrefix }); } return { hooks: dfGeneric.hooks.concat(dfObj?.hooks), environment: dfGeneric.environment, exitPoints: dfObj.exitPoints.concat(dfGeneric.exitPoints), graph: dfObj.graph.mergeWith(dfGeneric.graph), entryPoint: rootId, in: ingoing, out: dfGeneric.out.concat(dfObj.out), unknownReferences: [] }; } //# sourceMappingURL=built-in-s-three-dispatch.js.map