@eagleoutice/flowr 2.8.5 → 2.8.7
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 +14 -14
- package/abstract-interpretation/absint-visitor.d.ts +20 -68
- package/abstract-interpretation/absint-visitor.js +44 -54
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -9
- package/abstract-interpretation/data-frame/dataframe-domain.js +1 -14
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +1 -1
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +2 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +5 -2
- package/abstract-interpretation/data-frame/shape-inference.d.ts +15 -7
- package/abstract-interpretation/data-frame/shape-inference.js +20 -17
- package/abstract-interpretation/domains/abstract-domain.d.ts +1 -1
- package/abstract-interpretation/domains/abstract-domain.js +1 -2
- package/abstract-interpretation/domains/product-domain.d.ts +1 -1
- package/abstract-interpretation/domains/product-domain.js +1 -1
- package/abstract-interpretation/domains/set-range-domain.d.ts +1 -1
- package/abstract-interpretation/domains/set-range-domain.js +1 -1
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +3 -1
- package/abstract-interpretation/domains/state-abstract-domain.js +6 -0
- package/abstract-interpretation/normalized-ast-fold.d.ts +2 -1
- package/abstract-interpretation/normalized-ast-fold.js +8 -1
- package/cli/flowr.js +2 -0
- package/cli/repl/commands/repl-execute.js +1 -1
- package/cli/repl/commands/repl-query.js +7 -9
- package/cli/wiki.d.ts +2 -1
- package/cli/wiki.js +2 -0
- package/control-flow/cfg-dead-code.js +3 -0
- package/control-flow/extract-cfg.js +27 -7
- package/control-flow/semantic-cfg-guided-visitor.d.ts +57 -4
- package/control-flow/semantic-cfg-guided-visitor.js +89 -28
- package/control-flow/useless-loop.d.ts +2 -1
- package/control-flow/useless-loop.js +13 -6
- package/dataflow/environments/built-in-config.d.ts +6 -5
- package/dataflow/environments/built-in.d.ts +107 -34
- package/dataflow/environments/built-in.js +115 -39
- package/dataflow/environments/default-builtin-config.d.ts +113 -67
- package/dataflow/environments/default-builtin-config.js +71 -66
- package/dataflow/environments/diff.js +2 -2
- package/dataflow/environments/environment.js +7 -7
- package/dataflow/environments/identifier.d.ts +4 -2
- package/dataflow/environments/identifier.js +2 -0
- package/dataflow/environments/reference-to-maybe.d.ts +2 -2
- package/dataflow/environments/reference-to-maybe.js +11 -11
- package/dataflow/environments/resolve-by-name.js +17 -6
- package/dataflow/eval/resolve/alias-tracking.js +1 -1
- package/dataflow/eval/resolve/resolve.js +6 -6
- package/dataflow/eval/values/intervals/interval-constants.js +3 -3
- package/dataflow/eval/values/scalar/{scalar-consatnts.d.ts → scalar-constants.d.ts} +2 -2
- package/dataflow/eval/values/scalar/{scalar-consatnts.js → scalar-constants.js} +3 -3
- package/dataflow/eval/values/sets/set-constants.d.ts +4 -2
- package/dataflow/eval/values/sets/set-constants.js +4 -2
- package/dataflow/extractor.js +1 -1
- package/dataflow/fn/exceptions-of-function.d.ts +1 -1
- package/dataflow/fn/exceptions-of-function.js +3 -3
- package/dataflow/graph/call-graph.js +2 -2
- package/dataflow/graph/dataflowgraph-builder.d.ts +4 -4
- package/dataflow/graph/dataflowgraph-builder.js +14 -14
- package/dataflow/graph/diff-dataflow-graph.js +3 -3
- package/dataflow/graph/graph.d.ts +1 -1
- package/dataflow/graph/graph.js +4 -4
- package/dataflow/graph/vertex.d.ts +3 -3
- package/dataflow/info.d.ts +3 -3
- package/dataflow/info.js +11 -11
- package/dataflow/internal/linker.d.ts +9 -0
- package/dataflow/internal/linker.js +33 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +16 -12
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +11 -10
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +20 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.d.ts +5 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +11 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +0 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +39 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-get.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.d.ts +12 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +36 -12
- package/dataflow/internal/process/functions/call/built-in/built-in-library.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-library.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-local.d.ts +18 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-local.js +67 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +11 -10
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.js +5 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +7 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.d.ts +18 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.js +103 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +8 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.js +13 -12
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.js +6 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +7 -6
- package/dataflow/internal/process/functions/call/common.js +7 -7
- package/dataflow/internal/process/functions/call/known-call-handling.js +7 -8
- package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -2
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -6
- package/dataflow/internal/process/functions/process-argument.js +2 -2
- package/dataflow/internal/process/functions/process-parameter.js +3 -3
- package/dataflow/internal/process/process-symbol.js +3 -3
- package/dataflow/internal/process/process-uninteresting-leaf.d.ts +3 -1
- package/dataflow/internal/process/process-uninteresting-leaf.js +3 -1
- package/dataflow/internal/process/process-value.d.ts +1 -1
- package/dataflow/internal/process/process-value.js +4 -4
- package/dataflow/origin/dfg-get-symbol-refs.js +1 -1
- package/dataflow/processor.d.ts +1 -1
- package/documentation/doc-util/doc-structure.js +1 -1
- package/documentation/doc-util/doc-types.d.ts +10 -3
- package/documentation/doc-util/doc-types.js +110 -33
- package/documentation/wiki-absint.d.ts +6 -0
- package/documentation/wiki-absint.js +149 -0
- package/documentation/wiki-analyzer.js +1 -1
- package/documentation/wiki-dataflow-graph.js +12 -11
- package/documentation/wiki-interface.js +2 -1
- package/documentation/wiki-mk/doc-context.d.ts +3 -3
- package/documentation/wiki-mk/doc-context.js +2 -2
- package/documentation/wiki-mk/doc-maker.js +2 -2
- package/documentation/wiki-normalized-ast.d.ts +9 -0
- package/documentation/wiki-normalized-ast.js +40 -52
- package/linter/linter-rules.d.ts +1 -1
- package/linter/rules/seeded-randomness.js +5 -4
- package/linter/rules/useless-loop.d.ts +3 -3
- package/package.json +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +9 -4
- package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +1 -1
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +4 -0
- package/queries/catalog/dependencies-query/dependencies-query-format.js +5 -0
- package/queries/catalog/dependencies-query/function-info/test-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/test-functions.js +82 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +3 -2
- package/queries/catalog/df-shape-query/df-shape-query-format.js +3 -3
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.d.ts +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.js +1 -1
- package/r-bridge/data/data.d.ts +6 -1
- package/r-bridge/data/data.js +8 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +7 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.js +19 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-project.d.ts +4 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-project.js +7 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +2 -1
- package/r-bridge/lang-4.x/convert-values.d.ts +5 -0
- package/search/flowr-search-filters.d.ts +2 -2
- package/slicing/static/static-slicer.js +2 -2
- package/util/mermaid/cfg.d.ts +10 -3
- package/util/mermaid/cfg.js +39 -10
- package/util/mermaid/dfg.js +5 -5
- package/util/simple-df/dfg-view.js +1 -1
- package/util/text/ansi.d.ts +4 -0
- package/util/text/ansi.js +7 -0
- package/util/version.js +1 -1
|
@@ -14,8 +14,9 @@ const general_1 = require("../../../../../eval/values/general");
|
|
|
14
14
|
const r_value_1 = require("../../../../../eval/values/r-value");
|
|
15
15
|
const log_1 = require("../../../../../../util/log");
|
|
16
16
|
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
17
|
+
const built_in_1 = require("../../../../../environments/built-in");
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
+
* Process an apply call like `vapply` or `mapply`.
|
|
19
20
|
*/
|
|
20
21
|
function processApply(name, args, rootId, data, config) {
|
|
21
22
|
const { indexOfFunction = 1, nameOfFunctionArgument, unquoteFunction, resolveInEnvironment, resolveValue } = config;
|
|
@@ -23,14 +24,14 @@ function processApply(name, args, rootId, data, config) {
|
|
|
23
24
|
const forceArgsMask = new Array(indexOfFunction).fill(false);
|
|
24
25
|
forceArgsMask.push(true);
|
|
25
26
|
const resFn = (0, known_call_handling_1.processKnownFunctionCall)({
|
|
26
|
-
name, args, rootId, data, forceArgs: forceArgsMask, origin:
|
|
27
|
+
name, args, rootId, data, forceArgs: forceArgsMask, origin: built_in_1.BuiltInProcName.Apply
|
|
27
28
|
});
|
|
28
29
|
let information = resFn.information;
|
|
29
30
|
const processedArguments = resFn.processedArguments;
|
|
30
31
|
let index = indexOfFunction;
|
|
31
32
|
/* search, if one of the arguments actually contains the argument name if given in the config */
|
|
32
33
|
if (nameOfFunctionArgument !== undefined) {
|
|
33
|
-
const mayFn = args.findIndex(arg => arg !== r_function_call_1.EmptyArgument && arg.name
|
|
34
|
+
const mayFn = args.findIndex(arg => arg !== r_function_call_1.EmptyArgument && arg.name?.content === nameOfFunctionArgument);
|
|
34
35
|
if (mayFn >= 0) {
|
|
35
36
|
index = mayFn;
|
|
36
37
|
}
|
|
@@ -69,7 +70,7 @@ function processApply(name, args, rootId, data, config) {
|
|
|
69
70
|
functionName = val.content.str;
|
|
70
71
|
information = {
|
|
71
72
|
...information,
|
|
72
|
-
in: [...information.in, { type: identifier_1.ReferenceType.Function, name: functionName,
|
|
73
|
+
in: [...information.in, { type: identifier_1.ReferenceType.Function, name: functionName, cds: data.cds, nodeId: functionId }]
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
else if (val.type === type_1.RType.Symbol) {
|
|
@@ -99,7 +100,7 @@ function processApply(name, args, rootId, data, config) {
|
|
|
99
100
|
if (arg && counterpart !== r_function_call_1.EmptyArgument) {
|
|
100
101
|
return {
|
|
101
102
|
name: counterpart.name?.content,
|
|
102
|
-
|
|
103
|
+
cds: data.cds,
|
|
103
104
|
type: identifier_1.ReferenceType.Argument,
|
|
104
105
|
nodeId: arg.entryPoint
|
|
105
106
|
};
|
|
@@ -118,9 +119,9 @@ function processApply(name, args, rootId, data, config) {
|
|
|
118
119
|
name: functionName,
|
|
119
120
|
/* can never be a direct built-in-call */
|
|
120
121
|
onlyBuiltin: false,
|
|
121
|
-
|
|
122
|
+
cds: data.cds,
|
|
122
123
|
args: allOtherArguments, // same reference
|
|
123
|
-
origin: [
|
|
124
|
+
origin: [built_in_1.BuiltInProcName.Function]
|
|
124
125
|
}, data.ctx.env.makeCleanEnv());
|
|
125
126
|
information.graph.addEdge(rootId, rootFnId, edge_1.EdgeType.Calls | edge_1.EdgeType.Reads);
|
|
126
127
|
information.graph.addEdge(rootId, functionId, edge_1.EdgeType.Calls | edge_1.EdgeType.Argument);
|
|
@@ -128,7 +129,7 @@ function processApply(name, args, rootId, data, config) {
|
|
|
128
129
|
...information,
|
|
129
130
|
in: [
|
|
130
131
|
...information.in,
|
|
131
|
-
{ type: identifier_1.ReferenceType.Function, name: functionName,
|
|
132
|
+
{ type: identifier_1.ReferenceType.Function, name: functionName, cds: data.cds, nodeId: functionId }
|
|
132
133
|
]
|
|
133
134
|
};
|
|
134
135
|
const dfVert = information.graph.getVertex(rootId);
|
|
@@ -167,8 +168,8 @@ function processApply(name, args, rootId, data, config) {
|
|
|
167
168
|
args: allOtherArguments,
|
|
168
169
|
environment: resolveInEnvironment === 'global' ? undefined : data.environment,
|
|
169
170
|
onlyBuiltin: resolveInEnvironment === 'global',
|
|
170
|
-
|
|
171
|
-
origin: [
|
|
171
|
+
cds: data.cds,
|
|
172
|
+
origin: [built_in_1.BuiltInProcName.Function]
|
|
172
173
|
});
|
|
173
174
|
}
|
|
174
175
|
for (const arg of processedArguments) {
|
|
@@ -64,7 +64,7 @@ function tryReplacementPassingIndices(rootId, functionName, data, name, args, in
|
|
|
64
64
|
location: functionName.location,
|
|
65
65
|
namespace: undefined
|
|
66
66
|
}, (0, make_argument_1.wrapArgumentsUnnamed)(args, data.completeAst.idMap), functionName.info.id, data, {
|
|
67
|
-
...
|
|
67
|
+
...resolved[0].config,
|
|
68
68
|
activeIndices: indices,
|
|
69
69
|
assignRootId: rootId
|
|
70
70
|
});
|
|
@@ -80,16 +80,16 @@ args, rootId, data, config) {
|
|
|
80
80
|
const argsWithNames = new Map();
|
|
81
81
|
const argsWithoutNames = [];
|
|
82
82
|
for (const arg of args) {
|
|
83
|
-
const name = arg
|
|
84
|
-
if (name
|
|
85
|
-
|
|
83
|
+
const name = arg === r_function_call_1.EmptyArgument ? undefined : arg.name?.content;
|
|
84
|
+
if (name === undefined) {
|
|
85
|
+
argsWithoutNames.push(arg);
|
|
86
86
|
}
|
|
87
87
|
else {
|
|
88
|
-
|
|
88
|
+
argsWithNames.set(name, arg);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
const source = argsWithNames.get(config.source.name) ?? (config.source.idx
|
|
92
|
-
const target = argsWithNames.get(config.target.name) ?? (config.target.idx
|
|
91
|
+
const source = argsWithNames.get(config.source.name) ?? (config.source.idx === undefined ? undefined : argsWithoutNames[config.source.idx]);
|
|
92
|
+
const target = argsWithNames.get(config.target.name) ?? (config.target.idx === undefined ? undefined : argsWithoutNames[config.target.idx]);
|
|
93
93
|
if (source && target) {
|
|
94
94
|
args = [target, source];
|
|
95
95
|
}
|
|
@@ -123,7 +123,7 @@ args, rootId, data, config) {
|
|
|
123
123
|
data,
|
|
124
124
|
reverseOrder: !config.swapSourceAndTarget,
|
|
125
125
|
forceArgs: config.forceArgs,
|
|
126
|
-
origin:
|
|
126
|
+
origin: built_in_1.BuiltInProcName.Assignment
|
|
127
127
|
});
|
|
128
128
|
return processAssignmentToSymbol({
|
|
129
129
|
...config,
|
|
@@ -149,7 +149,7 @@ args, rootId, data, config) {
|
|
|
149
149
|
data,
|
|
150
150
|
reverseOrder: !config.swapSourceAndTarget,
|
|
151
151
|
forceArgs: config.forceArgs,
|
|
152
|
-
origin:
|
|
152
|
+
origin: built_in_1.BuiltInProcName.Assignment
|
|
153
153
|
});
|
|
154
154
|
return processAssignmentToSymbol({
|
|
155
155
|
...config,
|
|
@@ -187,7 +187,7 @@ args, rootId, data, config) {
|
|
|
187
187
|
data,
|
|
188
188
|
reverseOrder: !config.swapSourceAndTarget,
|
|
189
189
|
forceArgs: config.forceArgs,
|
|
190
|
-
origin:
|
|
190
|
+
origin: built_in_1.BuiltInProcName.Assignment
|
|
191
191
|
});
|
|
192
192
|
return processAssignmentToSymbol({
|
|
193
193
|
...config,
|
|
@@ -207,7 +207,7 @@ args, rootId, data, config) {
|
|
|
207
207
|
logger_1.dataflowLogger.warn(`Assignment ${name.content} has an unknown target type ${target.type} => unknown impact`);
|
|
208
208
|
const info = (0, known_call_handling_1.processKnownFunctionCall)({
|
|
209
209
|
name, args: effectiveArgs, rootId, data, forceArgs: config.forceArgs,
|
|
210
|
-
origin:
|
|
210
|
+
origin: built_in_1.BuiltInProcName.Assignment
|
|
211
211
|
}).information;
|
|
212
212
|
(0, unknown_side_effect_1.handleUnknownSideEffect)(info.graph, info.environment, rootId);
|
|
213
213
|
return info;
|
|
@@ -229,7 +229,7 @@ function produceWrittenNodes(rootId, target, referenceType, data, makeMaybe, val
|
|
|
229
229
|
name: ref.name,
|
|
230
230
|
type: referenceType,
|
|
231
231
|
definedAt: rootId,
|
|
232
|
-
|
|
232
|
+
cds: data.cds ?? (makeMaybe ? [] : undefined),
|
|
233
233
|
value
|
|
234
234
|
});
|
|
235
235
|
}
|
|
@@ -257,7 +257,7 @@ function processAssignmentToString(target, args, name, rootId, data, config, sou
|
|
|
257
257
|
data,
|
|
258
258
|
reverseOrder: !config.swapSourceAndTarget,
|
|
259
259
|
forceArgs: config.forceArgs,
|
|
260
|
-
origin:
|
|
260
|
+
origin: built_in_1.BuiltInProcName.Assignment
|
|
261
261
|
});
|
|
262
262
|
return processAssignmentToSymbol({
|
|
263
263
|
...config,
|
|
@@ -350,17 +350,17 @@ function processAssignmentToSymbol(config) {
|
|
|
350
350
|
name: targetName,
|
|
351
351
|
type: referenceType,
|
|
352
352
|
definedAt: rootId,
|
|
353
|
-
|
|
353
|
+
cds: data.cds ?? (makeMaybe ? [] : undefined),
|
|
354
354
|
value: aliases
|
|
355
355
|
}]
|
|
356
356
|
: produceWrittenNodes(rootId, targetArg, referenceType, data, makeMaybe ?? false, aliases);
|
|
357
|
-
if (writeNodes.length !== 1 && log_1.log.settings.minLevel
|
|
357
|
+
if (writeNodes.length !== 1 && log_1.log.settings.minLevel >= 4 /* LogLevel.Warn */) {
|
|
358
358
|
log_1.log.warn(`Unexpected write number in assignment: ${JSON.stringify(writeNodes)}`);
|
|
359
359
|
}
|
|
360
360
|
// we drop the first arg which we use to pass along arguments :D
|
|
361
361
|
const readFromSourceWritten = sourceArg.out.slice(1);
|
|
362
362
|
const readTargets = [
|
|
363
|
-
{ nodeId: rootId, name: nameOfAssignmentFunction,
|
|
363
|
+
{ nodeId: rootId, name: nameOfAssignmentFunction, cds: data.cds, type: identifier_1.ReferenceType.Function }
|
|
364
364
|
].concat(sourceArg.unknownReferences, sourceArg.in, targetName ? targetArg.in : targetArg.in.filter(i => i.nodeId !== targetId), readFromSourceWritten);
|
|
365
365
|
information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
|
|
366
366
|
// install assigned variables in environment
|
|
@@ -376,7 +376,10 @@ function processAssignmentToSymbol(config) {
|
|
|
376
376
|
information.graph.addEdge(rootId, source.info.id, edge_1.EdgeType.Reads);
|
|
377
377
|
}
|
|
378
378
|
return {
|
|
379
|
-
|
|
379
|
+
environment: information.environment,
|
|
380
|
+
graph: information.graph,
|
|
381
|
+
exitPoints: information.exitPoints,
|
|
382
|
+
hooks: information.hooks,
|
|
380
383
|
unknownReferences: [],
|
|
381
384
|
entryPoint: rootId,
|
|
382
385
|
in: readTargets,
|
|
@@ -5,7 +5,7 @@ import { type RFunctionArgument } 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 { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Process a call to `eval()`, trying to resolve the code being evaluated if possible.
|
|
9
9
|
*/
|
|
10
10
|
export declare function processEvalCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
|
|
11
11
|
/** should this produce an explicit source function call in the graph? */
|
|
@@ -18,8 +18,9 @@ const string_constants_1 = require("../../../../../eval/values/string/string-con
|
|
|
18
18
|
const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
|
|
19
19
|
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
20
20
|
const arrays_1 = require("../../../../../../util/collections/arrays");
|
|
21
|
+
const built_in_1 = require("../../../../../environments/built-in");
|
|
21
22
|
/**
|
|
22
|
-
*
|
|
23
|
+
* Process a call to `eval()`, trying to resolve the code being evaluated if possible.
|
|
23
24
|
*/
|
|
24
25
|
function processEvalCall(name, args, rootId, data, config) {
|
|
25
26
|
if (args.length !== 1 || args[0] === r_function_call_1.EmptyArgument || !args[0].value) {
|
|
@@ -27,7 +28,7 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
27
28
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
28
29
|
}
|
|
29
30
|
const information = config.includeFunctionCall ?
|
|
30
|
-
(0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: [true], origin:
|
|
31
|
+
(0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: [true], origin: built_in_1.BuiltInProcName.Eval }).information
|
|
31
32
|
: (0, info_1.initializeCleanDataflowInformation)(rootId, data);
|
|
32
33
|
const evalArgument = args[0];
|
|
33
34
|
if (config.includeFunctionCall) {
|
|
@@ -43,7 +44,7 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
43
44
|
const idGenerator = (0, decorate_1.sourcedDeterministicCountingIdGenerator)(name.lexeme + '::' + rootId, name.location);
|
|
44
45
|
data = {
|
|
45
46
|
...data,
|
|
46
|
-
|
|
47
|
+
cds: [...(data.cds ?? []), { id: rootId, when: true }]
|
|
47
48
|
};
|
|
48
49
|
const originalInfo = { ...information };
|
|
49
50
|
const result = [];
|
|
@@ -9,6 +9,6 @@ import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/
|
|
|
9
9
|
import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
10
10
|
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Processes a list of expressions joining their dataflow graphs accordingly.
|
|
13
13
|
*/
|
|
14
14
|
export declare function processExpressionList<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -23,10 +23,10 @@ function linkReadNameToWriteIfPossible(read, environments, listEnvironments, rem
|
|
|
23
23
|
const readName = read.name && dotDotDotAccess.test(read.name) ? '...' : read.name;
|
|
24
24
|
const probableTarget = readName ? (0, resolve_by_name_1.resolveByName)(readName, environments, read.type) : undefined;
|
|
25
25
|
// record if at least one has not been defined
|
|
26
|
-
if (probableTarget === undefined || probableTarget.some(t => !listEnvironments.has(t.nodeId) || !(0, info_1.happensInEveryBranch)(t.
|
|
26
|
+
if (probableTarget === undefined || probableTarget.some(t => !listEnvironments.has(t.nodeId) || !(0, info_1.happensInEveryBranch)(t.cds))) {
|
|
27
27
|
const has = remainingRead.get(readName);
|
|
28
28
|
if (has) {
|
|
29
|
-
if (!has?.some(h => h.nodeId === read.nodeId && h.name === read.name && h.
|
|
29
|
+
if (!has?.some(h => h.nodeId === read.nodeId && h.name === read.name && h.cds === read.cds)) {
|
|
30
30
|
has.push(read);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -81,7 +81,7 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
if (callDependencies === null) {
|
|
84
|
-
callDependencies = nextGraph.getVertex(functionCall, true)?.
|
|
84
|
+
callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
|
|
85
85
|
}
|
|
86
86
|
inputEnvironment = (0, overwrite_1.overwriteEnvironment)(inputEnvironment, environment, callDependencies);
|
|
87
87
|
}
|
|
@@ -90,7 +90,7 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
|
|
|
90
90
|
return inputEnvironment;
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
93
|
+
* Processes a list of expressions joining their dataflow graphs accordingly.
|
|
94
94
|
*/
|
|
95
95
|
function processExpressionList(name, args, rootId, data) {
|
|
96
96
|
const expressions = args.map(unpack_argument_1.unpackNonameArg);
|
|
@@ -102,7 +102,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
102
102
|
const nextGraph = new graph_1.DataflowGraph(data.completeAst.idMap);
|
|
103
103
|
let out = [];
|
|
104
104
|
const exitPoints = [];
|
|
105
|
-
const activeCdsAtStart = data.
|
|
105
|
+
const activeCdsAtStart = data.cds;
|
|
106
106
|
const invertExitCds = [];
|
|
107
107
|
const processedExpressions = [];
|
|
108
108
|
let defaultReturnExpr = undefined;
|
|
@@ -154,10 +154,10 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
if (defaultReturnExpr) {
|
|
157
|
-
exitPoints.push(data.
|
|
157
|
+
exitPoints.push(data.cds ? {
|
|
158
158
|
type: 0 /* ExitPointType.Default */,
|
|
159
159
|
nodeId: defaultReturnExpr.entryPoint,
|
|
160
|
-
|
|
160
|
+
cds: data.cds
|
|
161
161
|
} : {
|
|
162
162
|
type: 0 /* ExitPointType.Default */,
|
|
163
163
|
nodeId: defaultReturnExpr.entryPoint
|
|
@@ -167,14 +167,14 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
167
167
|
const rootNode = data.completeAst.idMap.get(rootId);
|
|
168
168
|
const withGroup = rootNode?.grouping;
|
|
169
169
|
if (withGroup) {
|
|
170
|
-
ingoing.push({ nodeId: rootId, name: name.content,
|
|
170
|
+
ingoing.push({ nodeId: rootId, name: name.content, cds: data.cds, type: identifier_1.ReferenceType.Function });
|
|
171
171
|
(0, common_1.patchFunctionCall)({
|
|
172
172
|
nextGraph,
|
|
173
173
|
rootId,
|
|
174
174
|
name,
|
|
175
175
|
data,
|
|
176
176
|
argumentProcessResult: processedExpressions,
|
|
177
|
-
origin:
|
|
177
|
+
origin: built_in_1.BuiltInProcName.ExpressionList
|
|
178
178
|
});
|
|
179
179
|
nextGraph.addEdge(rootId, (0, built_in_1.builtInId)('{'), edge_1.EdgeType.Reads | edge_1.EdgeType.Calls);
|
|
180
180
|
// process all exit points as potential returns:
|
|
@@ -5,6 +5,10 @@ import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/
|
|
|
5
5
|
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
6
6
|
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Processes a for-loop call: `for(<variable> in <vector>) <body>`
|
|
9
|
+
* desugared as:
|
|
10
|
+
* ```r
|
|
11
|
+
* `for`(<variable>, <vector>, <body>)
|
|
12
|
+
* ```
|
|
9
13
|
*/
|
|
10
14
|
export declare function processForLoop<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -15,8 +15,13 @@ const append_1 = require("../../../../../environments/append");
|
|
|
15
15
|
const edge_1 = require("../../../../../graph/edge");
|
|
16
16
|
const identifier_1 = require("../../../../../environments/identifier");
|
|
17
17
|
const reference_to_maybe_1 = require("../../../../../environments/reference-to-maybe");
|
|
18
|
+
const built_in_1 = require("../../../../../environments/built-in");
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
+
* Processes a for-loop call: `for(<variable> in <vector>) <body>`
|
|
21
|
+
* desugared as:
|
|
22
|
+
* ```r
|
|
23
|
+
* `for`(<variable>, <vector>, <body>)
|
|
24
|
+
* ```
|
|
20
25
|
*/
|
|
21
26
|
function processForLoop(name, args, rootId, data) {
|
|
22
27
|
if (args.length !== 3) {
|
|
@@ -32,14 +37,14 @@ function processForLoop(name, args, rootId, data) {
|
|
|
32
37
|
}
|
|
33
38
|
const variable = (0, processor_1.processDataflowFor)(variableArg, data);
|
|
34
39
|
// this should not be able to exit always!
|
|
35
|
-
const originalDependency = data.
|
|
40
|
+
const originalDependency = data.cds;
|
|
36
41
|
let headEnvironments = (0, overwrite_1.overwriteEnvironment)(vector.environment, variable.environment);
|
|
37
42
|
const headGraph = variable.graph.mergeWith(vector.graph);
|
|
38
43
|
const writtenVariable = variable.unknownReferences.concat(variable.in);
|
|
39
44
|
for (const write of writtenVariable) {
|
|
40
45
|
headEnvironments = (0, define_1.define)({ ...write, definedAt: name.info.id, type: identifier_1.ReferenceType.Variable }, false, headEnvironments, data.ctx.config);
|
|
41
46
|
}
|
|
42
|
-
data = { ...data,
|
|
47
|
+
data = { ...data, cds: [...data.cds ?? [], { id: name.info.id, when: true }], environment: headEnvironments };
|
|
43
48
|
const body = (0, processor_1.processDataflowFor)(bodyArg, data);
|
|
44
49
|
const nextGraph = headGraph.mergeWith(body.graph);
|
|
45
50
|
const outEnvironment = (0, append_1.appendEnvironment)(headEnvironments, body.environment);
|
|
@@ -57,9 +62,9 @@ function processForLoop(name, args, rootId, data) {
|
|
|
57
62
|
nextGraph,
|
|
58
63
|
rootId,
|
|
59
64
|
name,
|
|
60
|
-
data: { ...data,
|
|
65
|
+
data: { ...data, cds: originalDependency },
|
|
61
66
|
argumentProcessResult: [variable, vector, body],
|
|
62
|
-
origin:
|
|
67
|
+
origin: built_in_1.BuiltInProcName.ForLoop
|
|
63
68
|
});
|
|
64
69
|
/* mark the last argument as nse */
|
|
65
70
|
nextGraph.addEdge(rootId, body.entryPoint, edge_1.EdgeType.NonStandardEvaluation);
|
|
@@ -68,7 +73,7 @@ function processForLoop(name, args, rootId, data) {
|
|
|
68
73
|
return {
|
|
69
74
|
unknownReferences: [],
|
|
70
75
|
// we only want those not bound by a local variable
|
|
71
|
-
in: [{ nodeId: rootId, name: name.content,
|
|
76
|
+
in: [{ nodeId: rootId, name: name.content, cds: originalDependency, type: identifier_1.ReferenceType.Function }, ...vector.unknownReferences, ...[...nameIdShares.values()].flat()],
|
|
72
77
|
out: outgoing,
|
|
73
78
|
graph: nextGraph,
|
|
74
79
|
entryPoint: name.info.id,
|
|
@@ -19,13 +19,6 @@ export declare function processFunctionDefinition<OtherInfo>(name: RSymbol<Other
|
|
|
19
19
|
* @returns active environment within the function definition / call
|
|
20
20
|
*/
|
|
21
21
|
export declare function retrieveActiveEnvironment(callerEnvironment: REnvironmentInformation | undefined, baseEnvironment: REnvironmentInformation, ctx: ReadOnlyFlowrAnalyzerContext): REnvironmentInformation;
|
|
22
|
-
/**
|
|
23
|
-
* Update the closure links of all nested function definitions
|
|
24
|
-
* @param graph - dataflow graph to collect the function definitions from and to update the closure links for
|
|
25
|
-
* @param outEnvironment - active environment on resolving closures (i.e., exit of the function definition)
|
|
26
|
-
* @param fnId - id of the function definition to update the closure links for
|
|
27
|
-
*/
|
|
28
|
-
export declare function updateNestedFunctionClosures(graph: DataflowGraph, outEnvironment: REnvironmentInformation, fnId: NodeId): void;
|
|
29
22
|
/**
|
|
30
23
|
* Update the closure links of all nested function calls, this is probably to be done once at the end of the script
|
|
31
24
|
* @param graph - dataflow graph to collect the function calls from and to update the closure links for
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.processFunctionDefinition = processFunctionDefinition;
|
|
4
4
|
exports.retrieveActiveEnvironment = retrieveActiveEnvironment;
|
|
5
|
-
exports.updateNestedFunctionClosures = updateNestedFunctionClosures;
|
|
6
5
|
exports.updateNestedFunctionCalls = updateNestedFunctionCalls;
|
|
7
6
|
const processor_1 = require("../../../../../processor");
|
|
8
7
|
const info_1 = require("../../../../../info");
|
|
@@ -33,7 +32,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
33
32
|
}
|
|
34
33
|
/* we remove the last argument, as it is the body */
|
|
35
34
|
const parameters = args.slice(0, -1);
|
|
36
|
-
const bodyArg = (0, unpack_argument_1.unpackNonameArg)(args
|
|
35
|
+
const bodyArg = (0, unpack_argument_1.unpackNonameArg)(args.at(-1));
|
|
37
36
|
(0, assert_1.guard)(bodyArg !== undefined, () => `Function Definition ${JSON.stringify(args)} has no body! This is bad!`);
|
|
38
37
|
const originalEnvironment = data.environment;
|
|
39
38
|
// within a function def we do not pass on the outer binds as they could be overwritten when called
|
|
@@ -79,7 +78,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
79
78
|
tag: vertex_1.VertexType.Use,
|
|
80
79
|
id: read.nodeId,
|
|
81
80
|
environment: undefined,
|
|
82
|
-
|
|
81
|
+
cds: undefined
|
|
83
82
|
}, data.ctx.env.makeCleanEnv());
|
|
84
83
|
}
|
|
85
84
|
}
|
|
@@ -94,6 +93,20 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
94
93
|
environment: outEnvironment,
|
|
95
94
|
hooks: compactedHooks
|
|
96
95
|
};
|
|
96
|
+
updateS3Dispatches(subgraph, parameters.map(p => {
|
|
97
|
+
if (p === r_function_call_1.EmptyArgument) {
|
|
98
|
+
return r_function_call_1.EmptyArgument;
|
|
99
|
+
}
|
|
100
|
+
else if (!p.name && p.value && p.value.type === type_1.RType.Parameter) {
|
|
101
|
+
return { type: identifier_1.ReferenceType.Argument, cds: data.cds, nodeId: p.value.name.info.id, name: p.value.name.content };
|
|
102
|
+
}
|
|
103
|
+
else if (p.name) {
|
|
104
|
+
return { type: identifier_1.ReferenceType.Argument, cds: data.cds, nodeId: p.name.info.id, name: p.name.content };
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
return r_function_call_1.EmptyArgument;
|
|
108
|
+
}
|
|
109
|
+
}));
|
|
97
110
|
updateNestedFunctionClosures(subgraph, outEnvironment, name.info.id);
|
|
98
111
|
const exitPoints = body.exitPoints;
|
|
99
112
|
const readParams = {};
|
|
@@ -119,7 +132,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
119
132
|
tag: vertex_1.VertexType.FunctionDefinition,
|
|
120
133
|
id: name.info.id,
|
|
121
134
|
environment: (0, scoping_1.popLocalEnvironment)(outEnvironment),
|
|
122
|
-
|
|
135
|
+
cds: data.cds,
|
|
123
136
|
params: readParams,
|
|
124
137
|
subflow: flow,
|
|
125
138
|
exitPoints: afterHookExitPoints
|
|
@@ -157,6 +170,22 @@ function retrieveActiveEnvironment(callerEnvironment, baseEnvironment, ctx) {
|
|
|
157
170
|
}
|
|
158
171
|
return (0, overwrite_1.overwriteEnvironment)(baseEnvironment, callerEnvironment);
|
|
159
172
|
}
|
|
173
|
+
function updateS3Dispatches(graph, myArgs) {
|
|
174
|
+
for (const [, info] of graph.vertices(false)) {
|
|
175
|
+
if (info.tag !== vertex_1.VertexType.FunctionCall || !info.origin.includes(built_in_1.BuiltInProcName.S3Dispatch)) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (info.args.length === 0) {
|
|
179
|
+
info.args = myArgs;
|
|
180
|
+
for (const arg of myArgs) {
|
|
181
|
+
// add argument edges
|
|
182
|
+
if (arg !== r_function_call_1.EmptyArgument) {
|
|
183
|
+
graph.addEdge(info.id, arg.nodeId, edge_1.EdgeType.Argument);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
160
189
|
/**
|
|
161
190
|
* Update the closure links of all nested function definitions
|
|
162
191
|
* @param graph - dataflow graph to collect the function definitions from and to update the closure links for
|
|
@@ -199,7 +228,7 @@ function updateNestedFunctionClosures(graph, outEnvironment, fnId) {
|
|
|
199
228
|
function updateNestedFunctionCalls(graph, outEnvironment) {
|
|
200
229
|
// track *all* function definitions - including those nested within the current graph,
|
|
201
230
|
// try to resolve their 'in' by only using the lowest scope which will be popped after this definition
|
|
202
|
-
for (const [id, { onlyBuiltin, environment, name }] of graph.verticesOfType(vertex_1.VertexType.FunctionCall)) {
|
|
231
|
+
for (const [id, { onlyBuiltin, environment, name, args }] of graph.verticesOfType(vertex_1.VertexType.FunctionCall)) {
|
|
203
232
|
if (onlyBuiltin || !name) {
|
|
204
233
|
continue;
|
|
205
234
|
}
|
|
@@ -248,6 +277,10 @@ function updateNestedFunctionCalls(graph, outEnvironment) {
|
|
|
248
277
|
}
|
|
249
278
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Keeping ${remainingIn.length} references to open ref ${id} in closure of function definition ${id}`);
|
|
250
279
|
targetVertex.subflow.in = remainingIn;
|
|
280
|
+
const linkedParameters = graph.idMap?.get(target);
|
|
281
|
+
if (linkedParameters?.type === type_1.RType.FunctionDefinition) {
|
|
282
|
+
(0, linker_1.linkArgumentsOnCall)(args, linkedParameters.parameters, graph);
|
|
283
|
+
}
|
|
251
284
|
}
|
|
252
285
|
}
|
|
253
286
|
}
|
|
@@ -286,7 +319,7 @@ function findPromiseLinkagesForParameters(parameters, readInParameters, paramete
|
|
|
286
319
|
remainingRead.push(read);
|
|
287
320
|
continue;
|
|
288
321
|
}
|
|
289
|
-
if (writingOuts[0].
|
|
322
|
+
if (writingOuts[0].cds === undefined) {
|
|
290
323
|
parameters.addEdge(read, writingOuts[0], edge_1.EdgeType.Reads);
|
|
291
324
|
continue;
|
|
292
325
|
}
|
|
@@ -8,6 +8,7 @@ const logger_1 = require("../../../../../logger");
|
|
|
8
8
|
const retriever_1 = require("../../../../../../r-bridge/retriever");
|
|
9
9
|
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
10
10
|
const edge_1 = require("../../../../../graph/edge");
|
|
11
|
+
const built_in_1 = require("../../../../../environments/built-in");
|
|
11
12
|
/**
|
|
12
13
|
* Processes a built-in 'get' function call.
|
|
13
14
|
*/
|
|
@@ -34,7 +35,7 @@ function processGet(name, args, rootId, data) {
|
|
|
34
35
|
args: (0, make_argument_1.wrapArgumentsUnnamed)([treatTargetAsSymbol], data.completeAst.idMap),
|
|
35
36
|
rootId,
|
|
36
37
|
data,
|
|
37
|
-
origin:
|
|
38
|
+
origin: built_in_1.BuiltInProcName.Get
|
|
38
39
|
});
|
|
39
40
|
const firstArg = processedArguments[0];
|
|
40
41
|
if (firstArg) {
|
|
@@ -4,9 +4,20 @@ import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/node
|
|
|
4
4
|
import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
5
|
import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
6
|
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
|
+
/** `if(<cond>) <then> else <else>` built-in function configuration, make sure to not reuse indices */
|
|
8
|
+
export interface IfThenElseConfig {
|
|
9
|
+
args?: {
|
|
10
|
+
/** the expression to treat as condition, defaults to index 0 */
|
|
11
|
+
cond: string;
|
|
12
|
+
/** argument to treat as yes/'then' case, defaults to index 1 */
|
|
13
|
+
yes: string;
|
|
14
|
+
/** argument to treat as no/'else' case, defaults to index 2 */
|
|
15
|
+
no: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
7
18
|
/**
|
|
8
19
|
* Processes an if-then-else built-in function call.
|
|
9
20
|
* For example, `if(cond) thenExpr else elseExpr` and `if(cond) thenExpr`.
|
|
10
21
|
* The arguments will be either `[cond, thenExpr]` or `[cond, thenExpr, elseExpr]`.
|
|
11
22
|
*/
|
|
12
|
-
export declare function processIfThenElse<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation
|
|
23
|
+
export declare function processIfThenElse<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config?: IfThenElseConfig): DataflowInformation;
|
|
@@ -13,17 +13,41 @@ const identifier_1 = require("../../../../../environments/identifier");
|
|
|
13
13
|
const general_1 = require("../../../../../eval/values/general");
|
|
14
14
|
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
15
15
|
const reference_to_maybe_1 = require("../../../../../environments/reference-to-maybe");
|
|
16
|
+
const linker_1 = require("../../../../linker");
|
|
17
|
+
const r_argument_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-argument");
|
|
18
|
+
const built_in_1 = require("../../../../../environments/built-in");
|
|
19
|
+
function getArguments(config, args) {
|
|
20
|
+
let condArg;
|
|
21
|
+
let thenArg;
|
|
22
|
+
let otherwiseArg;
|
|
23
|
+
if (config?.args) {
|
|
24
|
+
const params = {
|
|
25
|
+
[config.args.cond]: 'cond',
|
|
26
|
+
[config.args.yes]: 'yes',
|
|
27
|
+
[config.args.no]: 'no',
|
|
28
|
+
'...': '...'
|
|
29
|
+
};
|
|
30
|
+
const argMaps = (0, linker_1.invertArgumentMap)((0, linker_1.pMatch)((0, common_1.convertFnArguments)(args), params));
|
|
31
|
+
condArg = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('cond')?.[0]));
|
|
32
|
+
thenArg = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('yes')?.[0]));
|
|
33
|
+
otherwiseArg = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('no')?.[0]));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
[condArg, thenArg, otherwiseArg] = args.map(e => (0, unpack_argument_1.unpackArg)(e));
|
|
37
|
+
}
|
|
38
|
+
return { condArg, thenArg, otherwiseArg };
|
|
39
|
+
}
|
|
16
40
|
/**
|
|
17
41
|
* Processes an if-then-else built-in function call.
|
|
18
42
|
* For example, `if(cond) thenExpr else elseExpr` and `if(cond) thenExpr`.
|
|
19
43
|
* The arguments will be either `[cond, thenExpr]` or `[cond, thenExpr, elseExpr]`.
|
|
20
44
|
*/
|
|
21
|
-
function processIfThenElse(name, args, rootId, data) {
|
|
45
|
+
function processIfThenElse(name, args, rootId, data, config) {
|
|
22
46
|
if (args.length !== 2 && args.length !== 3) {
|
|
23
47
|
logger_1.dataflowLogger.warn(`If-then-else ${name.content} has something different from 2 or 3 arguments, skipping`);
|
|
24
48
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
25
49
|
}
|
|
26
|
-
const
|
|
50
|
+
const { condArg, thenArg, otherwiseArg } = getArguments(config, args);
|
|
27
51
|
if (condArg === undefined || thenArg === undefined) {
|
|
28
52
|
logger_1.dataflowLogger.warn(`If-then-else ${name.content} has empty condition or then case in ${JSON.stringify(args)}, skipping`);
|
|
29
53
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
@@ -33,7 +57,7 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
33
57
|
logger_1.dataflowLogger.warn(`If-then-else ${rootId} forces exit in condition, skipping rest`);
|
|
34
58
|
return cond;
|
|
35
59
|
}
|
|
36
|
-
const originalDependency = data.
|
|
60
|
+
const originalDependency = data.cds?.slice();
|
|
37
61
|
// currently we update the cd afterward :sweat:
|
|
38
62
|
data = { ...data, environment: cond.environment };
|
|
39
63
|
let then;
|
|
@@ -45,7 +69,7 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
45
69
|
if (!conditionIsAlwaysFalse) {
|
|
46
70
|
then = (0, processor_1.processDataflowFor)(thenArg, data);
|
|
47
71
|
if (then.entryPoint) {
|
|
48
|
-
then.graph.addEdge(
|
|
72
|
+
then.graph.addEdge(rootId, then.entryPoint, edge_1.EdgeType.Returns);
|
|
49
73
|
}
|
|
50
74
|
if (!conditionIsAlwaysTrue) {
|
|
51
75
|
makeThenMaybe = true;
|
|
@@ -54,10 +78,10 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
54
78
|
let otherwise;
|
|
55
79
|
let makeOtherwiseMaybe = false;
|
|
56
80
|
if (otherwiseArg !== undefined && !conditionIsAlwaysTrue) {
|
|
57
|
-
data = { ...data,
|
|
81
|
+
data = { ...data, cds: originalDependency?.slice() };
|
|
58
82
|
otherwise = (0, processor_1.processDataflowFor)(otherwiseArg, data);
|
|
59
83
|
if (otherwise.entryPoint) {
|
|
60
|
-
otherwise.graph.addEdge(
|
|
84
|
+
otherwise.graph.addEdge(rootId, otherwise.entryPoint, edge_1.EdgeType.Returns);
|
|
61
85
|
}
|
|
62
86
|
if (!conditionIsAlwaysFalse) {
|
|
63
87
|
makeOtherwiseMaybe = true;
|
|
@@ -87,17 +111,17 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
87
111
|
nextGraph,
|
|
88
112
|
rootId,
|
|
89
113
|
name,
|
|
90
|
-
data: { ...data,
|
|
114
|
+
data: { ...data, cds: originalDependency },
|
|
91
115
|
argumentProcessResult: [cond, then, otherwise],
|
|
92
|
-
origin:
|
|
116
|
+
origin: built_in_1.BuiltInProcName.IfThenElse
|
|
93
117
|
});
|
|
94
118
|
// as an if always evaluates its condition, we add a 'reads'-edge
|
|
95
|
-
nextGraph.addEdge(
|
|
96
|
-
const exitPoints = (then?.exitPoints ?? []).map(e => ({ ...e,
|
|
97
|
-
.concat((otherwise?.exitPoints ?? []).map(e => ({ ...e,
|
|
119
|
+
nextGraph.addEdge(rootId, cond.entryPoint, edge_1.EdgeType.Reads);
|
|
120
|
+
const exitPoints = (then?.exitPoints ?? []).map(e => ({ ...e, cds: makeThenMaybe ? [...data.cds ?? [], { id: rootId, when: true }] : e.cds }))
|
|
121
|
+
.concat((otherwise?.exitPoints ?? []).map(e => ({ ...e, cds: makeOtherwiseMaybe ? [...data.cds ?? [], { id: rootId, when: false }] : e.cds })));
|
|
98
122
|
return {
|
|
99
123
|
unknownReferences: [],
|
|
100
|
-
in: [{ nodeId: rootId, name: name.content,
|
|
124
|
+
in: [{ nodeId: rootId, name: name.content, cds: originalDependency, type: identifier_1.ReferenceType.Function }, ...ingoing],
|
|
101
125
|
out: outgoing,
|
|
102
126
|
exitPoints,
|
|
103
127
|
entryPoint: rootId,
|