@eagleoutice/flowr 2.7.6 → 2.8.1
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 +67 -64
- package/cli/wiki.js +1 -1
- package/control-flow/extract-cfg.js +3 -3
- package/control-flow/useless-loop.d.ts +1 -1
- package/control-flow/useless-loop.js +2 -2
- package/dataflow/cluster.js +3 -3
- package/dataflow/environments/built-in-config.d.ts +8 -4
- package/dataflow/environments/built-in.d.ts +27 -14
- package/dataflow/environments/built-in.js +27 -12
- package/dataflow/environments/default-builtin-config.d.ts +615 -3
- package/dataflow/environments/default-builtin-config.js +50 -15
- package/dataflow/environments/environment.js +3 -2
- package/dataflow/environments/identifier.d.ts +5 -1
- package/dataflow/environments/reference-to-maybe.d.ts +2 -2
- package/dataflow/environments/reference-to-maybe.js +23 -14
- package/dataflow/environments/resolve-by-name.d.ts +6 -2
- package/dataflow/environments/resolve-by-name.js +5 -1
- package/dataflow/environments/scoping.js +1 -3
- package/dataflow/eval/resolve/alias-tracking.js +5 -1
- package/dataflow/extractor.js +3 -3
- package/dataflow/fn/exceptions-of-function.d.ts +13 -0
- package/dataflow/fn/exceptions-of-function.js +47 -0
- package/dataflow/fn/higher-order-function.d.ts +1 -1
- package/dataflow/fn/higher-order-function.js +3 -3
- package/dataflow/fn/recursive-function.d.ts +6 -0
- package/dataflow/fn/recursive-function.js +32 -0
- package/dataflow/graph/call-graph.d.ts +10 -0
- package/dataflow/graph/call-graph.js +212 -0
- package/dataflow/graph/dataflowgraph-builder.d.ts +7 -2
- package/dataflow/graph/dataflowgraph-builder.js +14 -9
- package/dataflow/graph/diff-dataflow-graph.js +96 -2
- package/dataflow/graph/graph.d.ts +10 -7
- package/dataflow/graph/graph.js +7 -8
- package/dataflow/graph/vertex.d.ts +6 -3
- package/dataflow/hooks.d.ts +30 -0
- package/dataflow/hooks.js +38 -0
- package/dataflow/info.d.ts +28 -5
- package/dataflow/info.js +66 -31
- package/dataflow/internal/linker.d.ts +13 -3
- package/dataflow/internal/linker.js +163 -73
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +4 -0
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +7 -0
- 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 +19 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +14 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +30 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +24 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +5 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +59 -21
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.d.ts +34 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.js +92 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.d.ts +21 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.js +129 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.d.ts +16 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.js +127 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +5 -3
- package/dataflow/internal/process/functions/call/common.d.ts +13 -1
- package/dataflow/internal/process/functions/call/common.js +33 -2
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +13 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +29 -3
- package/dataflow/internal/process/functions/call/named-call-handling.js +2 -1
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -4
- package/dataflow/internal/process/functions/process-argument.js +7 -6
- package/dataflow/internal/process/functions/process-parameter.js +2 -1
- package/dataflow/internal/process/process-named-call.d.ts +2 -2
- package/dataflow/internal/process/process-symbol.js +3 -2
- package/dataflow/internal/process/process-value.d.ts +3 -2
- package/dataflow/internal/process/process-value.js +8 -6
- package/dataflow/origin/dfg-get-origin.js +2 -1
- package/dataflow/origin/dfg-get-symbol-refs.js +1 -1
- package/documentation/doc-readme.d.ts +1 -1
- package/documentation/doc-readme.js +6 -6
- package/documentation/doc-util/doc-code.js +1 -1
- package/documentation/doc-util/doc-dfg.d.ts +1 -0
- package/documentation/doc-util/doc-dfg.js +7 -4
- package/documentation/doc-util/doc-query.d.ts +1 -0
- package/documentation/doc-util/doc-query.js +1 -1
- package/documentation/doc-util/doc-repl.d.ts +2 -1
- package/documentation/doc-util/doc-repl.js +11 -3
- package/documentation/wiki-analyzer.js +2 -0
- package/documentation/wiki-dataflow-graph.js +59 -16
- package/documentation/wiki-interface.js +33 -5
- package/documentation/wiki-mk/doc-context.d.ts +2 -1
- package/documentation/wiki-mk/doc-context.js +2 -2
- package/documentation/wiki-mk/doc-maker.js +4 -3
- package/documentation/wiki-normalized-ast.js +6 -0
- package/documentation/wiki-query.js +109 -1
- package/linter/linter-rules.d.ts +1 -1
- package/linter/rules/seeded-randomness.js +17 -12
- package/linter/rules/useless-loop.d.ts +1 -1
- package/package.json +9 -9
- package/project/cache/flowr-analyzer-cache.d.ts +11 -0
- package/project/cache/flowr-analyzer-cache.js +19 -0
- package/project/context/flowr-analyzer-dependencies-context.d.ts +6 -1
- package/project/context/flowr-analyzer-dependencies-context.js +6 -0
- package/project/context/flowr-analyzer-files-context.d.ts +5 -2
- package/project/context/flowr-analyzer-files-context.js +24 -17
- package/project/context/flowr-file.d.ts +9 -4
- package/project/context/flowr-file.js +20 -6
- package/project/flowr-analyzer.d.ts +11 -0
- package/project/flowr-analyzer.js +6 -0
- package/project/plugins/file-plugins/files/flowr-description-file.d.ts +8 -0
- package/project/plugins/file-plugins/files/flowr-description-file.js +36 -3
- package/project/plugins/file-plugins/files/flowr-jupyter-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-namespace-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-news-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +1 -1
- package/project/plugins/file-plugins/flowr-analyzer-description-file-plugin.js +1 -1
- package/project/plugins/file-plugins/flowr-analyzer-file-plugin.d.ts +4 -1
- package/project/plugins/file-plugins/flowr-analyzer-file-plugin.js +3 -0
- package/project/plugins/file-plugins/{flowr-analyzer-namespace-file-plugin.d.ts → flowr-analyzer-namespace-files-plugin.d.ts} +1 -1
- package/project/plugins/file-plugins/{flowr-analyzer-namespace-file-plugin.js → flowr-analyzer-namespace-files-plugin.js} +4 -4
- package/project/plugins/file-plugins/flowr-analyzer-test-file-plugin.d.ts +26 -0
- package/project/plugins/file-plugins/flowr-analyzer-test-file-plugin.js +39 -0
- package/project/plugins/file-plugins/flowr-analyzer-vignette-file-plugin.d.ts +26 -0
- package/project/plugins/file-plugins/flowr-analyzer-vignette-file-plugin.js +39 -0
- package/project/plugins/flowr-analyzer-plugin-defaults.js +6 -2
- package/project/plugins/package-version-plugins/flowr-analyzer-package-versions-description-file-plugin.js +3 -13
- package/project/plugins/package-version-plugins/package.d.ts +1 -1
- package/project/plugins/package-version-plugins/package.js +3 -3
- package/project/plugins/plugin-registry.d.ts +4 -2
- package/project/plugins/plugin-registry.js +6 -2
- package/project/plugins/project-discovery/flowr-analyzer-project-discovery-plugin.d.ts +11 -0
- package/project/plugins/project-discovery/flowr-analyzer-project-discovery-plugin.js +5 -2
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +4 -12
- package/queries/catalog/call-graph-query/call-graph-query-executor.d.ts +6 -0
- package/queries/catalog/call-graph-query/call-graph-query-executor.js +21 -0
- package/queries/catalog/call-graph-query/call-graph-query-format.d.ts +21 -0
- package/queries/catalog/call-graph-query/call-graph-query-format.js +32 -0
- package/queries/catalog/dataflow-query/dataflow-query-executor.js +4 -3
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +29 -3
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -0
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +8 -1
- package/queries/catalog/dependencies-query/function-info/write-functions.js +13 -0
- package/queries/catalog/does-call-query/does-call-query-executor.d.ts +6 -0
- package/queries/catalog/does-call-query/does-call-query-executor.js +100 -0
- package/queries/catalog/does-call-query/does-call-query-format.d.ts +51 -0
- package/queries/catalog/does-call-query/does-call-query-format.js +102 -0
- package/queries/catalog/files-query/files-query-executor.js +4 -4
- package/queries/catalog/files-query/files-query-format.d.ts +2 -1
- package/queries/catalog/files-query/files-query-format.js +18 -2
- package/queries/catalog/id-map-query/id-map-query-executor.js +4 -3
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.d.ts +18 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.js +56 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.d.ts +34 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.js +54 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +3 -3
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +6 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.js +12 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-executor.d.ts +6 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-executor.js +23 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.d.ts +28 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.js +44 -0
- package/queries/catalog/linter-query/linter-query-format.js +4 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.js +4 -3
- package/queries/catalog/project-query/project-query-executor.js +9 -3
- package/queries/catalog/project-query/project-query-format.d.ts +6 -1
- package/queries/catalog/project-query/project-query-format.js +35 -9
- package/queries/query.d.ts +34 -2
- package/queries/query.js +9 -0
- package/r-bridge/data/data.d.ts +10 -5
- package/r-bridge/data/data.js +11 -5
- package/r-bridge/lang-4.x/ast/model/model.d.ts +7 -7
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +5 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.js +8 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/other/normalize-comment.js +0 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +0 -2
- package/r-bridge/roxygen2/roxygen-ast.d.ts +218 -0
- package/r-bridge/roxygen2/roxygen-ast.js +82 -0
- package/r-bridge/roxygen2/roxygen-parse.d.ts +24 -0
- package/r-bridge/roxygen2/roxygen-parse.js +214 -0
- package/reconstruct/auto-select/magic-comments.js +4 -4
- package/slicing/static/slice-call.js +3 -4
- package/slicing/static/static-slicer.js +2 -2
- package/statistics/features/supported/defined-functions/defined-functions.js +1 -1
- package/util/collections/defaultmap.d.ts +3 -3
- package/util/mermaid/dfg.js +5 -5
- package/util/objects.js +1 -1
- package/util/r-author.d.ts +5 -0
- package/util/r-author.js +110 -0
- package/util/r-license.d.ts +10 -1
- package/util/r-license.js +27 -6
- package/util/r-version.d.ts +19 -0
- package/util/r-version.js +106 -0
- package/util/range.d.ts +6 -0
- package/util/range.js +7 -0
- package/util/simple-df/dfg-ascii.js +2 -2
- package/util/text/args.d.ts +9 -0
- package/util/text/args.js +65 -0
- package/util/version.js +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
/**
|
|
8
|
+
* Processes a built-in 'stopifnot' function call.
|
|
9
|
+
* This is special in that it may take a number of boolean expressions either via `...` or
|
|
10
|
+
* via `exprs` for which each expression is now evaluated individually:
|
|
11
|
+
* @example
|
|
12
|
+
* ```r
|
|
13
|
+
* stopifnot(exprs = {
|
|
14
|
+
* all.equal(pi, 3.1415927)
|
|
15
|
+
* 2 < 2
|
|
16
|
+
* all(1:10 < 12)
|
|
17
|
+
* "a" < "b"
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function processStopIfNot<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processStopIfNot = processStopIfNot;
|
|
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 defaultmap_1 = require("../../../../../../util/collections/defaultmap");
|
|
8
|
+
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
9
|
+
const general_1 = require("../../../../../eval/values/general");
|
|
10
|
+
const assert_1 = require("../../../../../../util/assert");
|
|
11
|
+
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
12
|
+
/**
|
|
13
|
+
* Processes a built-in 'stopifnot' function call.
|
|
14
|
+
* This is special in that it may take a number of boolean expressions either via `...` or
|
|
15
|
+
* via `exprs` for which each expression is now evaluated individually:
|
|
16
|
+
* @example
|
|
17
|
+
* ```r
|
|
18
|
+
* stopifnot(exprs = {
|
|
19
|
+
* all.equal(pi, 3.1415927)
|
|
20
|
+
* 2 < 2
|
|
21
|
+
* all(1:10 < 12)
|
|
22
|
+
* "a" < "b"
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
function processStopIfNot(name, args, rootId, data) {
|
|
27
|
+
const res = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'builtin:stopifnot' }).information;
|
|
28
|
+
if (args.length === 0) {
|
|
29
|
+
logger_1.dataflowLogger.warn(`stopifnot (${name.content}) has no argument, assuming trivially true and skipping`);
|
|
30
|
+
return res;
|
|
31
|
+
}
|
|
32
|
+
// R only allows ... or exprs or exprObject, not all, but we over-approximate and collect all, given that they are after '...'
|
|
33
|
+
// we can safely extract named args by full name
|
|
34
|
+
const argMap = new defaultmap_1.DefaultMap(() => []);
|
|
35
|
+
for (const arg of args) {
|
|
36
|
+
const name = (arg === r_function_call_1.EmptyArgument ? undefined : arg.name)?.content;
|
|
37
|
+
if (name === 'exprObject' || name === 'exprs' || name === 'local') {
|
|
38
|
+
argMap.get(name).push(arg);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
argMap.get('...').push(arg);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const localArgs = argMap.get('local');
|
|
45
|
+
const localArg = localArgs.length > 0 ? localArgs[localArgs.length - 1] : undefined;
|
|
46
|
+
const resolveArgs = { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.ctx.config.solver.variables, ctx: data.ctx };
|
|
47
|
+
// we collect all control dependencies from: all '...', all expressions in 'exprs', and 'exprObject'
|
|
48
|
+
const ids = collectIdsForControl(argMap, data);
|
|
49
|
+
if (localArg !== undefined && localArg !== r_function_call_1.EmptyArgument) {
|
|
50
|
+
const localVal = (0, alias_tracking_1.resolveIdToValue)(localArg?.value?.info.id, resolveArgs);
|
|
51
|
+
const alwaysTrue = (0, general_1.valueSetGuard)(localVal)?.elements.every(d => d.type === 'logical' && d.value === true) ?? false;
|
|
52
|
+
if (!alwaysTrue) {
|
|
53
|
+
logger_1.dataflowLogger.warn(`stopifnot (${name.content}) with non-true 'local' argument is not yet supported, over-approximate`);
|
|
54
|
+
const cds = (data.controlDependencies ?? []).concat(Array.from(ids).map(r => ({
|
|
55
|
+
id: r,
|
|
56
|
+
when: false
|
|
57
|
+
})));
|
|
58
|
+
res.exitPoints.push({
|
|
59
|
+
type: 4 /* ExitPointType.Error */,
|
|
60
|
+
nodeId: rootId,
|
|
61
|
+
controlDependencies: cds
|
|
62
|
+
});
|
|
63
|
+
return res;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const cds = [];
|
|
67
|
+
for (const id of ids) {
|
|
68
|
+
const val = (0, alias_tracking_1.resolveIdToValue)(id, resolveArgs);
|
|
69
|
+
const alwaysFalse = (0, general_1.valueSetGuard)(val)?.elements.every(d => d.type === 'logical' && d.value === false) ?? false;
|
|
70
|
+
if (alwaysFalse) {
|
|
71
|
+
// we know that this fails *always*
|
|
72
|
+
res.exitPoints.push(data.controlDependencies ? {
|
|
73
|
+
type: 4 /* ExitPointType.Error */,
|
|
74
|
+
nodeId: rootId,
|
|
75
|
+
controlDependencies: data.controlDependencies
|
|
76
|
+
} : {
|
|
77
|
+
type: 4 /* ExitPointType.Error */,
|
|
78
|
+
nodeId: rootId
|
|
79
|
+
});
|
|
80
|
+
return res;
|
|
81
|
+
}
|
|
82
|
+
const alwaysTrue = (0, general_1.valueSetGuard)(val)?.elements.every(d => d.type === 'logical' && d.value === true) ?? false;
|
|
83
|
+
if (!alwaysTrue) {
|
|
84
|
+
cds.push({
|
|
85
|
+
id: id,
|
|
86
|
+
when: false // only trigger if it is false
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (cds.length === 0) {
|
|
91
|
+
logger_1.dataflowLogger.warn(`stopifnot (${name.content}) has no unknown expressions to evaluate, assuming trivially true and skipping`);
|
|
92
|
+
return res;
|
|
93
|
+
}
|
|
94
|
+
res.exitPoints.push({
|
|
95
|
+
type: 4 /* ExitPointType.Error */,
|
|
96
|
+
nodeId: rootId,
|
|
97
|
+
controlDependencies: (data.controlDependencies ?? []).concat(cds)
|
|
98
|
+
});
|
|
99
|
+
return res;
|
|
100
|
+
}
|
|
101
|
+
/** Generator so we can early exit on first always-false */
|
|
102
|
+
function* collectIdsForControl(argMap, data) {
|
|
103
|
+
yield* argMap.get('...')
|
|
104
|
+
.map(a => a !== r_function_call_1.EmptyArgument ? a.value?.info.id : undefined)
|
|
105
|
+
.filter(assert_1.isNotUndefined);
|
|
106
|
+
const exprs = argMap.get('exprs');
|
|
107
|
+
if (exprs.length > 0) {
|
|
108
|
+
const exprsArg = exprs[exprs.length - 1];
|
|
109
|
+
if (exprsArg !== r_function_call_1.EmptyArgument && exprsArg.value?.info.id) {
|
|
110
|
+
const elem = data.completeAst.idMap.get(exprsArg.value?.info.id);
|
|
111
|
+
if (elem?.type === type_1.RType.ExpressionList) {
|
|
112
|
+
for (const expr of elem.children) {
|
|
113
|
+
yield expr.info.id;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
yield exprsArg.value?.info.id;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const exprObjectArgs = argMap.get('exprObject');
|
|
122
|
+
if (exprObjectArgs.length > 0) {
|
|
123
|
+
const exprObjectArg = exprObjectArgs[exprObjectArgs.length - 1];
|
|
124
|
+
if (exprObjectArg !== r_function_call_1.EmptyArgument && exprObjectArg.value?.info.id) {
|
|
125
|
+
yield exprObjectArg.value?.info.id;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=built-in-stop-if-not.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
/**
|
|
8
|
+
* Process a built-in try-catch or similar handler.
|
|
9
|
+
*/
|
|
10
|
+
export declare function processTryCatch<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
|
|
11
|
+
block: string;
|
|
12
|
+
handlers: {
|
|
13
|
+
error?: string;
|
|
14
|
+
finally?: string;
|
|
15
|
+
};
|
|
16
|
+
}): DataflowInformation;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processTryCatch = processTryCatch;
|
|
4
|
+
const info_1 = require("../../../../../info");
|
|
5
|
+
const known_call_handling_1 = require("../known-call-handling");
|
|
6
|
+
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
7
|
+
const logger_1 = require("../../../../../logger");
|
|
8
|
+
const linker_1 = require("../../../../linker");
|
|
9
|
+
const vertex_1 = require("../../../../../graph/vertex");
|
|
10
|
+
const unpack_argument_1 = require("../argument/unpack-argument");
|
|
11
|
+
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
12
|
+
const assert_1 = require("../../../../../../util/assert");
|
|
13
|
+
const edge_1 = require("../../../../../graph/edge");
|
|
14
|
+
function getArgsOfName(argMaps, name) {
|
|
15
|
+
return new Set(argMaps.entries().filter(([, v]) => v === name).map(([k]) => k));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Process a built-in try-catch or similar handler.
|
|
19
|
+
*/
|
|
20
|
+
function processTryCatch(name, args, rootId, data, config) {
|
|
21
|
+
const res = (0, known_call_handling_1.processKnownFunctionCall)({ name, args: args.map(unpack_argument_1.tryUnpackNoNameArg), rootId, data, origin: 'builtin:try', forceArgs: 'all' });
|
|
22
|
+
if (args.length < 1 || args[0] === r_function_call_1.EmptyArgument) {
|
|
23
|
+
logger_1.dataflowLogger.warn(`TryCatch Handler ${name.content} does not have 1 argument, skipping`);
|
|
24
|
+
return res.information;
|
|
25
|
+
}
|
|
26
|
+
// artificial ids :)
|
|
27
|
+
const params = {
|
|
28
|
+
[config.block]: 'block',
|
|
29
|
+
'...': '...'
|
|
30
|
+
};
|
|
31
|
+
if (config.handlers.error) {
|
|
32
|
+
params[config.handlers.error] = 'error';
|
|
33
|
+
}
|
|
34
|
+
if (config.handlers.finally) {
|
|
35
|
+
params[config.handlers.finally] = 'finally';
|
|
36
|
+
}
|
|
37
|
+
// only remove exit points from the block
|
|
38
|
+
const argMaps = (0, linker_1.pMatch)(res.callArgs, params);
|
|
39
|
+
const info = res.information;
|
|
40
|
+
const blockArg = getArgsOfName(argMaps, 'block');
|
|
41
|
+
const errorArg = getArgsOfName(argMaps, 'error');
|
|
42
|
+
const finallyArg = getArgsOfName(argMaps, 'finally');
|
|
43
|
+
// only take those exit points from the block
|
|
44
|
+
// check whether blockArg has *always* happening exceptions, if so we do not constrain the error handler
|
|
45
|
+
const blockErrorExitPoints = [];
|
|
46
|
+
const errorExitPoints = [];
|
|
47
|
+
info.exitPoints = res.processedArguments.flatMap(arg => {
|
|
48
|
+
if (!arg) {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
// this calls error and finally args
|
|
52
|
+
if (finallyArg.has(arg.entryPoint)) {
|
|
53
|
+
return handleFdefAsCalled(arg.entryPoint, info.graph, arg.exitPoints, undefined);
|
|
54
|
+
}
|
|
55
|
+
else if (errorArg.has(arg.entryPoint)) {
|
|
56
|
+
errorExitPoints.push(...getExitPoints(info.graph.getVertex(arg.entryPoint), info.graph) ?? []);
|
|
57
|
+
}
|
|
58
|
+
if (!blockArg.has(arg.entryPoint)) {
|
|
59
|
+
// not killing other args
|
|
60
|
+
return arg.exitPoints;
|
|
61
|
+
}
|
|
62
|
+
blockErrorExitPoints.push(...arg.exitPoints.filter(ep => ep.type === 4 /* ExitPointType.Error */).flatMap(a => a.controlDependencies));
|
|
63
|
+
return arg.exitPoints.filter(ep => ep.type !== 4 /* ExitPointType.Error */);
|
|
64
|
+
});
|
|
65
|
+
if (errorExitPoints.length > 0) {
|
|
66
|
+
if ((0, info_1.happensInEveryBranch)(blockErrorExitPoints.some(assert_1.isUndefined) ? undefined : blockErrorExitPoints)) {
|
|
67
|
+
info.exitPoints.push(...errorExitPoints);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
info.exitPoints.push(...constrainExitPoints(errorExitPoints, blockArg));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const e of errorArg) {
|
|
74
|
+
info.graph.addEdge(rootId, e, edge_1.EdgeType.Calls);
|
|
75
|
+
}
|
|
76
|
+
for (const f of finallyArg) {
|
|
77
|
+
info.graph.addEdge(rootId, f, edge_1.EdgeType.Calls);
|
|
78
|
+
}
|
|
79
|
+
for (const e of info.exitPoints) {
|
|
80
|
+
if (e.type !== 4 /* ExitPointType.Error */) {
|
|
81
|
+
info.graph.addEdge(rootId, e.nodeId, edge_1.EdgeType.Returns);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return info;
|
|
85
|
+
}
|
|
86
|
+
function getExitPoints(vertex, graph) {
|
|
87
|
+
if (!vertex) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
if (vertex.tag === vertex_1.VertexType.FunctionDefinition) {
|
|
91
|
+
return vertex.exitPoints;
|
|
92
|
+
}
|
|
93
|
+
// we assumed named argument
|
|
94
|
+
const n = graph.idMap?.get(vertex.id);
|
|
95
|
+
if (!n) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (n.type === type_1.RType.Argument && n.value?.type === type_1.RType.FunctionDefinition) {
|
|
99
|
+
const fdefV = graph.getVertex(n.value.info.id);
|
|
100
|
+
if (fdefV?.tag === vertex_1.VertexType.FunctionDefinition) {
|
|
101
|
+
return fdefV.exitPoints;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
function handleFdefAsCalled(nodeId, graph, def, constrain) {
|
|
107
|
+
const v = graph.getVertex(nodeId);
|
|
108
|
+
const e = getExitPoints(v, graph);
|
|
109
|
+
return e ? constrainExitPoints(e, constrain) : def;
|
|
110
|
+
}
|
|
111
|
+
function constrainExitPoints(exitPoints, constrain) {
|
|
112
|
+
if (!constrain || constrain.size === 0) {
|
|
113
|
+
return exitPoints;
|
|
114
|
+
}
|
|
115
|
+
// append constrains with true
|
|
116
|
+
const cds = Array.from(constrain, id => ({ id, when: true }));
|
|
117
|
+
return exitPoints.map(e => {
|
|
118
|
+
if (e.controlDependencies) {
|
|
119
|
+
e.controlDependencies.push(...cds);
|
|
120
|
+
return e;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return { ...e, controlDependencies: cds };
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=built-in-try-catch.js.map
|
|
@@ -58,7 +58,8 @@ function processWhileLoop(name, args, rootId, data) {
|
|
|
58
58
|
entryPoint: name.info.id,
|
|
59
59
|
exitPoints: [],
|
|
60
60
|
graph: information.graph,
|
|
61
|
-
environment: information.environment
|
|
61
|
+
environment: information.environment,
|
|
62
|
+
hooks: condition.hooks
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
65
|
(0, assert_1.guard)(condition !== undefined && body !== undefined, () => `While-Loop ${name.content} has no condition or body, impossible!`);
|
|
@@ -68,7 +69,7 @@ function processWhileLoop(name, args, rootId, data) {
|
|
|
68
69
|
information.graph.addEdge(name.info.id, condition.entryPoint, edge_1.EdgeType.Reads);
|
|
69
70
|
return condition;
|
|
70
71
|
}
|
|
71
|
-
const cdTrue = { id: name.info.id, when: true };
|
|
72
|
+
const cdTrue = [{ id: name.info.id, when: true }];
|
|
72
73
|
const remainingInputs = (0, linker_1.linkInputs)((0, reference_to_maybe_1.makeAllMaybe)(body.unknownReferences, information.graph, information.environment, false, cdTrue).concat((0, reference_to_maybe_1.makeAllMaybe)(body.in, information.graph, information.environment, false, cdTrue)), information.environment, condition.in.concat(condition.unknownReferences), information.graph, true);
|
|
73
74
|
(0, linker_1.linkCircularRedefinitionsWithinALoop)(information.graph, (0, linker_1.produceNameSharedIdMap)((0, linker_1.findNonLocalReads)(information.graph, condition.in)), body.out);
|
|
74
75
|
(0, linker_1.reapplyLoopExitPoints)(body.exitPoints, body.in.concat(body.out, body.unknownReferences));
|
|
@@ -81,7 +82,8 @@ function processWhileLoop(name, args, rootId, data) {
|
|
|
81
82
|
entryPoint: name.info.id,
|
|
82
83
|
exitPoints: (0, info_1.filterOutLoopExitPoints)(body.exitPoints),
|
|
83
84
|
graph: information.graph,
|
|
84
|
-
environment: information.environment
|
|
85
|
+
environment: information.environment,
|
|
86
|
+
hooks: condition.hooks.concat(body.hooks)
|
|
85
87
|
};
|
|
86
88
|
}
|
|
87
89
|
//# sourceMappingURL=built-in-while-loop.js.map
|
|
@@ -2,7 +2,7 @@ import { type DataflowInformation } from '../../../../info';
|
|
|
2
2
|
import { type DataflowProcessorInformation } from '../../../../processor';
|
|
3
3
|
import type { RNode } from '../../../../../r-bridge/lang-4.x/ast/model/model';
|
|
4
4
|
import type { ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
|
-
import { type RFunctionArgument } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
5
|
+
import { EmptyArgument, type RFunctionArgument } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
6
|
import type { DataflowGraph, FunctionArgument } from '../../../../graph/graph';
|
|
7
7
|
import type { NodeId } from '../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
8
|
import type { REnvironmentInformation } from '../../../../environments/environment';
|
|
@@ -29,6 +29,18 @@ export interface ProcessAllArgumentResult {
|
|
|
29
29
|
readonly remainingReadInArgs: IdentifierReference[];
|
|
30
30
|
readonly processedArguments: (DataflowInformation | undefined)[];
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Converts function arguments into function argument references for a function call vertex.
|
|
34
|
+
* Please be aware, that the ids here are those inferred from the AST, not from the dataflow graph!
|
|
35
|
+
* This function also works after the arguments were unpacked, e.g., by {@link tryUnpackNoNameArg}.
|
|
36
|
+
* @see convertFnArgument
|
|
37
|
+
*/
|
|
38
|
+
export declare function convertFnArguments<OtherInfo>(args: readonly (typeof EmptyArgument | RNode<OtherInfo & ParentInformation>)[]): FunctionArgument[];
|
|
39
|
+
/**
|
|
40
|
+
* Transforms a function argument into a function argument reference for a function call vertex.
|
|
41
|
+
* Please be aware, that the ids here are those inferred from the AST, not from the dataflow graph!
|
|
42
|
+
*/
|
|
43
|
+
export declare function convertFnArgument<OtherInfo>(arg: typeof EmptyArgument | RNode<OtherInfo & ParentInformation>): FunctionArgument;
|
|
32
44
|
/**
|
|
33
45
|
* Processes all arguments for a function call, updating the given final graph and environment.
|
|
34
46
|
*/
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertFnArguments = convertFnArguments;
|
|
4
|
+
exports.convertFnArgument = convertFnArgument;
|
|
3
5
|
exports.processAllArguments = processAllArguments;
|
|
4
6
|
exports.patchFunctionCall = patchFunctionCall;
|
|
5
7
|
const info_1 = require("../../../../info");
|
|
@@ -20,7 +22,7 @@ function forceVertexArgumentValueReferences(rootId, value, graph, env) {
|
|
|
20
22
|
if (valueVertex.tag !== vertex_1.VertexType.Value) {
|
|
21
23
|
if (valueVertex.tag === vertex_1.VertexType.FunctionDefinition) {
|
|
22
24
|
for (const exit of valueVertex.exitPoints) {
|
|
23
|
-
graph.addEdge(rootId, exit, edge_1.EdgeType.Reads);
|
|
25
|
+
graph.addEdge(rootId, exit.nodeId, edge_1.EdgeType.Reads);
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
else {
|
|
@@ -42,6 +44,35 @@ function forceVertexArgumentValueReferences(rootId, value, graph, env) {
|
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Converts function arguments into function argument references for a function call vertex.
|
|
49
|
+
* Please be aware, that the ids here are those inferred from the AST, not from the dataflow graph!
|
|
50
|
+
* This function also works after the arguments were unpacked, e.g., by {@link tryUnpackNoNameArg}.
|
|
51
|
+
* @see convertFnArgument
|
|
52
|
+
*/
|
|
53
|
+
function convertFnArguments(args) {
|
|
54
|
+
return args.map(arg => convertFnArgument(arg));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Transforms a function argument into a function argument reference for a function call vertex.
|
|
58
|
+
* Please be aware, that the ids here are those inferred from the AST, not from the dataflow graph!
|
|
59
|
+
*/
|
|
60
|
+
function convertFnArgument(arg) {
|
|
61
|
+
if (arg === r_function_call_1.EmptyArgument) {
|
|
62
|
+
return r_function_call_1.EmptyArgument;
|
|
63
|
+
}
|
|
64
|
+
else if (!arg.name || arg.type !== type_1.RType.Argument) {
|
|
65
|
+
return { nodeId: arg.info.id, controlDependencies: undefined, type: identifier_1.ReferenceType.Argument };
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return {
|
|
69
|
+
nodeId: arg.info.id,
|
|
70
|
+
name: arg.name.content,
|
|
71
|
+
controlDependencies: undefined,
|
|
72
|
+
type: identifier_1.ReferenceType.Argument
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
45
76
|
/**
|
|
46
77
|
* Processes all arguments for a function call, updating the given final graph and environment.
|
|
47
78
|
*/
|
|
@@ -117,7 +148,7 @@ function patchFunctionCall({ nextGraph, rootId, name, data, argumentProcessResul
|
|
|
117
148
|
environment: data.environment,
|
|
118
149
|
/* will be overwritten accordingly */
|
|
119
150
|
onlyBuiltin: false,
|
|
120
|
-
|
|
151
|
+
controlDependencies: data.controlDependencies,
|
|
121
152
|
args: argumentProcessResult.map(arg => arg === undefined ? r_function_call_1.EmptyArgument : { nodeId: arg.entryPoint, controlDependencies: undefined, call: undefined, type: identifier_1.ReferenceType.Argument }),
|
|
122
153
|
origin: [origin],
|
|
123
154
|
link
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DataflowProcessorInformation } from '../../../../processor';
|
|
2
|
-
import {
|
|
2
|
+
import type { DataflowInformation } from '../../../../info';
|
|
3
3
|
import { type ForceArguments } from './common';
|
|
4
4
|
import type { RSymbol } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
5
5
|
import type { ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
@@ -7,6 +7,7 @@ import type { RFunctionArgument } from '../../../../../r-bridge/lang-4.x/ast/mod
|
|
|
7
7
|
import type { NodeId } from '../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
8
|
import type { RNode } from '../../../../../r-bridge/lang-4.x/ast/model/model';
|
|
9
9
|
import { type IdentifierReference } from '../../../../environments/identifier';
|
|
10
|
+
import type { FunctionArgument } from '../../../../graph/graph';
|
|
10
11
|
import { DataflowGraph } from '../../../../graph/graph';
|
|
11
12
|
import { type ContainerIndicesCollection, type FunctionOriginInformation } from '../../../../graph/vertex';
|
|
12
13
|
export interface ProcessKnownFunctionCallInput<OtherInfo> extends ForceArguments {
|
|
@@ -22,12 +23,23 @@ export interface ProcessKnownFunctionCallInput<OtherInfo> extends ForceArguments
|
|
|
22
23
|
readonly patchData?: (data: DataflowProcessorInformation<OtherInfo & ParentInformation>, arg: number) => DataflowProcessorInformation<OtherInfo & ParentInformation>;
|
|
23
24
|
/** Does the call have a side effect that we do not know a lot about which may have further consequences? */
|
|
24
25
|
readonly hasUnknownSideEffect?: boolean;
|
|
26
|
+
/** The origin to use for the function being called. */
|
|
25
27
|
readonly origin: FunctionOriginInformation | 'default';
|
|
26
28
|
}
|
|
29
|
+
/** The result of processing a known function call. */
|
|
27
30
|
export interface ProcessKnownFunctionCallResult {
|
|
31
|
+
/** This is the overall information about the function call itself. */
|
|
28
32
|
readonly information: DataflowInformation;
|
|
33
|
+
/** The processed arguments in order, they are included in the information but sometimes useful separately. */
|
|
29
34
|
readonly processedArguments: readonly (DataflowInformation | undefined)[];
|
|
35
|
+
/** A reference to the function being called. */
|
|
30
36
|
readonly fnRef: IdentifierReference;
|
|
37
|
+
/**
|
|
38
|
+
* The arguments as recorded on the function call vertex.
|
|
39
|
+
* They are also part of the information via the function call vertex adde, but sometimes useful separately.
|
|
40
|
+
* For example, together with {@link pMatch} to do custom parameter matching.
|
|
41
|
+
*/
|
|
42
|
+
readonly callArgs: readonly FunctionArgument[];
|
|
31
43
|
}
|
|
32
44
|
/**
|
|
33
45
|
* Marks the given arguments as being involved in R's non-standard evaluation.
|
|
@@ -48,8 +48,8 @@ function processKnownFunctionCall({ name, args, rootId, data, reverseOrder = fal
|
|
|
48
48
|
name: functionCallName,
|
|
49
49
|
/* will be overwritten accordingly */
|
|
50
50
|
onlyBuiltin: false,
|
|
51
|
-
|
|
52
|
-
args: reverseOrder ? callArgs.
|
|
51
|
+
controlDependencies: data.controlDependencies,
|
|
52
|
+
args: reverseOrder ? callArgs.toReversed() : callArgs,
|
|
53
53
|
indicesCollection: indicesCollection,
|
|
54
54
|
origin: origin === 'default' ? ['function'] : [origin]
|
|
55
55
|
}, data.ctx.env.makeCleanEnv());
|
|
@@ -59,6 +59,30 @@ function processKnownFunctionCall({ name, args, rootId, data, reverseOrder = fal
|
|
|
59
59
|
const inIds = remainingReadInArgs;
|
|
60
60
|
const fnRef = { nodeId: rootId, name: functionCallName, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function };
|
|
61
61
|
inIds.push(fnRef);
|
|
62
|
+
// if force args is not none, we need to collect all non-default exit points from our arguments!
|
|
63
|
+
let exitPoints = undefined;
|
|
64
|
+
if (forceArgs === 'all') {
|
|
65
|
+
const nonDefaults = processedArguments.flatMap(p => p ? p.exitPoints.filter(ep => ep.type !== 0 /* ExitPointType.Default */) : []);
|
|
66
|
+
if (nonDefaults.length > 0) {
|
|
67
|
+
exitPoints = nonDefaults;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (forceArgs) {
|
|
71
|
+
for (let i = 0; i < forceArgs.length; i++) {
|
|
72
|
+
if (forceArgs[i]) {
|
|
73
|
+
const p = processedArguments[i];
|
|
74
|
+
if (p) {
|
|
75
|
+
const nonDefaults = p.exitPoints.filter(ep => ep.type !== 0 /* ExitPointType.Default */);
|
|
76
|
+
if (nonDefaults.length > 0) {
|
|
77
|
+
if (exitPoints === undefined) {
|
|
78
|
+
exitPoints = [];
|
|
79
|
+
}
|
|
80
|
+
exitPoints.push(...nonDefaults);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
62
86
|
return {
|
|
63
87
|
information: {
|
|
64
88
|
unknownReferences: [],
|
|
@@ -68,8 +92,10 @@ function processKnownFunctionCall({ name, args, rootId, data, reverseOrder = fal
|
|
|
68
92
|
graph: finalGraph,
|
|
69
93
|
environment: finalEnv,
|
|
70
94
|
entryPoint: rootId,
|
|
71
|
-
exitPoints: [{ nodeId: rootId, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }]
|
|
95
|
+
exitPoints: exitPoints ?? [{ nodeId: rootId, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }],
|
|
96
|
+
hooks: functionName.hooks
|
|
72
97
|
},
|
|
98
|
+
callArgs,
|
|
73
99
|
processedArguments: reverseOrder ? processedArguments.reverse() : processedArguments,
|
|
74
100
|
fnRef
|
|
75
101
|
};
|
|
@@ -20,6 +20,7 @@ function mergeInformation(info, newInfo) {
|
|
|
20
20
|
environment: (0, append_1.appendEnvironment)(info.environment, newInfo.environment),
|
|
21
21
|
entryPoint: newInfo.entryPoint,
|
|
22
22
|
exitPoints: info.exitPoints.concat(newInfo.exitPoints),
|
|
23
|
+
hooks: info.hooks.concat(newInfo.hooks)
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
26
|
function processDefaultFunctionProcessor(information, name, args, rootId, data) {
|
|
@@ -48,7 +49,7 @@ function processNamedCall(name, args, rootId, data) {
|
|
|
48
49
|
let builtIn = false;
|
|
49
50
|
for (const resolvedFunction of resolved) {
|
|
50
51
|
if (resolvedFunction.type === identifier_1.ReferenceType.BuiltInFunction && typeof resolvedFunction.processor === 'function') {
|
|
51
|
-
builtIn
|
|
52
|
+
builtIn ||= resolvedFunction.config?.libFn !== true;
|
|
52
53
|
information = mergeInformation(information, resolvedFunction.processor(name, args, rootId, data));
|
|
53
54
|
}
|
|
54
55
|
else {
|
|
@@ -23,8 +23,8 @@ function processUnnamedFunctionCall(functionCall, data) {
|
|
|
23
23
|
const calledRootId = functionCall.calledFunction.info.id;
|
|
24
24
|
const functionCallName = `${exports.UnnamedFunctionCallPrefix}${functionRootId}`;
|
|
25
25
|
logger_1.dataflowLogger.debug(`Using ${functionRootId} as root for the unnamed function call`);
|
|
26
|
-
// we know that it
|
|
27
|
-
finalGraph.addEdge(functionRootId, calledRootId, edge_1.EdgeType.
|
|
26
|
+
// we know that it reads the toplevel:
|
|
27
|
+
finalGraph.addEdge(functionRootId, calledRootId, edge_1.EdgeType.Reads);
|
|
28
28
|
// keep the defined function
|
|
29
29
|
finalGraph.mergeWith(calledFunction.graph);
|
|
30
30
|
const { finalEnv, callArgs, remainingReadInArgs } = (0, common_1.processAllArguments)({
|
|
@@ -42,12 +42,13 @@ function processUnnamedFunctionCall(functionCall, data) {
|
|
|
42
42
|
name: functionCallName,
|
|
43
43
|
/* can never be a direct built-in-call */
|
|
44
44
|
onlyBuiltin: false,
|
|
45
|
-
|
|
45
|
+
controlDependencies: data.controlDependencies,
|
|
46
46
|
args: callArgs, // same reference
|
|
47
47
|
origin: [exports.UnnamedFunctionCallOrigin]
|
|
48
48
|
}, data.ctx.env.makeCleanEnv());
|
|
49
49
|
let inIds = remainingReadInArgs;
|
|
50
50
|
inIds.push({ nodeId: functionRootId, name: functionCallName, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function });
|
|
51
|
+
// if we just call a nested fdef
|
|
51
52
|
if (functionCall.calledFunction.type === type_1.RType.FunctionDefinition) {
|
|
52
53
|
(0, linker_1.linkArgumentsOnCall)(callArgs, functionCall.calledFunction.parameters, finalGraph);
|
|
53
54
|
}
|
|
@@ -61,7 +62,8 @@ function processUnnamedFunctionCall(functionCall, data) {
|
|
|
61
62
|
graph: finalGraph,
|
|
62
63
|
environment: finalEnv,
|
|
63
64
|
entryPoint: functionCall.info.id,
|
|
64
|
-
exitPoints: calledFunction.exitPoints
|
|
65
|
+
exitPoints: calledFunction.exitPoints,
|
|
66
|
+
hooks: calledFunction.hooks,
|
|
65
67
|
};
|
|
66
68
|
}
|
|
67
69
|
//# sourceMappingURL=unnamed-call-handling.js.map
|
|
@@ -33,27 +33,28 @@ function processFunctionArgument(argument, data) {
|
|
|
33
33
|
graph.addVertex({
|
|
34
34
|
tag: vertex_1.VertexType.Use,
|
|
35
35
|
id: argument.info.id,
|
|
36
|
-
|
|
36
|
+
controlDependencies: data.controlDependencies
|
|
37
37
|
}, data.ctx.env.makeCleanEnv());
|
|
38
38
|
entryPoint = argument.info.id;
|
|
39
39
|
}
|
|
40
|
-
const ingoingRefs =
|
|
40
|
+
const ingoingRefs = value ? value.unknownReferences.concat(value.in, name?.in ?? []) : name?.in;
|
|
41
41
|
if (entryPoint && argument.value?.type === type_1.RType.FunctionDefinition) {
|
|
42
42
|
graph.addEdge(entryPoint, argument.value.info.id, edge_1.EdgeType.Reads);
|
|
43
43
|
}
|
|
44
|
-
else if (argumentName) {
|
|
44
|
+
else if (argumentName && ingoingRefs) {
|
|
45
45
|
// we only need to link against those which are not already bound to another function call argument
|
|
46
|
-
linkReadsForArgument(argument,
|
|
46
|
+
linkReadsForArgument(argument, value ? ingoingRefs.concat(value.out /* value may perform definitions */) : ingoingRefs, graph);
|
|
47
47
|
}
|
|
48
48
|
return {
|
|
49
49
|
unknownReferences: [],
|
|
50
50
|
// active nodes of the name will be lost as they are only used to reference the corresponding parameter
|
|
51
|
-
in: ingoingRefs
|
|
51
|
+
in: ingoingRefs?.filter(r => r.name !== undefined) ?? [],
|
|
52
52
|
out: [...value?.out ?? [], ...(name?.out ?? [])],
|
|
53
53
|
graph: graph,
|
|
54
54
|
environment: value?.environment ?? data.environment,
|
|
55
55
|
entryPoint: entryPoint ?? argument.info.id,
|
|
56
|
-
exitPoints: value?.exitPoints ?? name?.exitPoints ?? [{ nodeId: argument.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }]
|
|
56
|
+
exitPoints: value?.exitPoints ?? name?.exitPoints ?? [{ nodeId: argument.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }],
|
|
57
|
+
hooks: []
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
60
|
//# sourceMappingURL=process-argument.js.map
|
|
@@ -43,7 +43,8 @@ function processFunctionParameter(parameter, data) {
|
|
|
43
43
|
graph: graph,
|
|
44
44
|
environment: environment,
|
|
45
45
|
entryPoint: parameter.info.id,
|
|
46
|
-
exitPoints: [{ nodeId: parameter.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }]
|
|
46
|
+
exitPoints: [{ nodeId: parameter.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }],
|
|
47
|
+
hooks: []
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
//# sourceMappingURL=process-parameter.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { DataflowProcessorInformation } from '../../processor';
|
|
2
2
|
import type { DataflowInformation } from '../../info';
|
|
3
|
-
import type {
|
|
3
|
+
import type { RAstNodeBase, RNode, Location } from '../../../r-bridge/lang-4.x/ast/model/model';
|
|
4
4
|
import type { ParentInformation } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
5
|
import type { EmptyArgument } from '../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
6
|
/**
|
|
7
7
|
* Helper function for {@link processNamedCall} using the given `functionName` as the name of the function.
|
|
8
8
|
*/
|
|
9
|
-
export declare function processAsNamedCall<OtherInfo>({ info, lexeme, location }: RNode<OtherInfo & ParentInformation> &
|
|
9
|
+
export declare function processAsNamedCall<OtherInfo>({ info, lexeme, location }: RNode<OtherInfo & ParentInformation> & RAstNodeBase<OtherInfo> & Location, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, name: string, args: readonly (RNode<OtherInfo & ParentInformation> | typeof EmptyArgument | undefined)[]): DataflowInformation;
|
|
@@ -21,10 +21,11 @@ function processSymbol(symbol, data) {
|
|
|
21
21
|
graph: new graph_1.DataflowGraph(data.completeAst.idMap).addVertex({
|
|
22
22
|
tag: vertex_1.VertexType.Use,
|
|
23
23
|
id: symbol.info.id,
|
|
24
|
-
|
|
24
|
+
controlDependencies: data.controlDependencies
|
|
25
25
|
}, data.ctx.env.makeCleanEnv()),
|
|
26
26
|
entryPoint: symbol.info.id,
|
|
27
|
-
exitPoints: [{ nodeId: symbol.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }]
|
|
27
|
+
exitPoints: [{ nodeId: symbol.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }],
|
|
28
|
+
hooks: []
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
//# sourceMappingURL=process-symbol.js.map
|
|
@@ -2,6 +2,7 @@ import { type DataflowInformation } from '../../info';
|
|
|
2
2
|
import type { DataflowProcessorInformation } from '../../processor';
|
|
3
3
|
import type { RNodeWithParent } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Processes a value node in the AST for dataflow analysis.
|
|
6
|
+
* For example, literals like numbers.
|
|
6
7
|
*/
|
|
7
|
-
export declare function processValue<OtherInfo>({ info: { id } }: RNodeWithParent, { controlDependencies, completeAst: { idMap },
|
|
8
|
+
export declare function processValue<OtherInfo>({ info: { id } }: RNodeWithParent, { controlDependencies, completeAst: { idMap }, environment }: DataflowProcessorInformation<OtherInfo>): DataflowInformation;
|