UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

233 lines 11.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BuiltIns = exports.BuiltInEvalHandlerMapper = exports.BuiltInProcessorMapper = void 0; exports.builtInId = builtInId; exports.isBuiltIn = isBuiltIn; const known_call_handling_1 = require("../internal/process/functions/call/known-call-handling"); const built_in_access_1 = require("../internal/process/functions/call/built-in/built-in-access"); const built_in_if_then_else_1 = require("../internal/process/functions/call/built-in/built-in-if-then-else"); const built_in_assignment_1 = require("../internal/process/functions/call/built-in/built-in-assignment"); const built_in_special_bin_op_1 = require("../internal/process/functions/call/built-in/built-in-special-bin-op"); const built_in_pipe_1 = require("../internal/process/functions/call/built-in/built-in-pipe"); const built_in_for_loop_1 = require("../internal/process/functions/call/built-in/built-in-for-loop"); const built_in_repeat_loop_1 = require("../internal/process/functions/call/built-in/built-in-repeat-loop"); const built_in_while_loop_1 = require("../internal/process/functions/call/built-in/built-in-while-loop"); const identifier_1 = require("./identifier"); const assert_1 = require("../../util/assert"); const built_in_replacement_1 = require("../internal/process/functions/call/built-in/built-in-replacement"); const built_in_quote_1 = require("../internal/process/functions/call/built-in/built-in-quote"); const built_in_function_definition_1 = require("../internal/process/functions/call/built-in/built-in-function-definition"); const built_in_expression_list_1 = require("../internal/process/functions/call/built-in/built-in-expression-list"); const built_in_get_1 = require("../internal/process/functions/call/built-in/built-in-get"); const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call"); const edge_1 = require("../graph/edge"); const built_in_library_1 = require("../internal/process/functions/call/built-in/built-in-library"); const built_in_source_1 = require("../internal/process/functions/call/built-in/built-in-source"); const built_in_apply_1 = require("../internal/process/functions/call/built-in/built-in-apply"); const built_in_list_1 = require("../internal/process/functions/call/built-in/built-in-list"); const built_in_vector_1 = require("../internal/process/functions/call/built-in/built-in-vector"); const built_in_rm_1 = require("../internal/process/functions/call/built-in/built-in-rm"); const built_in_eval_1 = require("../internal/process/functions/call/built-in/built-in-eval"); const vertex_1 = require("../graph/vertex"); const type_1 = require("../../r-bridge/lang-4.x/ast/model/type"); const unknown_side_effect_1 = require("../graph/unknown-side-effect"); const resolve_1 = require("../eval/resolve/resolve"); function builtInId(name) { return `built-in:${name}`; } function isBuiltIn(name) { return String(name).startsWith('built-in:'); } function defaultBuiltInProcessor(name, args, rootId, data, { returnsNthArgument, useAsProcessor, forceArgs, readAllArguments, cfg, hasUnknownSideEffects, treatAsFnCall }) { const activeProcessor = useAsProcessor ?? 'builtin:default'; const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs, origin: activeProcessor }); if (returnsNthArgument !== undefined) { const arg = returnsNthArgument === 'last' ? processedArguments[args.length - 1] : processedArguments[returnsNthArgument]; if (arg !== undefined) { res.graph.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Returns); } } if (readAllArguments) { for (const arg of processedArguments) { if (arg) { res.graph.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Reads); } } } if (hasUnknownSideEffects) { if (typeof hasUnknownSideEffects !== 'boolean') { (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId, hasUnknownSideEffects); } else { (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId); } } const fnCallNames = treatAsFnCall?.[name.content]; if (fnCallNames) { for (const arg of args) { if (arg !== r_function_call_1.EmptyArgument && arg.value && fnCallNames.includes(arg.name?.content)) { const rhs = arg.value; let fnName; let fnId; if (rhs.type === type_1.RType.String) { fnName = rhs.content.str; fnId = rhs.info.id; } else if (rhs.type === type_1.RType.Symbol) { fnName = rhs.content; fnId = rhs.info.id; } else { continue; } res.graph.updateToFunctionCall({ tag: vertex_1.VertexType.FunctionCall, id: fnId, name: fnName, args: [], environment: data.environment, onlyBuiltin: false, cds: data.controlDependencies, origin: [activeProcessor] }); } } } if (cfg !== undefined) { res.exitPoints.push({ type: cfg, nodeId: rootId, controlDependencies: data.controlDependencies }); } return res; } exports.BuiltInProcessorMapper = { 'builtin:default': defaultBuiltInProcessor, 'builtin:eval': built_in_eval_1.processEvalCall, 'builtin:apply': built_in_apply_1.processApply, 'builtin:expression-list': built_in_expression_list_1.processExpressionList, 'builtin:source': built_in_source_1.processSourceCall, 'builtin:access': built_in_access_1.processAccess, 'builtin:if-then-else': built_in_if_then_else_1.processIfThenElse, 'builtin:get': built_in_get_1.processGet, 'builtin:rm': built_in_rm_1.processRm, 'builtin:library': built_in_library_1.processLibrary, 'builtin:assignment': built_in_assignment_1.processAssignment, 'builtin:special-bin-op': built_in_special_bin_op_1.processSpecialBinOp, 'builtin:pipe': built_in_pipe_1.processPipe, 'builtin:function-definition': built_in_function_definition_1.processFunctionDefinition, 'builtin:quote': built_in_quote_1.processQuote, 'builtin:for-loop': built_in_for_loop_1.processForLoop, 'builtin:repeat-loop': built_in_repeat_loop_1.processRepeatLoop, 'builtin:while-loop': built_in_while_loop_1.processWhileLoop, 'builtin:replacement': built_in_replacement_1.processReplacementFunction, 'builtin:list': built_in_list_1.processList, 'builtin:vector': built_in_vector_1.processVector, }; exports.BuiltInEvalHandlerMapper = { 'built-in:c': resolve_1.resolveAsVector, 'built-in::': resolve_1.resolveAsSeq, 'built-in:+': resolve_1.resolveAsPlus, 'built-in:-': resolve_1.resolveAsMinus }; class BuiltIns { /** * Register a built-in constant (like `NULL` or `TRUE`) to the given {@link builtIns} */ registerBuiltInConstant({ names, value, assumePrimitive }) { for (const name of names) { const id = builtInId(name); const d = [{ type: identifier_1.ReferenceType.BuiltInConstant, definedAt: id, controlDependencies: undefined, value, name, nodeId: id }]; this.set(name, d, assumePrimitive); } } /** * Register a built-in function (like `print` or `c`) to the given {@link builtIns} */ registerBuiltInFunctions({ names, processor, config, assumePrimitive }) { const mappedProcessor = exports.BuiltInProcessorMapper[processor]; (0, assert_1.guard)(mappedProcessor !== undefined, () => `Processor for ${processor} is undefined! Please pass a valid builtin name ${JSON.stringify(Object.keys(exports.BuiltInProcessorMapper))}!`); for (const name of names) { (0, assert_1.guard)(processor !== undefined, `Processor for ${name} is undefined, maybe you have an import loop? You may run 'npm run detect-circular-deps' - although by far not all are bad`); const id = builtInId(name); const d = [{ type: identifier_1.ReferenceType.BuiltInFunction, definedAt: id, controlDependencies: undefined, /* eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-argument */ processor: (name, args, rootId, data) => mappedProcessor(name, args, rootId, data, config), config, name, nodeId: id }]; this.set(name, d, assumePrimitive); } } /** * Registers all combinations of replacements */ registerReplacementFunctions({ names, suffixes, assumePrimitive, config }) { const replacer = exports.BuiltInProcessorMapper['builtin:replacement']; (0, assert_1.guard)(replacer !== undefined, () => 'Processor for builtin:replacement is undefined!'); for (const assignment of names) { for (const suffix of suffixes) { const effectiveName = `${assignment}${suffix}`; const id = builtInId(effectiveName); const d = [{ type: identifier_1.ReferenceType.BuiltInFunction, definedAt: id, processor: (name, args, rootId, data) => replacer(name, args, rootId, data, { makeMaybe: true, assignmentOperator: suffix, readIndices: config.readIndices }), config: { ...config, assignmentOperator: suffix, makeMaybe: true }, name: effectiveName, controlDependencies: undefined, nodeId: id }]; this.set(effectiveName, d, assumePrimitive); } } } /** * Register a single {@link BuiltInDefinition} to the given memories in {@link builtIns} */ registerBuiltInDefinition(definition) { switch (definition.type) { case 'constant': return this.registerBuiltInConstant(definition); case 'function': return this.registerBuiltInFunctions(definition); case 'replacement': return this.registerReplacementFunctions(definition); } } /** * The built-in {@link REnvironmentInformation|environment} is the root of all environments. * * For its default content (when not overwritten by a flowR config), * see the {@link DefaultBuiltinConfig}. */ builtInMemory = new Map(); /** * The twin of the {@link builtInMemory} but with less built ins defined for * cases in which we want some commonly overwritten variables to remain open. * If you do not know if you need the empty environment, you do not need the empty environment (right now). * * @see {@link builtInMemory} */ emptyBuiltInMemory = new Map(); set(identifier, definition, includeInEmptyMemory) { this.builtInMemory.set(identifier, definition); if (includeInEmptyMemory) { this.emptyBuiltInMemory.set(identifier, definition); } } } exports.BuiltIns = BuiltIns; //# sourceMappingURL=built-in.js.map