@eagleoutice/flowr 2.2.10 → 2.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/benchmark/slicer.d.ts +49 -22
- package/benchmark/slicer.js +88 -28
- package/benchmark/stats/print.js +16 -10
- package/benchmark/stats/size-of.js +18 -1
- package/benchmark/stats/stats.d.ts +3 -0
- package/benchmark/summarizer/second-phase/process.js +8 -2
- package/cli/benchmark-app.d.ts +5 -0
- package/cli/benchmark-app.js +49 -6
- package/cli/benchmark-helper-app.d.ts +4 -0
- package/cli/benchmark-helper-app.js +20 -4
- package/cli/common/options.js +13 -4
- package/cli/repl/commands/repl-commands.js +2 -0
- package/cli/repl/commands/repl-dataflow.d.ts +2 -0
- package/cli/repl/commands/repl-dataflow.js +35 -1
- package/cli/repl/server/compact.d.ts +2 -2
- package/cli/repl/server/compact.js +3 -3
- package/cli/repl/server/messages/message-analysis.d.ts +2 -2
- package/cli/repl/server/messages/message-analysis.js +2 -2
- package/config.d.ts +27 -2
- package/config.js +30 -4
- package/dataflow/environments/built-in-config.d.ts +5 -2
- package/dataflow/environments/built-in-config.js +8 -2
- package/dataflow/environments/built-in.d.ts +8 -1
- package/dataflow/environments/built-in.js +8 -1
- package/dataflow/environments/clone.d.ts +5 -0
- package/dataflow/environments/clone.js +5 -0
- package/dataflow/environments/default-builtin-config.js +96 -10
- package/dataflow/environments/define.d.ts +5 -1
- package/dataflow/environments/define.js +36 -10
- package/dataflow/environments/environment.js +4 -2
- package/dataflow/environments/overwrite.js +4 -0
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +24 -0
- package/dataflow/environments/resolve-by-name.js +1 -1
- package/dataflow/extractor.d.ts +1 -1
- package/dataflow/extractor.js +8 -6
- package/dataflow/graph/dataflowgraph-builder.d.ts +76 -6
- package/dataflow/graph/dataflowgraph-builder.js +102 -6
- package/dataflow/graph/edge.js +4 -1
- package/dataflow/graph/graph.d.ts +12 -1
- package/dataflow/graph/graph.js +37 -0
- package/dataflow/graph/vertex.d.ts +42 -2
- package/dataflow/graph/vertex.js +32 -0
- package/dataflow/internal/linker.js +3 -1
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +3 -0
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +4 -10
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +55 -45
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +6 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +27 -8
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +37 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +10 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +140 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +21 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +3 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +83 -29
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +7 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +41 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +20 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +15 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +75 -0
- package/dataflow/internal/process/functions/call/common.d.ts +1 -1
- package/dataflow/internal/process/functions/call/common.js +4 -2
- package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -0
- package/dataflow/internal/process/functions/call/named-call-handling.js +9 -5
- package/dataflow/internal/process/process-named-call.d.ts +3 -0
- package/dataflow/internal/process/process-named-call.js +3 -0
- package/dataflow/processor.d.ts +7 -7
- package/documentation/data/server/doc-data-server-messages.js +2 -2
- package/documentation/doc-util/doc-cfg.d.ts +11 -2
- package/documentation/doc-util/doc-cfg.js +35 -6
- package/documentation/doc-util/doc-code.js +10 -2
- package/documentation/print-capabilities-markdown.js +1 -1
- package/documentation/print-cfg-wiki.d.ts +1 -0
- package/documentation/print-cfg-wiki.js +84 -0
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-interface-wiki.js +4 -0
- package/documentation/print-query-wiki.js +22 -3
- package/package.json +4 -3
- package/queries/catalog/call-context-query/call-context-query-executor.js +13 -0
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +4 -0
- package/queries/catalog/call-context-query/call-context-query-format.js +1 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +13 -5
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -25
- package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -145
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +24 -0
- package/queries/catalog/dependencies-query/function-info/function-info.js +10 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.js +18 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.js +101 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.js +11 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +87 -0
- package/queries/catalog/location-map-query/location-map-query-executor.d.ts +1 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +38 -3
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +10 -1
- package/queries/catalog/location-map-query/location-map-query-format.js +5 -1
- package/queries/catalog/project-query/project-query-executor.d.ts +3 -0
- package/queries/catalog/project-query/project-query-executor.js +17 -0
- package/queries/catalog/project-query/project-query-format.d.ts +67 -0
- package/queries/catalog/project-query/project-query-format.js +26 -0
- package/queries/query.d.ts +60 -1
- package/queries/query.js +3 -1
- package/r-bridge/data/data.d.ts +2 -2
- package/r-bridge/data/data.js +2 -2
- package/slicing/static/fingerprint.js +8 -1
- package/slicing/static/slice-call.d.ts +1 -1
- package/slicing/static/slice-call.js +5 -16
- package/slicing/static/slicer-types.d.ts +2 -0
- package/slicing/static/static-slicer.d.ts +4 -2
- package/slicing/static/static-slicer.js +24 -18
- package/slicing/static/visiting-queue.d.ts +7 -1
- package/slicing/static/visiting-queue.js +20 -6
- package/util/arrays.d.ts +23 -0
- package/util/arrays.js +41 -0
- package/util/cfg/visitor.d.ts +1 -1
- package/util/cfg/visitor.js +2 -2
- package/util/{list-access.d.ts → containers.d.ts} +24 -4
- package/util/{list-access.js → containers.js} +42 -12
- package/util/mermaid/ast.js +12 -1
- package/util/mermaid/cfg.js +2 -2
- package/util/parallel.d.ts +2 -1
- package/util/parallel.js +11 -2
- package/util/prefix.d.ts +13 -0
- package/util/prefix.js +34 -0
- package/util/version.js +1 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processEvalCall = processEvalCall;
|
|
4
|
+
const info_1 = require("../../../../../info");
|
|
5
|
+
const config_1 = require("../../../../../../config");
|
|
6
|
+
const known_call_handling_1 = require("../known-call-handling");
|
|
7
|
+
const retriever_1 = require("../../../../../../r-bridge/retriever");
|
|
8
|
+
const decorate_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate");
|
|
9
|
+
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
10
|
+
const logger_1 = require("../../../../../logger");
|
|
11
|
+
const log_1 = require("../../../../../../util/log");
|
|
12
|
+
const built_in_source_1 = require("./built-in-source");
|
|
13
|
+
const edge_1 = require("../../../../../graph/edge");
|
|
14
|
+
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
15
|
+
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
16
|
+
const append_1 = require("../../../../../environments/append");
|
|
17
|
+
const assert_1 = require("../../../../../../util/assert");
|
|
18
|
+
const arrays_1 = require("../../../../../../util/arrays");
|
|
19
|
+
function processEvalCall(name, args, rootId, data, config) {
|
|
20
|
+
if (args.length !== 1 || args[0] === r_function_call_1.EmptyArgument || !args[0].value) {
|
|
21
|
+
logger_1.dataflowLogger.warn(`Expected exactly one argument for eval currently, but got ${args.length} instead, skipping`);
|
|
22
|
+
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information;
|
|
23
|
+
}
|
|
24
|
+
const information = config.includeFunctionCall ?
|
|
25
|
+
(0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: [true] }).information
|
|
26
|
+
: (0, info_1.initializeCleanDataflowInformation)(rootId, data);
|
|
27
|
+
const evalArgument = args[0];
|
|
28
|
+
if (config.includeFunctionCall) {
|
|
29
|
+
information.graph.addEdge(rootId, args[0].value.info.id, edge_1.EdgeType.Returns);
|
|
30
|
+
}
|
|
31
|
+
if (!(0, config_1.getConfig)().solver.evalStrings) {
|
|
32
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping eval call ${JSON.stringify(evalArgument)} (disabled in config file)`);
|
|
33
|
+
information.graph.markIdForUnknownSideEffects(rootId);
|
|
34
|
+
return information;
|
|
35
|
+
}
|
|
36
|
+
const code = resolveEvalToCode(evalArgument.value, data.environment, data.completeAst.idMap);
|
|
37
|
+
if (code) {
|
|
38
|
+
const idGenerator = (0, decorate_1.sourcedDeterministicCountingIdGenerator)(name.lexeme + '::' + rootId, name.location);
|
|
39
|
+
data = {
|
|
40
|
+
...data,
|
|
41
|
+
controlDependencies: [...(data.controlDependencies ?? []), { id: rootId, when: true }]
|
|
42
|
+
};
|
|
43
|
+
const originalInfo = { ...information };
|
|
44
|
+
const result = [];
|
|
45
|
+
for (const c of code) {
|
|
46
|
+
const codeRequest = (0, retriever_1.requestFromInput)(c);
|
|
47
|
+
const r = (0, built_in_source_1.sourceRequest)(rootId, codeRequest, data, originalInfo, idGenerator);
|
|
48
|
+
result.push(r);
|
|
49
|
+
// add a returns edge from the eval to the result
|
|
50
|
+
for (const e of r.exitPoints) {
|
|
51
|
+
information.graph.addEdge(rootId, e, edge_1.EdgeType.Returns);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
graph: result.reduce((acc, r) => acc.mergeWith(r.graph), information.graph),
|
|
56
|
+
environment: result.reduce((acc, r) => (0, append_1.appendEnvironment)(acc, r.environment), information.environment),
|
|
57
|
+
entryPoint: rootId,
|
|
58
|
+
out: [...information.out, ...result.flatMap(r => r.out)],
|
|
59
|
+
in: [...information.in, ...result.flatMap(r => r.in)],
|
|
60
|
+
unknownReferences: [...information.unknownReferences, ...result.flatMap(r => r.unknownReferences)],
|
|
61
|
+
exitPoints: [...information.exitPoints, ...result.flatMap(r => r.exitPoints)],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(args)} for eval is currently not supported, skipping`);
|
|
65
|
+
information.graph.markIdForUnknownSideEffects(rootId);
|
|
66
|
+
return information;
|
|
67
|
+
}
|
|
68
|
+
function resolveEvalToCode(evalArgument, env, idMap) {
|
|
69
|
+
const val = evalArgument;
|
|
70
|
+
if (val.type === type_1.RType.FunctionCall && val.named && val.functionName.content === 'parse') {
|
|
71
|
+
const arg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'text');
|
|
72
|
+
const nArg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'n');
|
|
73
|
+
if (nArg !== undefined || arg === undefined || arg === r_function_call_1.EmptyArgument) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
if (arg.value?.type === type_1.RType.String) {
|
|
77
|
+
return [arg.value.content.str];
|
|
78
|
+
}
|
|
79
|
+
else if (arg.value?.type === type_1.RType.Symbol) {
|
|
80
|
+
const resolve = (0, resolve_by_name_1.resolveValueOfVariable)(arg.value.content, env, idMap);
|
|
81
|
+
if (resolve && resolve.every(r => typeof r === 'object' && r !== null && 'str' in r)) {
|
|
82
|
+
return resolve.map(r => r.str);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (arg.value?.type === type_1.RType.FunctionCall && arg.value.named && ['paste', 'paste0'].includes(arg.value.functionName.content)) {
|
|
86
|
+
return handlePaste(arg.value.arguments, env, idMap, arg.value.functionName.content === 'paste' ? [' '] : ['']);
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
else if (val.type === type_1.RType.Symbol) {
|
|
91
|
+
// const resolved = resolveValueOfVariable(val.content, env);
|
|
92
|
+
// see https://github.com/flowr-analysis/flowr/pull/1467
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function getAsString(val, env, idMap) {
|
|
100
|
+
if (!val) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
if (val.type === type_1.RType.String) {
|
|
104
|
+
return [val.content.str];
|
|
105
|
+
}
|
|
106
|
+
else if (val.type === type_1.RType.Symbol) {
|
|
107
|
+
const resolved = (0, resolve_by_name_1.resolveValueOfVariable)(val.content, env, idMap);
|
|
108
|
+
if (resolved && resolved.every(r => typeof r === 'object' && r !== null && 'str' in r)) {
|
|
109
|
+
return resolved.map(r => r.str);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
function handlePaste(args, env, idMap, sepDefault) {
|
|
115
|
+
const sepArg = args.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'sep');
|
|
116
|
+
if (sepArg) {
|
|
117
|
+
const res = sepArg !== r_function_call_1.EmptyArgument && sepArg.value ? getAsString(sepArg.value, env, idMap) : undefined;
|
|
118
|
+
if (!res) {
|
|
119
|
+
// sep not resolvable clearly / unknown
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
sepDefault = res;
|
|
123
|
+
}
|
|
124
|
+
const allArgs = args
|
|
125
|
+
.filter(v => v !== r_function_call_1.EmptyArgument && v.name?.content !== 'sep' && v.value)
|
|
126
|
+
.map(v => getAsString(v.value, env, idMap));
|
|
127
|
+
if (allArgs.some(assert_1.isUndefined)) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
// return all cartesian products using the separator
|
|
131
|
+
const result = [];
|
|
132
|
+
const cartesianProducts = (0, arrays_1.cartesianProduct)(...allArgs);
|
|
133
|
+
for (const sep of sepDefault) {
|
|
134
|
+
for (const c of cartesianProducts) {
|
|
135
|
+
result.push(c.join(sep));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=built-in-eval.js.map
|
|
@@ -17,6 +17,7 @@ const scoping_1 = require("../../../../../environments/scoping");
|
|
|
17
17
|
const built_in_1 = require("../../../../../environments/built-in");
|
|
18
18
|
const overwrite_1 = require("../../../../../environments/overwrite");
|
|
19
19
|
const logger_1 = require("../../../../../logger");
|
|
20
|
+
const log_1 = require("../../../../../../util/log");
|
|
20
21
|
const dotDotDotAccess = /^\.\.\d+$/;
|
|
21
22
|
function linkReadNameToWriteIfPossible(read, environments, listEnvironments, remainingRead, nextGraph) {
|
|
22
23
|
const readName = read.name && dotDotDotAccess.test(read.name) ? '...' : read.name;
|
|
@@ -83,7 +84,7 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
|
|
|
83
84
|
}
|
|
84
85
|
function processExpressionList(name, args, rootId, data) {
|
|
85
86
|
const expressions = args.map(e => (0, unpack_argument_1.unpackArgument)(e));
|
|
86
|
-
logger_1.dataflowLogger
|
|
87
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `[expr list] with ${expressions.length} expressions`);
|
|
87
88
|
let { environment } = data;
|
|
88
89
|
// used to detect if a "write" happens within the same expression list
|
|
89
90
|
const listEnvironments = new Set();
|
|
@@ -95,7 +96,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
95
96
|
const processedExpressions = [];
|
|
96
97
|
let defaultReturnExpr = undefined;
|
|
97
98
|
for (const expression of expressions) {
|
|
98
|
-
logger_1.dataflowLogger
|
|
99
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `processing expression ${++expressionCounter} of ${expressions.length}`);
|
|
99
100
|
if (expression === undefined) {
|
|
100
101
|
processedExpressions.push(undefined);
|
|
101
102
|
continue;
|
|
@@ -115,7 +116,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
115
116
|
}
|
|
116
117
|
(0, info_1.addNonDefaultExitPoints)(exitPoints, processed.exitPoints);
|
|
117
118
|
out.push(...processed.out);
|
|
118
|
-
logger_1.dataflowLogger
|
|
119
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `expression ${expressionCounter} of ${expressions.length} has ${processed.unknownReferences.length} unknown nodes`);
|
|
119
120
|
processNextExpression(processed, environment, listEnvironments, remainingRead, nextGraph);
|
|
120
121
|
environment = exitPoints.length > 0 ? (0, overwrite_1.overwriteEnvironment)(environment, processed.environment) : processed.environment;
|
|
121
122
|
const calledEnvs = (0, linker_1.linkFunctionCalls)(nextGraph, data.completeAst.idMap, processed.graph);
|
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.processList = processList;
|
|
4
4
|
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
5
5
|
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
6
|
-
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
7
6
|
const known_call_handling_1 = require("../known-call-handling");
|
|
8
7
|
const config_1 = require("../../../../../../config");
|
|
8
|
+
const containers_1 = require("../../../../../../util/containers");
|
|
9
9
|
/**
|
|
10
10
|
* Process a list call.
|
|
11
11
|
*
|
|
@@ -15,36 +15,70 @@ const config_1 = require("../../../../../../config");
|
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
17
|
function processList(name, args, rootId, data) {
|
|
18
|
+
const fnCall = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data });
|
|
18
19
|
if (!(0, config_1.getConfig)().solver.pointerTracking) {
|
|
19
|
-
return
|
|
20
|
+
return fnCall.information;
|
|
20
21
|
}
|
|
21
|
-
const
|
|
22
|
+
const listArgs = [];
|
|
22
23
|
for (const arg of args) {
|
|
23
24
|
// Skip non named arguments
|
|
24
|
-
if (arg === r_function_call_1.EmptyArgument || arg.type !== type_1.RType.Argument || arg.
|
|
25
|
+
if (arg === r_function_call_1.EmptyArgument || arg.type !== type_1.RType.Argument || arg.value === undefined) {
|
|
25
26
|
continue;
|
|
26
27
|
}
|
|
27
|
-
let newIndex
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
let newIndex;
|
|
29
|
+
if (arg.name) {
|
|
30
|
+
// Named argument
|
|
31
|
+
newIndex = {
|
|
32
|
+
identifier: {
|
|
33
|
+
index: arg.info.index,
|
|
34
|
+
lexeme: arg.name.content
|
|
35
|
+
},
|
|
36
|
+
nodeId: arg.info.id,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Unnamed argument
|
|
41
|
+
newIndex = {
|
|
42
|
+
identifier: {
|
|
43
|
+
index: arg.info.index,
|
|
44
|
+
},
|
|
45
|
+
nodeId: arg.value.info.id,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// Check whether argument value can be resolved
|
|
49
|
+
if (arg.value.type === type_1.RType.Symbol) {
|
|
50
|
+
const indicesCollection = (0, containers_1.resolveIndicesByName)(arg.value.lexeme, data.environment);
|
|
51
|
+
if (indicesCollection) {
|
|
36
52
|
newIndex = {
|
|
37
53
|
...newIndex,
|
|
38
|
-
subIndices:
|
|
54
|
+
subIndices: indicesCollection,
|
|
39
55
|
};
|
|
40
56
|
}
|
|
41
57
|
}
|
|
42
|
-
|
|
58
|
+
else {
|
|
59
|
+
// Check whether argument is nested container
|
|
60
|
+
const indicesCollection = fnCall.information.graph.getVertex(arg.value.info.id)?.indicesCollection;
|
|
61
|
+
if (indicesCollection) {
|
|
62
|
+
newIndex = {
|
|
63
|
+
...newIndex,
|
|
64
|
+
subIndices: indicesCollection,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
listArgs.push(newIndex);
|
|
69
|
+
}
|
|
70
|
+
if ((0, config_1.isOverPointerAnalysisThreshold)(listArgs.length)) {
|
|
71
|
+
return fnCall.information;
|
|
43
72
|
}
|
|
44
73
|
const indices = {
|
|
45
|
-
indices:
|
|
74
|
+
indices: listArgs,
|
|
46
75
|
isContainer: true,
|
|
47
76
|
};
|
|
48
|
-
|
|
77
|
+
// Add resolved indices to vertex
|
|
78
|
+
const vertex = fnCall.information.graph.getVertex(rootId);
|
|
79
|
+
if (vertex) {
|
|
80
|
+
vertex.indicesCollection = [indices];
|
|
81
|
+
}
|
|
82
|
+
return fnCall.information;
|
|
49
83
|
}
|
|
50
84
|
//# sourceMappingURL=built-in-list.js.map
|
|
@@ -35,11 +35,29 @@ function processPipe(name, args, rootId, data) {
|
|
|
35
35
|
information.graph.addEdge(functionCallNode.id, argId, edge_1.EdgeType.Argument | edge_1.EdgeType.Reads);
|
|
36
36
|
}
|
|
37
37
|
const firstArgument = processedArguments[0];
|
|
38
|
+
const uniqueIn = [...information.in];
|
|
39
|
+
for (const ing of (firstArgument?.in ?? [])) {
|
|
40
|
+
if (!uniqueIn.find(e => e.nodeId === ing.nodeId)) {
|
|
41
|
+
uniqueIn.push(ing);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const uniqueOut = [...information.out];
|
|
45
|
+
for (const outg of (firstArgument?.out ?? [])) {
|
|
46
|
+
if (!uniqueOut.find(e => e.nodeId === outg.nodeId)) {
|
|
47
|
+
uniqueOut.push(outg);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const uniqueUnknownReferences = [...information.unknownReferences];
|
|
51
|
+
for (const unknown of (firstArgument?.unknownReferences ?? [])) {
|
|
52
|
+
if (!uniqueUnknownReferences.find(e => e.nodeId === unknown.nodeId)) {
|
|
53
|
+
uniqueUnknownReferences.push(unknown);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
38
56
|
return {
|
|
39
57
|
...information,
|
|
40
|
-
in:
|
|
41
|
-
out:
|
|
42
|
-
unknownReferences:
|
|
58
|
+
in: uniqueIn,
|
|
59
|
+
out: uniqueOut,
|
|
60
|
+
unknownReferences: uniqueUnknownReferences,
|
|
43
61
|
entryPoint: rootId
|
|
44
62
|
};
|
|
45
63
|
}
|
|
@@ -5,9 +5,12 @@ import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/
|
|
|
5
5
|
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
6
6
|
import { type RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
7
7
|
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
|
+
import type { ContainerIndicesCollection } from '../../../../../graph/vertex';
|
|
8
9
|
export declare function processReplacementFunction<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>,
|
|
9
10
|
/** The last one has to be the value */
|
|
10
11
|
args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
|
|
11
12
|
makeMaybe?: boolean;
|
|
12
13
|
assignmentOperator?: '<-' | '<<-';
|
|
14
|
+
readIndices?: boolean;
|
|
15
|
+
activeIndices?: ContainerIndicesCollection;
|
|
13
16
|
} & ForceArguments): DataflowInformation;
|
|
@@ -6,16 +6,15 @@ const known_call_handling_1 = require("../known-call-handling");
|
|
|
6
6
|
const log_1 = require("../../../../../../util/log");
|
|
7
7
|
const built_in_assignment_1 = require("./built-in-assignment");
|
|
8
8
|
const common_1 = require("../common");
|
|
9
|
-
const assert_1 = require("../../../../../../util/assert");
|
|
10
9
|
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
11
10
|
const logger_1 = require("../../../../../logger");
|
|
12
|
-
const vertex_1 = require("../../../../../graph/vertex");
|
|
13
11
|
const graph_1 = require("../../../../../graph/graph");
|
|
14
12
|
const edge_1 = require("../../../../../graph/edge");
|
|
15
|
-
const dfg_1 = require("../../../../../../util/mermaid/dfg");
|
|
16
13
|
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
17
|
-
const
|
|
14
|
+
const containers_1 = require("../../../../../../util/containers");
|
|
18
15
|
const config_1 = require("../../../../../../config");
|
|
16
|
+
const unpack_argument_1 = require("../argument/unpack-argument");
|
|
17
|
+
const built_in_access_1 = require("./built-in-access");
|
|
19
18
|
function processReplacementFunction(name,
|
|
20
19
|
/** The last one has to be the value */
|
|
21
20
|
args, rootId, data, config) {
|
|
@@ -25,45 +24,38 @@ args, rootId, data, config) {
|
|
|
25
24
|
}
|
|
26
25
|
/* we only get here if <-, <<-, ... or whatever is part of the replacement is not overwritten */
|
|
27
26
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Replacement ${name.content} with ${JSON.stringify(args)}, processing`);
|
|
28
|
-
let indices =
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
const accessedArg = nonEmptyArgs.find(arg => arg.info.role === "accessed" /* RoleInParent.Accessed */);
|
|
32
|
-
const accessArg = nonEmptyArgs.find(arg => arg.info.role === "index-access" /* RoleInParent.IndexAccess */);
|
|
33
|
-
if (accessArg !== undefined && accessedArg != undefined) {
|
|
34
|
-
const leafIndex = { lexeme: accessArg.lexeme, nodeId: accessedArg.info.parent ?? '' };
|
|
35
|
-
const accessIndices = {
|
|
36
|
-
indices: [leafIndex],
|
|
37
|
-
isContainer: false
|
|
38
|
-
};
|
|
39
|
-
// Check for nested access
|
|
40
|
-
if (accessedArg.value?.type === type_1.RType.Access) {
|
|
41
|
-
indices = (0, list_access_1.constructNestedAccess)(accessedArg.value, accessIndices);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// use access node as reference to get complete line in slice
|
|
45
|
-
indices = [accessIndices];
|
|
46
|
-
}
|
|
47
|
-
}
|
|
27
|
+
let indices = config.activeIndices;
|
|
28
|
+
if ((0, config_1.getConfig)().solver.pointerTracking) {
|
|
29
|
+
indices ??= constructAccessedIndices(name.content, args);
|
|
48
30
|
}
|
|
49
31
|
/* we assign the first argument by the last for now and maybe mark as maybe!, we can keep the symbol as we now know we have an assignment */
|
|
50
32
|
const res = (0, built_in_assignment_1.processAssignment)(name, [args[0], args[args.length - 1]], rootId, data, {
|
|
51
33
|
superAssignment: config.assignmentOperator === '<<-',
|
|
52
34
|
makeMaybe: indices !== undefined ? false : config.makeMaybe,
|
|
53
|
-
indicesCollection: indices
|
|
35
|
+
indicesCollection: indices,
|
|
36
|
+
canBeReplacement: true
|
|
54
37
|
});
|
|
38
|
+
const convertedArgs = config.readIndices ? args.slice(1, -1) : (0, built_in_access_1.symbolArgumentsToStrings)(args.slice(1, -1), 0);
|
|
55
39
|
/* now, we soft-inject other arguments, so that calls like `x[y] <- 3` are linked correctly */
|
|
56
40
|
const { callArgs } = (0, common_1.processAllArguments)({
|
|
57
41
|
functionName: (0, info_1.initializeCleanDataflowInformation)(rootId, data),
|
|
58
|
-
args:
|
|
42
|
+
args: convertedArgs,
|
|
59
43
|
data,
|
|
60
44
|
functionRootId: rootId,
|
|
61
45
|
finalGraph: res.graph,
|
|
62
46
|
forceArgs: config.forceArgs,
|
|
63
47
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
48
|
+
(0, common_1.patchFunctionCall)({
|
|
49
|
+
nextGraph: res.graph,
|
|
50
|
+
data,
|
|
51
|
+
rootId,
|
|
52
|
+
name,
|
|
53
|
+
argumentProcessResult: args.map(a => a === r_function_call_1.EmptyArgument ? undefined : { entryPoint: (0, unpack_argument_1.unpackArgument)(a)?.info.id })
|
|
54
|
+
});
|
|
55
|
+
const firstArg = (0, unpack_argument_1.unpackArgument)(args[0])?.info.id;
|
|
56
|
+
if (firstArg) {
|
|
57
|
+
res.graph.addEdge(firstArg, rootId, edge_1.EdgeType.DefinedBy | edge_1.EdgeType.Reads);
|
|
58
|
+
}
|
|
67
59
|
/* a replacement reads all of its call args as well, at least as far as I am aware of */
|
|
68
60
|
for (const arg of callArgs) {
|
|
69
61
|
const ref = (0, graph_1.getReferenceOfArgument)(arg);
|
|
@@ -73,4 +65,66 @@ args, rootId, data, config) {
|
|
|
73
65
|
}
|
|
74
66
|
return res;
|
|
75
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Constructs accessed indices of replacement function recursively.
|
|
70
|
+
*
|
|
71
|
+
* Example:
|
|
72
|
+
* ```r
|
|
73
|
+
* a$b <- 1
|
|
74
|
+
* # results in index with lexeme b as identifier
|
|
75
|
+
*
|
|
76
|
+
* a[[1]]$b
|
|
77
|
+
* # results in index with index 1 as identifier with a sub-index with lexeme b as identifier
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @param operation - Operation of replacement function e.g. '$\<-', '[\<-', '[[\<-'
|
|
81
|
+
* @param args - Arguments of the replacement function
|
|
82
|
+
* @returns Accessed indices construct
|
|
83
|
+
*/
|
|
84
|
+
function constructAccessedIndices(operation, args) {
|
|
85
|
+
const { accessedArg, accessArg } = (0, containers_1.getAccessOperands)(args);
|
|
86
|
+
if (accessedArg === undefined || accessArg?.value === undefined || !isSupportedOperation(operation, accessArg.value)) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
const constructIdentifier = getIdentifierBuilder(operation);
|
|
90
|
+
const leafIndex = {
|
|
91
|
+
identifier: constructIdentifier(accessArg),
|
|
92
|
+
nodeId: accessedArg.info.parent ?? ''
|
|
93
|
+
};
|
|
94
|
+
const accessIndices = {
|
|
95
|
+
indices: [leafIndex],
|
|
96
|
+
isContainer: false
|
|
97
|
+
};
|
|
98
|
+
// Check for nested access
|
|
99
|
+
let indicesCollection = undefined;
|
|
100
|
+
if (accessedArg.value?.type === type_1.RType.Access) {
|
|
101
|
+
indicesCollection = (0, containers_1.constructNestedAccess)(accessedArg.value, accessIndices, constructIdentifier);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// use access node as reference to get complete line in slice
|
|
105
|
+
indicesCollection = [accessIndices];
|
|
106
|
+
}
|
|
107
|
+
return indicesCollection;
|
|
108
|
+
}
|
|
109
|
+
function isSupportedOperation(operation, value) {
|
|
110
|
+
const isNameBasedAccess = (operation === '$<-' || operation === '@<-') && value.type === type_1.RType.Symbol;
|
|
111
|
+
const isNumericalIndexBasedAccess = (operation === '[[<-' || operation === '[<-') && value.type === type_1.RType.Number;
|
|
112
|
+
return isNameBasedAccess || isNumericalIndexBasedAccess;
|
|
113
|
+
}
|
|
114
|
+
function getIdentifierBuilder(operation) {
|
|
115
|
+
if (operation === '$<-' || operation == '@<-') {
|
|
116
|
+
return (arg) => {
|
|
117
|
+
return {
|
|
118
|
+
index: undefined,
|
|
119
|
+
lexeme: arg.lexeme,
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// [[<- and [<-
|
|
124
|
+
return (arg) => {
|
|
125
|
+
return {
|
|
126
|
+
index: Number(arg.lexeme),
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
}
|
|
76
130
|
//# sourceMappingURL=built-in-replacement.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DataflowProcessorInformation } from '../../../../../processor';
|
|
2
|
+
import type { DataflowInformation } from '../../../../../info';
|
|
3
|
+
import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
|
+
import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
5
|
+
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
6
|
+
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
|
+
export declare function processRm<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processRm = processRm;
|
|
4
|
+
const known_call_handling_1 = require("../known-call-handling");
|
|
5
|
+
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
6
|
+
const logger_1 = require("../../../../../logger");
|
|
7
|
+
const remove_1 = require("../../../../../environments/remove");
|
|
8
|
+
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
9
|
+
function processRm(name, args, rootId, data) {
|
|
10
|
+
if (args.length === 0) {
|
|
11
|
+
logger_1.dataflowLogger.warn('empty rm, skipping');
|
|
12
|
+
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information;
|
|
13
|
+
}
|
|
14
|
+
const res = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information;
|
|
15
|
+
const names = [];
|
|
16
|
+
for (const arg of args) {
|
|
17
|
+
if (arg === r_function_call_1.EmptyArgument) {
|
|
18
|
+
logger_1.dataflowLogger.warn('empty argument in rm, skipping');
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const unpacked = arg.value;
|
|
22
|
+
if (unpacked === undefined || (unpacked.type !== type_1.RType.Symbol && unpacked.type !== type_1.RType.String)) {
|
|
23
|
+
logger_1.dataflowLogger.warn(`argument is not a symbol or string, skipping ${JSON.stringify(unpacked)}`);
|
|
24
|
+
}
|
|
25
|
+
else if (unpacked.type === type_1.RType.Symbol) {
|
|
26
|
+
names.push(unpacked.content);
|
|
27
|
+
}
|
|
28
|
+
else if (unpacked.type === type_1.RType.String) {
|
|
29
|
+
names.push(unpacked.content.str);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
let env = res.environment;
|
|
33
|
+
for (const name of names) {
|
|
34
|
+
env = (0, remove_1.remove)(name, env);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
...res,
|
|
38
|
+
environment: env
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=built-in-rm.js.map
|
|
@@ -103,6 +103,10 @@ function findSource(seed, data) {
|
|
|
103
103
|
return found;
|
|
104
104
|
}
|
|
105
105
|
function processSourceCall(name, args, rootId, data, config) {
|
|
106
|
+
if (args.length !== 1) {
|
|
107
|
+
logger_1.dataflowLogger.warn(`Expected exactly one argument for source currently, but got ${args.length} instead, skipping`);
|
|
108
|
+
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information;
|
|
109
|
+
}
|
|
106
110
|
const information = config.includeFunctionCall ?
|
|
107
111
|
(0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information
|
|
108
112
|
: (0, info_1.initializeCleanDataflowInformation)(rootId, data);
|
|
@@ -135,12 +139,14 @@ function processSourceCall(name, args, rootId, data, config) {
|
|
|
135
139
|
if (filepath !== undefined) {
|
|
136
140
|
const request = sourceProvider.createRequest(filepath);
|
|
137
141
|
// check if the sourced file has already been dataflow analyzed, and if so, skip it
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
const limit = (0, config_1.getConfig)().solver.resolveSource?.repeatedSourceLimit ?? 0;
|
|
143
|
+
const findCount = data.referenceChain.filter(e => e.request === request.request && e.content === request.content).length;
|
|
144
|
+
if (findCount > limit) {
|
|
145
|
+
logger_1.dataflowLogger.warn(`Found cycle (>=${limit + 1}) in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
|
|
140
146
|
information.graph.markIdForUnknownSideEffects(rootId);
|
|
141
147
|
return information;
|
|
142
148
|
}
|
|
143
|
-
return sourceRequest(rootId, request, data, information, (0, decorate_1.sourcedDeterministicCountingIdGenerator)(path, name.location));
|
|
149
|
+
return sourceRequest(rootId, request, data, information, (0, decorate_1.sourcedDeterministicCountingIdGenerator)((findCount > 0 ? findCount + '::' : '') + path, name.location));
|
|
144
150
|
}
|
|
145
151
|
}
|
|
146
152
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(sourceFile)} for source is currently not supported, skipping`);
|
|
@@ -172,7 +178,8 @@ function sourceRequest(rootId, request, data, information, getId) {
|
|
|
172
178
|
});
|
|
173
179
|
}
|
|
174
180
|
catch (e) {
|
|
175
|
-
logger_1.dataflowLogger.
|
|
181
|
+
logger_1.dataflowLogger.error(`Failed to analyze sourced file ${JSON.stringify(request)}, skipping: ${e.message}`);
|
|
182
|
+
logger_1.dataflowLogger.error(e.stack);
|
|
176
183
|
information.graph.markIdForUnknownSideEffects(rootId);
|
|
177
184
|
return information;
|
|
178
185
|
}
|
|
@@ -183,6 +190,7 @@ function sourceRequest(rootId, request, data, information, getId) {
|
|
|
183
190
|
for (const out of dataflow.out) {
|
|
184
191
|
dataflow.graph.addControlDependency(out.nodeId, rootId, true);
|
|
185
192
|
}
|
|
193
|
+
dataflow.graph.addFile(request.request === 'file' ? request.content : '<inline>');
|
|
186
194
|
// update our graph with the sourced file's information
|
|
187
195
|
const newInformation = { ...information };
|
|
188
196
|
newInformation.environment = (0, overwrite_1.overwriteEnvironment)(information.environment, dataflow.environment);
|
|
@@ -191,7 +199,13 @@ function sourceRequest(rootId, request, data, information, getId) {
|
|
|
191
199
|
for (const [k, v] of normalized.idMap) {
|
|
192
200
|
data.completeAst.idMap.set(k, v);
|
|
193
201
|
}
|
|
194
|
-
return
|
|
202
|
+
return {
|
|
203
|
+
...newInformation,
|
|
204
|
+
in: newInformation.in.concat(dataflow.in),
|
|
205
|
+
out: newInformation.out.concat(dataflow.out),
|
|
206
|
+
unknownReferences: newInformation.unknownReferences.concat(dataflow.unknownReferences),
|
|
207
|
+
exitPoints: dataflow.exitPoints
|
|
208
|
+
};
|
|
195
209
|
}
|
|
196
210
|
function standaloneSourceFile(inputRequest, data, uniqueSourceId, information) {
|
|
197
211
|
const path = inputRequest.request === 'file' ? inputRequest.content : '-inline-';
|
|
@@ -208,6 +222,6 @@ function standaloneSourceFile(inputRequest, data, uniqueSourceId, information) {
|
|
|
208
222
|
currentRequest: request,
|
|
209
223
|
environment: information.environment,
|
|
210
224
|
referenceChain: [...data.referenceChain, inputRequest]
|
|
211
|
-
}, information, (0, decorate_1.deterministicPrefixIdGenerator)(path + '
|
|
225
|
+
}, information, (0, decorate_1.deterministicPrefixIdGenerator)(path + '::' + uniqueSourceId));
|
|
212
226
|
}
|
|
213
227
|
//# sourceMappingURL=built-in-source.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
2
|
+
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
3
|
+
import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
|
+
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
5
|
+
import type { DataflowInformation } from '../../../../../info';
|
|
6
|
+
import type { DataflowProcessorInformation } from '../../../../../processor';
|
|
7
|
+
/**
|
|
8
|
+
* Process a vector call.
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* ```r
|
|
12
|
+
* c(1, 2, 3, 4)
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function processVector<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|