@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
256 lines • 15 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BuiltIns = exports.BuiltInEvalHandlerMapper = exports.BuiltInProcessorMapper = void 0;
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 r_symbol_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-symbol");
const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id");
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 unknown_side_effect_1 = require("../graph/unknown-side-effect");
const resolve_1 = require("../eval/resolve/resolve");
const built_in_stop_if_not_1 = require("../internal/process/functions/call/built-in/built-in-stop-if-not");
const built_in_try_catch_1 = require("../internal/process/functions/call/built-in/built-in-try-catch");
const built_in_register_hook_1 = require("../internal/process/functions/call/built-in/built-in-register-hook");
const built_in_local_1 = require("../internal/process/functions/call/built-in/built-in-local");
const built_in_s_three_dispatch_1 = require("../internal/process/functions/call/built-in/built-in-s-three-dispatch");
const built_in_recall_1 = require("../internal/process/functions/call/built-in/built-in-recall");
const built_in_s_seven_new_generic_1 = require("../internal/process/functions/call/built-in/built-in-s-seven-new-generic");
const built_in_s_seven_dispatch_1 = require("../internal/process/functions/call/built-in/built-in-s-seven-dispatch");
const r_string_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-string");
const built_in_proc_name_1 = require("./built-in-proc-name");
function defaultBuiltInProcessor(name, args, rootId, data, { returnsNthArgument, useAsProcessor = built_in_proc_name_1.BuiltInProcName.Default, forceArgs, readAllArguments, cfg, hasUnknownSideEffects, treatAsFnCall }) {
const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs, origin: useAsProcessor });
if (returnsNthArgument !== undefined) {
const arg = returnsNthArgument === 'last' ? processedArguments.at(-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);
}
else {
(0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId, hasUnknownSideEffects);
}
}
const fnCallNames = treatAsFnCall?.[identifier_1.Identifier.getName(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 (r_string_1.RString.is(rhs)) {
fnName = rhs.content.str;
fnId = rhs.info.id;
}
else if (r_symbol_1.RSymbol.is(rhs)) {
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.cds,
origin: [useAsProcessor]
});
}
}
}
if (cfg !== undefined) {
res.exitPoints.push({ type: cfg, nodeId: rootId, cds: data.cds });
}
return res;
}
function defaultBuiltInProcessorReadallArgs(name, args, rootId, data, { useAsProcessor = built_in_proc_name_1.BuiltInProcName.Default, forceArgs }) {
const { information, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs, origin: useAsProcessor });
const g = information.graph;
for (const arg of processedArguments) {
if (arg) {
g.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Reads);
}
}
return information;
}
exports.BuiltInProcessorMapper = {
[built_in_proc_name_1.BuiltInProcName.Access]: built_in_access_1.processAccess,
[built_in_proc_name_1.BuiltInProcName.Apply]: built_in_apply_1.processApply,
[built_in_proc_name_1.BuiltInProcName.Assignment]: built_in_assignment_1.processAssignment,
[built_in_proc_name_1.BuiltInProcName.AssignmentLike]: built_in_assignment_1.processAssignmentLike,
[built_in_proc_name_1.BuiltInProcName.Default]: defaultBuiltInProcessor,
[built_in_proc_name_1.BuiltInProcName.DefaultReadAllArgs]: defaultBuiltInProcessorReadallArgs,
[built_in_proc_name_1.BuiltInProcName.Eval]: built_in_eval_1.processEvalCall,
[built_in_proc_name_1.BuiltInProcName.ExpressionList]: built_in_expression_list_1.processExpressionList,
[built_in_proc_name_1.BuiltInProcName.ForLoop]: built_in_for_loop_1.processForLoop,
[built_in_proc_name_1.BuiltInProcName.FunctionDefinition]: built_in_function_definition_1.processFunctionDefinition,
[built_in_proc_name_1.BuiltInProcName.Get]: built_in_get_1.processGet,
[built_in_proc_name_1.BuiltInProcName.IfThenElse]: built_in_if_then_else_1.processIfThenElse,
[built_in_proc_name_1.BuiltInProcName.Library]: built_in_library_1.processLibrary,
[built_in_proc_name_1.BuiltInProcName.List]: built_in_list_1.processList,
[built_in_proc_name_1.BuiltInProcName.Local]: built_in_local_1.processLocal,
[built_in_proc_name_1.BuiltInProcName.Pipe]: built_in_pipe_1.processPipe,
[built_in_proc_name_1.BuiltInProcName.Quote]: built_in_quote_1.processQuote,
[built_in_proc_name_1.BuiltInProcName.Recall]: built_in_recall_1.processRecall,
[built_in_proc_name_1.BuiltInProcName.RegisterHook]: built_in_register_hook_1.processRegisterHook,
[built_in_proc_name_1.BuiltInProcName.RepeatLoop]: built_in_repeat_loop_1.processRepeatLoop,
[built_in_proc_name_1.BuiltInProcName.Replacement]: built_in_replacement_1.processReplacementFunction,
[built_in_proc_name_1.BuiltInProcName.Rm]: built_in_rm_1.processRm,
[built_in_proc_name_1.BuiltInProcName.S3Dispatch]: built_in_s_three_dispatch_1.processS3Dispatch,
[built_in_proc_name_1.BuiltInProcName.S7NewGeneric]: built_in_s_seven_new_generic_1.processS7NewGeneric,
[built_in_proc_name_1.BuiltInProcName.S7Dispatch]: built_in_s_seven_dispatch_1.processS7Dispatch,
[built_in_proc_name_1.BuiltInProcName.Source]: built_in_source_1.processSourceCall,
[built_in_proc_name_1.BuiltInProcName.SpecialBinOp]: built_in_special_bin_op_1.processSpecialBinOp,
[built_in_proc_name_1.BuiltInProcName.StopIfNot]: built_in_stop_if_not_1.processStopIfNot,
[built_in_proc_name_1.BuiltInProcName.Try]: built_in_try_catch_1.processTryCatch,
[built_in_proc_name_1.BuiltInProcName.Vector]: built_in_vector_1.processVector,
[built_in_proc_name_1.BuiltInProcName.WhileLoop]: built_in_while_loop_1.processWhileLoop,
};
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 n = identifier_1.Identifier.getName(name);
const id = node_id_1.NodeId.toBuiltIn(n);
const d = [{
type: identifier_1.ReferenceType.BuiltInConstant,
definedAt: id,
cds: undefined,
value,
name,
nodeId: id
}];
this.set(n, d, assumePrimitive);
}
}
/**
* Register a built-in function (like `print` or `c`) to the given {@link BuiltIns}
*/
registerBuiltInFunctions({ names, processor, config, assumePrimitive }) {
(0, assert_1.guard)(processor !== undefined, () => `Processor for ${JSON.stringify(names)} is undefined, maybe you have an import loop? You may run 'npm run detect-circular-deps' - although by far not all are bad`);
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) {
const n = identifier_1.Identifier.getName(name);
const id = node_id_1.NodeId.toBuiltIn(n);
const d = [{
type: identifier_1.ReferenceType.BuiltInFunction,
definedAt: id,
cds: 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(n, d, assumePrimitive);
}
}
/**
* Registers all combinations of replacements
*/
registerReplacementFunctions({ names, suffixes, assumePrimitive, config }) {
const replacer = exports.BuiltInProcessorMapper[built_in_proc_name_1.BuiltInProcName.Replacement];
(0, assert_1.guard)(replacer !== undefined, () => `Processor for ${built_in_proc_name_1.BuiltInProcName.Replacement} is undefined!`);
for (const assignment of names) {
for (const suffix of suffixes) {
const effectiveName = `${identifier_1.Identifier.getName(assignment)}${suffix}`;
const id = node_id_1.NodeId.toBuiltIn(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: assignment,
cds: 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