@eagleoutice/flowr 2.2.15 → 2.3.0
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 +226 -6
- package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
- package/abstract-interpretation/data-frame/absint-info.js +31 -0
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +59 -0
- package/abstract-interpretation/data-frame/absint-visitor.js +173 -0
- package/abstract-interpretation/data-frame/domain.d.ts +107 -0
- package/abstract-interpretation/data-frame/domain.js +315 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
- package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
- package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
- package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
- package/abstract-interpretation/data-frame/resolve-args.js +118 -0
- package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
- package/abstract-interpretation/data-frame/semantics.js +366 -0
- package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
- package/abstract-interpretation/data-frame/shape-inference.js +117 -0
- package/benchmark/slicer.d.ts +18 -2
- package/benchmark/slicer.js +143 -5
- package/benchmark/stats/print.js +123 -45
- package/benchmark/stats/size-of.d.ts +7 -0
- package/benchmark/stats/size-of.js +1 -0
- package/benchmark/stats/stats.d.ts +30 -1
- package/benchmark/stats/stats.js +4 -2
- package/benchmark/summarizer/data.d.ts +33 -2
- package/benchmark/summarizer/first-phase/input.js +5 -1
- package/benchmark/summarizer/first-phase/process.d.ts +2 -1
- package/benchmark/summarizer/first-phase/process.js +49 -3
- package/benchmark/summarizer/second-phase/process.js +101 -3
- package/cli/benchmark-app.d.ts +2 -0
- package/cli/benchmark-app.js +5 -1
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +13 -8
- package/cli/common/options.js +4 -0
- package/cli/export-quads-app.js +2 -1
- package/cli/flowr.js +58 -57
- package/cli/repl/commands/repl-cfg.js +13 -13
- package/cli/repl/commands/repl-commands.js +2 -2
- package/cli/repl/commands/repl-dataflow.js +10 -10
- package/cli/repl/commands/repl-execute.d.ts +2 -3
- package/cli/repl/commands/repl-execute.js +4 -4
- package/cli/repl/commands/repl-lineage.js +4 -4
- package/cli/repl/commands/repl-main.d.ts +12 -1
- package/cli/repl/commands/repl-normalize.js +6 -6
- package/cli/repl/commands/repl-parse.js +2 -2
- package/cli/repl/commands/repl-query.js +9 -9
- package/cli/repl/commands/repl-version.js +1 -1
- package/cli/repl/core.d.ts +5 -2
- package/cli/repl/core.js +10 -8
- package/cli/repl/server/connection.d.ts +3 -1
- package/cli/repl/server/connection.js +7 -5
- package/cli/repl/server/server.d.ts +3 -2
- package/cli/repl/server/server.js +4 -2
- package/cli/script-core/statistics-core.d.ts +2 -1
- package/cli/script-core/statistics-core.js +2 -2
- package/cli/script-core/statistics-helper-core.d.ts +2 -1
- package/cli/script-core/statistics-helper-core.js +5 -4
- package/cli/slicer-app.js +4 -2
- package/cli/statistics-app.js +2 -1
- package/cli/statistics-helper-app.js +2 -1
- package/config.d.ts +43 -10
- package/config.js +47 -43
- package/control-flow/cfg-dead-code.js +45 -2
- package/control-flow/cfg-simplification.d.ts +2 -0
- package/control-flow/control-flow-graph.d.ts +2 -0
- package/control-flow/control-flow-graph.js +8 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +5 -3
- package/control-flow/dfg-cfg-guided-visitor.js +15 -4
- package/control-flow/extract-cfg.d.ts +4 -2
- package/control-flow/extract-cfg.js +4 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +20 -2
- package/control-flow/semantic-cfg-guided-visitor.js +24 -4
- package/core/pipeline-executor.d.ts +4 -1
- package/core/pipeline-executor.js +6 -5
- package/core/steps/all/core/10-normalize.d.ts +2 -0
- package/core/steps/all/core/10-normalize.js +1 -1
- package/core/steps/all/core/11-normalize-tree-sitter.d.ts +2 -1
- package/core/steps/all/core/11-normalize-tree-sitter.js +2 -2
- package/core/steps/all/core/20-dataflow.d.ts +2 -1
- package/core/steps/all/core/20-dataflow.js +2 -2
- package/core/steps/all/static-slicing/00-slice.d.ts +2 -1
- package/core/steps/all/static-slicing/00-slice.js +2 -2
- package/core/steps/pipeline/default-pipelines.d.ts +32 -31
- package/core/steps/pipeline/default-pipelines.js +8 -8
- package/core/steps/pipeline-step.d.ts +2 -1
- package/dataflow/environments/built-in-config.d.ts +3 -3
- package/dataflow/environments/built-in.d.ts +11 -3
- package/dataflow/environments/built-in.js +5 -3
- package/dataflow/environments/default-builtin-config.js +4 -2
- package/dataflow/environments/define.d.ts +2 -1
- package/dataflow/environments/define.js +4 -5
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +29 -0
- package/dataflow/eval/resolve/alias-tracking.d.ts +7 -2
- package/dataflow/eval/resolve/alias-tracking.js +11 -8
- package/dataflow/eval/resolve/resolve-argument.d.ts +8 -0
- package/dataflow/eval/resolve/resolve-argument.js +118 -0
- package/dataflow/eval/resolve/resolve.d.ts +65 -18
- package/dataflow/eval/resolve/resolve.js +144 -48
- package/dataflow/eval/values/string/string-constants.d.ts +1 -1
- package/dataflow/eval/values/string/string-constants.js +7 -2
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +5 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +4 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +11 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +10 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +7 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +6 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +19 -15
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +1 -1
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/process-parameter.js +1 -1
- package/dataflow/origin/dfg-get-symbol-refs.d.ts +21 -0
- package/dataflow/origin/dfg-get-symbol-refs.js +50 -0
- package/dataflow/processor.d.ts +5 -0
- package/documentation/doc-util/doc-cfg.js +4 -3
- package/documentation/doc-util/doc-code.d.ts +1 -1
- package/documentation/doc-util/doc-dfg.js +3 -2
- package/documentation/doc-util/doc-functions.d.ts +24 -0
- package/documentation/doc-util/doc-functions.js +65 -0
- package/documentation/doc-util/doc-normalized-ast.js +3 -2
- package/documentation/doc-util/doc-print.d.ts +5 -0
- package/documentation/doc-util/doc-print.js +36 -0
- package/documentation/doc-util/doc-query.js +13 -2
- package/documentation/doc-util/doc-repl.js +2 -1
- package/documentation/doc-util/doc-search.js +3 -2
- package/documentation/doc-util/doc-types.d.ts +28 -6
- package/documentation/doc-util/doc-types.js +89 -45
- package/documentation/print-cfg-wiki.js +6 -7
- package/documentation/print-core-wiki.js +5 -5
- package/documentation/print-dataflow-graph-wiki.js +10 -10
- package/documentation/print-engines-wiki.js +1 -2
- package/documentation/print-faq-wiki.js +8 -2
- package/documentation/print-interface-wiki.js +12 -2
- package/documentation/print-linter-issue.d.ts +1 -0
- package/documentation/print-linter-issue.js +71 -0
- package/documentation/print-linter-wiki.js +223 -34
- package/documentation/print-linting-and-testing-wiki.js +2 -4
- package/documentation/print-normalized-ast-wiki.js +3 -3
- package/documentation/print-query-wiki.js +18 -2
- package/documentation/print-readme.js +24 -1
- package/documentation/print-search-wiki.js +1 -2
- package/linter/linter-executor.d.ts +3 -1
- package/linter/linter-executor.js +3 -2
- package/linter/linter-format.d.ts +67 -7
- package/linter/linter-format.js +12 -1
- package/linter/linter-rules.d.ts +178 -16
- package/linter/linter-rules.js +14 -4
- package/linter/linter-tags.d.ts +80 -0
- package/linter/linter-tags.js +85 -0
- package/linter/rules/absolute-path.d.ts +71 -0
- package/linter/rules/absolute-path.js +177 -0
- package/linter/rules/dataframe-access-validation.d.ts +53 -0
- package/linter/rules/dataframe-access-validation.js +116 -0
- package/linter/rules/deprecated-functions.d.ts +43 -0
- package/linter/rules/deprecated-functions.js +58 -0
- package/linter/rules/{2-file-path-validity.d.ts → file-path-validity.d.ts} +16 -6
- package/linter/rules/{2-file-path-validity.js → file-path-validity.js} +21 -13
- package/linter/rules/naming-convention.d.ts +71 -0
- package/linter/rules/naming-convention.js +168 -0
- package/linter/rules/seeded-randomness.d.ts +65 -0
- package/linter/rules/seeded-randomness.js +122 -0
- package/linter/rules/unused-definition.d.ts +41 -0
- package/linter/rules/unused-definition.js +105 -0
- package/package.json +5 -2
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.js +2 -3
- 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 +2 -2
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -116
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
- package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.js +2 -2
- package/queries/catalog/linter-query/linter-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-format.js +16 -12
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
- package/queries/catalog/origin-query/origin-query-format.d.ts +1 -1
- package/queries/catalog/project-query/project-query-format.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +2 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.js +2 -2
- package/queries/catalog/search-query/search-query-format.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -2
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
- package/queries/query.d.ts +76 -16
- package/queries/query.js +2 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +4 -2
- package/r-bridge/lang-4.x/convert-values.js +2 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +3 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +7 -5
- package/r-bridge/shell.d.ts +3 -2
- package/r-bridge/shell.js +4 -5
- package/search/flowr-search-builder.d.ts +6 -2
- package/search/flowr-search-builder.js +7 -0
- package/search/flowr-search-filters.d.ts +32 -8
- package/search/flowr-search-filters.js +42 -15
- package/search/flowr-search.d.ts +4 -0
- package/search/search-executor/search-enrichers.d.ts +7 -3
- package/search/search-executor/search-enrichers.js +29 -20
- package/search/search-executor/search-generators.js +1 -1
- package/search/search-executor/search-transformer.d.ts +2 -0
- package/search/search-executor/search-transformer.js +10 -1
- package/slicing/static/static-slicer.d.ts +1 -1
- package/slicing/static/static-slicer.js +2 -3
- package/statistics/statistics.d.ts +3 -1
- package/statistics/statistics.js +5 -4
- package/util/containers.d.ts +12 -9
- package/util/containers.js +12 -9
- package/util/files.d.ts +8 -2
- package/util/files.js +22 -4
- package/util/objects.d.ts +5 -4
- package/util/r-value.d.ts +23 -0
- package/util/r-value.js +113 -0
- package/util/range.d.ts +5 -1
- package/util/range.js +11 -3
- package/util/text/strings.d.ts +6 -0
- package/util/text/strings.js +35 -0
- package/util/version.js +1 -1
- package/linter/rules/1-deprecated-functions.d.ts +0 -34
- package/linter/rules/1-deprecated-functions.js +0 -54
- package/util/cfg/cfg.d.ts +0 -0
- package/util/cfg/cfg.js +0 -2
package/README.md
CHANGED
|
@@ -12,6 +12,226 @@ available for [VSCode](https://marketplace.visualstudio.com/items?itemName=code-
|
|
|
12
12
|
and [Docker](https://hub.docker.com/r/eagleoutice/flowr).
|
|
13
13
|
It offers a wide variety of features, for example:
|
|
14
14
|
|
|
15
|
+
* 🐞 **code linting**\
|
|
16
|
+
Analyze your R scripts for common issues and potential bugs (see the [wiki page](https://github.com/flowr-analysis/flowr/wiki/Linter) for more information on the currently supported linters).
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
<details><summary style="">Example: Linting code with flowR</summary>
|
|
20
|
+
|
|
21
|
+
To lint your code, you can use the [REPL](https://github.com/flowr-analysis/flowr/wiki/Interface#using-the-repl) or the [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=code-inspect.vscode-flowr) (see [vscode-flowr#283](https://github.com/flowr-analysis/vscode-flowr/pull/283)).
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
```shell
|
|
26
|
+
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
27
|
+
flowR repl using flowR v2.2.16, R v4.5.0 (r-shell engine)
|
|
28
|
+
R> :query @linter "read.csv(\"/root/x.txt\")"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
<details>
|
|
32
|
+
<summary style='color:gray'>Output</summary>
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
Query: [;1mlinter[0m (2 ms)
|
|
37
|
+
╰ **Deprecated Functions** (deprecated-functions):
|
|
38
|
+
╰ _Metadata_: <code>{"totalDeprecatedCalls":0,"totalDeprecatedFunctionDefinitions":0,"searchTimeMs":0,"processTimeMs":0}</code>
|
|
39
|
+
╰ **File Path Validity** (file-path-validity):
|
|
40
|
+
╰ definitely:
|
|
41
|
+
╰ Path `/root/x.txt` at 1.1-23
|
|
42
|
+
╰ _Metadata_: <code>{"totalReads":1,"totalUnknown":0,"totalWritesBeforeAlways":0,"totalValid":0,"searchTimeMs":1,"processTimeMs":0}</code>
|
|
43
|
+
╰ **Seeded Randomness** (seeded-randomness):
|
|
44
|
+
╰ _Metadata_: <code>{"consumerCalls":0,"callsWithFunctionProducers":0,"callsWithAssignmentProducers":0,"callsWithNonConstantProducers":0,"searchTimeMs":0,"processTimeMs":0}</code>
|
|
45
|
+
╰ **Absolute Paths** (absolute-file-paths):
|
|
46
|
+
╰ definitely:
|
|
47
|
+
╰ Path `/root/x.txt` at 1.1-23
|
|
48
|
+
╰ _Metadata_: <code>{"totalConsidered":1,"totalUnknown":0,"searchTimeMs":1,"processTimeMs":0}</code>
|
|
49
|
+
╰ **Unused Definitions** (unused-definitions):
|
|
50
|
+
╰ _Metadata_: <code>{"totalConsidered":0,"searchTimeMs":0,"processTimeMs":0}</code>
|
|
51
|
+
╰ **Naming Convention** (naming-convention):
|
|
52
|
+
╰ _Metadata_: <code>{"numMatches":0,"numBreak":0,"searchTimeMs":0,"processTimeMs":0}</code>
|
|
53
|
+
╰ **Dataframe Access Validation** (dataframe-access-validation):
|
|
54
|
+
╰ _Metadata_: <code>{"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":0}</code>
|
|
55
|
+
[;3mAll queries together required ≈2 ms (1ms accuracy, total 7 ms)[0m[0m
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
The linter will analyze the code and return any issues found.
|
|
61
|
+
Formatted more nicely, this returns:
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
[ { "type": "linter" } ]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
(This query can be shortened to `@linter` when used within the REPL command <span title="Description (Repl Command): Query the given R code, start with 'file://' to indicate a file. The query is to be a valid query in json format (use 'help' to get more information).">`:query`</span>).
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
_Results (prettified and summarized):_
|
|
76
|
+
|
|
77
|
+
Query: **linter** (12 ms)\
|
|
78
|
+
╰ **Deprecated Functions** (deprecated-functions):\
|
|
79
|
+
╰ _Metadata_: <code>{"totalDeprecatedCalls":0,"totalDeprecatedFunctionDefinitions":0,"searchTimeMs":1,"processTimeMs":0}</code>\
|
|
80
|
+
╰ **File Path Validity** (file-path-validity):\
|
|
81
|
+
╰ definitely:\
|
|
82
|
+
╰ Path `/root/x.txt` at 1.1-23\
|
|
83
|
+
╰ _Metadata_: <code>{"totalReads":1,"totalUnknown":0,"totalWritesBeforeAlways":0,"totalValid":0,"searchTimeMs":3,"processTimeMs":1}</code>\
|
|
84
|
+
╰ **Seeded Randomness** (seeded-randomness):\
|
|
85
|
+
╰ _Metadata_: <code>{"consumerCalls":0,"callsWithFunctionProducers":0,"callsWithAssignmentProducers":0,"callsWithNonConstantProducers":0,"searchTimeMs":1,"processTimeMs":0}</code>\
|
|
86
|
+
╰ **Absolute Paths** (absolute-file-paths):\
|
|
87
|
+
╰ definitely:\
|
|
88
|
+
╰ Path `/root/x.txt` at 1.1-23\
|
|
89
|
+
╰ _Metadata_: <code>{"totalConsidered":1,"totalUnknown":0,"searchTimeMs":2,"processTimeMs":0}</code>\
|
|
90
|
+
╰ **Unused Definitions** (unused-definitions):\
|
|
91
|
+
╰ _Metadata_: <code>{"totalConsidered":0,"searchTimeMs":0,"processTimeMs":0}</code>\
|
|
92
|
+
╰ **Naming Convention** (naming-convention):\
|
|
93
|
+
╰ _Metadata_: <code>{"numMatches":0,"numBreak":0,"searchTimeMs":0,"processTimeMs":0}</code>\
|
|
94
|
+
╰ **Dataframe Access Validation** (dataframe-access-validation):\
|
|
95
|
+
╰ _Metadata_: <code>{"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":3}</code>\
|
|
96
|
+
_All queries together required ≈13 ms (1ms accuracy, total 207 ms)_
|
|
97
|
+
|
|
98
|
+
<details> <summary style="color:gray">Show Detailed Results as Json</summary>
|
|
99
|
+
|
|
100
|
+
The analysis required _207.2 ms_ (including parsing and normalization and the query) within the generation environment.
|
|
101
|
+
|
|
102
|
+
In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR.
|
|
103
|
+
Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"linter": {
|
|
111
|
+
"results": {
|
|
112
|
+
"deprecated-functions": {
|
|
113
|
+
"results": [],
|
|
114
|
+
".meta": {
|
|
115
|
+
"totalDeprecatedCalls": 0,
|
|
116
|
+
"totalDeprecatedFunctionDefinitions": 0,
|
|
117
|
+
"searchTimeMs": 1,
|
|
118
|
+
"processTimeMs": 0
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"file-path-validity": {
|
|
122
|
+
"results": [
|
|
123
|
+
{
|
|
124
|
+
"range": [
|
|
125
|
+
1,
|
|
126
|
+
1,
|
|
127
|
+
1,
|
|
128
|
+
23
|
|
129
|
+
],
|
|
130
|
+
"filePath": "/root/x.txt",
|
|
131
|
+
"certainty": "definitely"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
".meta": {
|
|
135
|
+
"totalReads": 1,
|
|
136
|
+
"totalUnknown": 0,
|
|
137
|
+
"totalWritesBeforeAlways": 0,
|
|
138
|
+
"totalValid": 0,
|
|
139
|
+
"searchTimeMs": 3,
|
|
140
|
+
"processTimeMs": 1
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"seeded-randomness": {
|
|
144
|
+
"results": [],
|
|
145
|
+
".meta": {
|
|
146
|
+
"consumerCalls": 0,
|
|
147
|
+
"callsWithFunctionProducers": 0,
|
|
148
|
+
"callsWithAssignmentProducers": 0,
|
|
149
|
+
"callsWithNonConstantProducers": 0,
|
|
150
|
+
"searchTimeMs": 1,
|
|
151
|
+
"processTimeMs": 0
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"absolute-file-paths": {
|
|
155
|
+
"results": [
|
|
156
|
+
{
|
|
157
|
+
"certainty": "definitely",
|
|
158
|
+
"filePath": "/root/x.txt",
|
|
159
|
+
"range": [
|
|
160
|
+
1,
|
|
161
|
+
1,
|
|
162
|
+
1,
|
|
163
|
+
23
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
".meta": {
|
|
168
|
+
"totalConsidered": 1,
|
|
169
|
+
"totalUnknown": 0,
|
|
170
|
+
"searchTimeMs": 2,
|
|
171
|
+
"processTimeMs": 0
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"unused-definitions": {
|
|
175
|
+
"results": [],
|
|
176
|
+
".meta": {
|
|
177
|
+
"totalConsidered": 0,
|
|
178
|
+
"searchTimeMs": 0,
|
|
179
|
+
"processTimeMs": 0
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"naming-convention": {
|
|
183
|
+
"results": [],
|
|
184
|
+
".meta": {
|
|
185
|
+
"numMatches": 0,
|
|
186
|
+
"numBreak": 0,
|
|
187
|
+
"searchTimeMs": 0,
|
|
188
|
+
"processTimeMs": 0
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"dataframe-access-validation": {
|
|
192
|
+
"results": [],
|
|
193
|
+
".meta": {
|
|
194
|
+
"numOperations": 0,
|
|
195
|
+
"numAccesses": 0,
|
|
196
|
+
"totalAccessed": 0,
|
|
197
|
+
"searchTimeMs": 0,
|
|
198
|
+
"processTimeMs": 3
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
".meta": {
|
|
203
|
+
"timing": 12
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
".meta": {
|
|
207
|
+
"timing": 13
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
</details>
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
</details>
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
</details>
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
15
235
|
* 🍕 **program slicing**\
|
|
16
236
|
Given a point of interest like the visualization of a plot, _flowR_ reduces the program to just the parts which are relevant
|
|
17
237
|
for the computation of the point of interest.
|
|
@@ -51,7 +271,7 @@ It offers a wide variety of features, for example:
|
|
|
51
271
|
|
|
52
272
|
```shell
|
|
53
273
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
54
|
-
flowR repl using flowR v2.2.
|
|
274
|
+
flowR repl using flowR v2.2.16, R v4.5.0 (r-shell engine)
|
|
55
275
|
R> :slicer test/testfiles/example.R --criterion "11@sum"
|
|
56
276
|
```
|
|
57
277
|
|
|
@@ -98,7 +318,7 @@ It offers a wide variety of features, for example:
|
|
|
98
318
|
|
|
99
319
|
|
|
100
320
|
* 🚀 **fast data- and control-flow graphs**\
|
|
101
|
-
Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">
|
|
321
|
+
Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">136.1 ms</span></i> (as of Jul 12, 2025),
|
|
102
322
|
_flowR_ can analyze the data- and control-flow of the average real-world R script. See the [benchmarks](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark) for more information,
|
|
103
323
|
and consult the [wiki pages](https://github.com/flowr-analysis/flowr/wiki/Dataflow-Graph) for more details on the dataflow graph.
|
|
104
324
|
|
|
@@ -134,7 +354,7 @@ It offers a wide variety of features, for example:
|
|
|
134
354
|
|
|
135
355
|
```shell
|
|
136
356
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
137
|
-
flowR repl using flowR v2.2.
|
|
357
|
+
flowR repl using flowR v2.2.16, R v4.5.0 (r-shell engine)
|
|
138
358
|
R> :dataflow* test/testfiles/example.R
|
|
139
359
|
```
|
|
140
360
|
|
|
@@ -411,7 +631,7 @@ It offers a wide variety of features, for example:
|
|
|
411
631
|
linkStyle 68 stroke:gray;
|
|
412
632
|
35 -->|"CD-True"| 36
|
|
413
633
|
linkStyle 69 stroke:gray,color:gray;
|
|
414
|
-
36 -->|"
|
|
634
|
+
36 -->|"argument"| 12
|
|
415
635
|
36 -->|"reads, argument"| 20
|
|
416
636
|
36 -->|"argument, non-standard-evaluation"| 35
|
|
417
637
|
36 -.->|"reads, calls"| built-in:for
|
|
@@ -435,7 +655,7 @@ It offers a wide variety of features, for example:
|
|
|
435
655
|
```
|
|
436
656
|
|
|
437
657
|
|
|
438
|
-
(The analysis required
|
|
658
|
+
(The analysis required _13.8 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
|
|
439
659
|
|
|
440
660
|
|
|
441
661
|
|
|
@@ -478,7 +698,7 @@ You can enter <span title="Description (Repl Command): Show help information (al
|
|
|
478
698
|
|
|
479
699
|
<summary>Example REPL session</summary>
|
|
480
700
|
|
|
481
|
-

|
|
701
|
+

|
|
482
702
|
|
|
483
703
|
</details>
|
|
484
704
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { RNode } from '../../r-bridge/lang-4.x/ast/model/model';
|
|
2
|
+
import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
3
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
4
|
+
import type { DataFrameStateDomain } from './domain';
|
|
5
|
+
import type { ConstraintType, DataFrameOperationArgs, DataFrameOperationName, DataFrameOperationOptions } from './semantics';
|
|
6
|
+
/**
|
|
7
|
+
* An abstract data frame operation without additional options.
|
|
8
|
+
* - `operation` contains the type of the abstract operation (see {@link DataFrameOperationName})
|
|
9
|
+
* - `operand` contains the ID of the data frame operand of the operation (may be `undefined`)
|
|
10
|
+
* - `...args` contains the arguments of the abstract operation (see {@link DataFrameOperationArgs})
|
|
11
|
+
*/
|
|
12
|
+
export type DataFrameOperationType<OperationName extends DataFrameOperationName = DataFrameOperationName> = {
|
|
13
|
+
[Name in OperationName]: {
|
|
14
|
+
operation: Name;
|
|
15
|
+
operand: NodeId | undefined;
|
|
16
|
+
} & DataFrameOperationArgs<Name>;
|
|
17
|
+
}[OperationName];
|
|
18
|
+
/**
|
|
19
|
+
* An abstract data frame operation.
|
|
20
|
+
* - `operation` contains the type of the abstract operation (see {@link DataFrameOperationName})
|
|
21
|
+
* - `operand` contains the ID of the data frame operand of the operation (may be `undefined`)
|
|
22
|
+
* - `type` optionally contains the constraint type to overwrite the default type of the operation (see {@link ConstraintType})
|
|
23
|
+
* - `options` optionally contains additional options for the abstract operation (see {@link DataFrameOperationOptions})
|
|
24
|
+
* - `...args` contains the arguments of the abstract operation (see {@link DataFrameOperationArgs})
|
|
25
|
+
*/
|
|
26
|
+
export type DataFrameOperation<OperationName extends DataFrameOperationName = DataFrameOperationName> = {
|
|
27
|
+
[Name in OperationName]: {
|
|
28
|
+
operation: Name;
|
|
29
|
+
operand: NodeId | undefined;
|
|
30
|
+
type?: ConstraintType;
|
|
31
|
+
options?: DataFrameOperationOptions<Name>;
|
|
32
|
+
} & DataFrameOperationArgs<Name>;
|
|
33
|
+
}[OperationName];
|
|
34
|
+
/**
|
|
35
|
+
* Represents the base data frame information stored in the abstract interpretation info of an AST node.
|
|
36
|
+
* - `type` optionally defines the type of the extra information stored in the data frame info
|
|
37
|
+
* - `domain` contains the abstract data frame shape state of the node
|
|
38
|
+
* This may not be present if the data frame shape inference has not been executed yet or the program contains no data frames
|
|
39
|
+
*/
|
|
40
|
+
interface DataFrameInfoBase {
|
|
41
|
+
type?: string;
|
|
42
|
+
domain?: DataFrameStateDomain;
|
|
43
|
+
}
|
|
44
|
+
/** Enum to mark nodes during the data frame shape inference */
|
|
45
|
+
export declare enum DataFrameInfoMarker {
|
|
46
|
+
/** Marks the target symbol of assignments as "unassigned" until the assigned expression is evaluated */
|
|
47
|
+
Unassigned = "unassigned"
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Represents the data frame information for a node without extra data frame information,
|
|
51
|
+
* i.e. for all nodes that do not represent a data frame assignment or data frame operation (this is the default).
|
|
52
|
+
*
|
|
53
|
+
* The `marker` can be used to mark nodes during the data frame shape inference.
|
|
54
|
+
*/
|
|
55
|
+
interface DataFrameEmptyInfo extends DataFrameInfoBase {
|
|
56
|
+
type?: never;
|
|
57
|
+
marker?: DataFrameInfoMarker;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Represents the data frame information for a data frame assignment with a target identifier (symbol/string) and an assigned expression.
|
|
61
|
+
* This is used during data frame shape inference to mark assignments of data frame expressions to an identifier.
|
|
62
|
+
*
|
|
63
|
+
* Use {@link hasDataFrameAssignmentInfo} to check whether an AST node has attached data frame assignment information.
|
|
64
|
+
*/
|
|
65
|
+
export interface DataFrameAssignmentInfo extends DataFrameInfoBase {
|
|
66
|
+
type: 'assignment';
|
|
67
|
+
identifier: NodeId;
|
|
68
|
+
expression: NodeId;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Represents the data frame information for a data frame function/operation with mapped abstract operations.
|
|
72
|
+
* This is used during data frame shape inference to store the abstract operations a data frame function/operation is mapped to.
|
|
73
|
+
*
|
|
74
|
+
* The order of the abstract operations is the order in which their semantics are applied (for example, access operations are typically before other operations in the list).
|
|
75
|
+
* Moreover, abstract operations that take the result of previous abstract operation as data frame operand must have the `operand` set to `undefined`.
|
|
76
|
+
*
|
|
77
|
+
* Use {@link hasDataFrameExpressionInfo} to check whether an AST node has attached data frame expression information.
|
|
78
|
+
*/
|
|
79
|
+
export interface DataFrameExpressionInfo extends DataFrameInfoBase {
|
|
80
|
+
type: 'expression';
|
|
81
|
+
operations: DataFrameOperation[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Represents the data frame shape inference information stored in the abstract interpretation info of AST nodes.
|
|
85
|
+
*/
|
|
86
|
+
export type DataFrameInfo = DataFrameEmptyInfo | DataFrameAssignmentInfo | DataFrameExpressionInfo;
|
|
87
|
+
/**
|
|
88
|
+
* Represents the abstract interpretation information attached to AST nodes.
|
|
89
|
+
*/
|
|
90
|
+
export interface AbstractInterpretationInfo {
|
|
91
|
+
dataFrame?: DataFrameInfo;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Checks whether an AST node has attached data frame assignment information.
|
|
95
|
+
*/
|
|
96
|
+
export declare function hasDataFrameAssignmentInfo<OtherInfo>(node: RNode<OtherInfo & ParentInformation & AbstractInterpretationInfo>): node is RNode<OtherInfo & ParentInformation & AbstractInterpretationInfo & {
|
|
97
|
+
dataFrame: DataFrameAssignmentInfo;
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Checks whether an AST node has attached data frame expression information.
|
|
101
|
+
*/
|
|
102
|
+
export declare function hasDataFrameExpressionInfo<OtherInfo>(node: RNode<OtherInfo & ParentInformation & AbstractInterpretationInfo>): node is RNode<OtherInfo & ParentInformation & AbstractInterpretationInfo & {
|
|
103
|
+
dataFrame: DataFrameExpressionInfo;
|
|
104
|
+
}>;
|
|
105
|
+
/**
|
|
106
|
+
* Checks whether an AST node has an attached data frame info marker.
|
|
107
|
+
*/
|
|
108
|
+
export declare function hasDataFrameInfoMarker<OtherInfo>(node: RNode<OtherInfo & ParentInformation & AbstractInterpretationInfo>, marker: DataFrameInfoMarker): boolean;
|
|
109
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DataFrameInfoMarker = void 0;
|
|
4
|
+
exports.hasDataFrameAssignmentInfo = hasDataFrameAssignmentInfo;
|
|
5
|
+
exports.hasDataFrameExpressionInfo = hasDataFrameExpressionInfo;
|
|
6
|
+
exports.hasDataFrameInfoMarker = hasDataFrameInfoMarker;
|
|
7
|
+
/** Enum to mark nodes during the data frame shape inference */
|
|
8
|
+
var DataFrameInfoMarker;
|
|
9
|
+
(function (DataFrameInfoMarker) {
|
|
10
|
+
/** Marks the target symbol of assignments as "unassigned" until the assigned expression is evaluated */
|
|
11
|
+
DataFrameInfoMarker["Unassigned"] = "unassigned";
|
|
12
|
+
})(DataFrameInfoMarker || (exports.DataFrameInfoMarker = DataFrameInfoMarker = {}));
|
|
13
|
+
/**
|
|
14
|
+
* Checks whether an AST node has attached data frame assignment information.
|
|
15
|
+
*/
|
|
16
|
+
function hasDataFrameAssignmentInfo(node) {
|
|
17
|
+
return node.info.dataFrame?.type === 'assignment';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Checks whether an AST node has attached data frame expression information.
|
|
21
|
+
*/
|
|
22
|
+
function hasDataFrameExpressionInfo(node) {
|
|
23
|
+
return node.info.dataFrame?.type === 'expression';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Checks whether an AST node has an attached data frame info marker.
|
|
27
|
+
*/
|
|
28
|
+
function hasDataFrameInfoMarker(node, marker) {
|
|
29
|
+
return node.info.dataFrame?.type === undefined && node.info.dataFrame?.marker === marker;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=absint-info.js.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { CfgBasicBlockVertex, CfgSimpleVertex, ControlFlowInformation } from '../../control-flow/control-flow-graph';
|
|
2
|
+
import type { SemanticCfgGuidedVisitorConfiguration } from '../../control-flow/semantic-cfg-guided-visitor';
|
|
3
|
+
import { SemanticCfgGuidedVisitor } from '../../control-flow/semantic-cfg-guided-visitor';
|
|
4
|
+
import type { DataflowGraph } from '../../dataflow/graph/graph';
|
|
5
|
+
import type { DataflowGraphVertexFunctionCall, DataflowGraphVertexVariableDefinition } from '../../dataflow/graph/vertex';
|
|
6
|
+
import type { NoInfo } from '../../r-bridge/lang-4.x/ast/model/model';
|
|
7
|
+
import type { NormalizedAst } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
8
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
9
|
+
import { type AbstractInterpretationInfo } from './absint-info';
|
|
10
|
+
export type DataFrameShapeInferenceVisitorConfiguration<OtherInfo = NoInfo, ControlFlow extends ControlFlowInformation = ControlFlowInformation, Ast extends NormalizedAst<OtherInfo & AbstractInterpretationInfo> = NormalizedAst<OtherInfo & AbstractInterpretationInfo>, Dfg extends DataflowGraph = DataflowGraph> = Omit<SemanticCfgGuidedVisitorConfiguration<OtherInfo & AbstractInterpretationInfo, ControlFlow, Ast, Dfg>, 'defaultVisitingOrder' | 'defaultVisitingType'>;
|
|
11
|
+
/**
|
|
12
|
+
* The control flow graph visitor to infer the shape of data frames using abstract interpretation
|
|
13
|
+
*/
|
|
14
|
+
export declare class DataFrameShapeInferenceVisitor<OtherInfo = NoInfo, ControlFlow extends ControlFlowInformation = ControlFlowInformation, Ast extends NormalizedAst<OtherInfo & AbstractInterpretationInfo> = NormalizedAst<OtherInfo & AbstractInterpretationInfo>, Dfg extends DataflowGraph = DataflowGraph, Config extends DataFrameShapeInferenceVisitorConfiguration<OtherInfo, ControlFlow, Ast, Dfg> = DataFrameShapeInferenceVisitorConfiguration<OtherInfo, ControlFlow, Ast, Dfg>> extends SemanticCfgGuidedVisitor<OtherInfo & AbstractInterpretationInfo, ControlFlow, Ast, Dfg, Config & {
|
|
15
|
+
defaultVisitingOrder: 'forward';
|
|
16
|
+
defaultVisitingType: 'exit';
|
|
17
|
+
}> {
|
|
18
|
+
/**
|
|
19
|
+
* The old domain of an AST node before processing the node retrieved from the attached {@link AbstractInterpretationInfo}.
|
|
20
|
+
* This is used to check whether the state has changed and successors should be visited again, and is also required for widening.
|
|
21
|
+
*/
|
|
22
|
+
private oldDomain;
|
|
23
|
+
/**
|
|
24
|
+
* The new domain of an AST node during and after processing the node.
|
|
25
|
+
* This information is stored in the {@link AbstractInterpretationInfo} afterwards.
|
|
26
|
+
*/
|
|
27
|
+
private newDomain;
|
|
28
|
+
constructor(config: Config);
|
|
29
|
+
protected visitNode(nodeId: NodeId): boolean;
|
|
30
|
+
protected visitDataflowNode(vertex: Exclude<CfgSimpleVertex, CfgBasicBlockVertex>): void;
|
|
31
|
+
protected onVariableDefinition({ vertex }: {
|
|
32
|
+
vertex: DataflowGraphVertexVariableDefinition;
|
|
33
|
+
}): void;
|
|
34
|
+
protected onAssignmentCall({ call, target, source }: {
|
|
35
|
+
call: DataflowGraphVertexFunctionCall;
|
|
36
|
+
target?: NodeId;
|
|
37
|
+
source?: NodeId;
|
|
38
|
+
}): void;
|
|
39
|
+
protected onAccessCall({ call }: {
|
|
40
|
+
call: DataflowGraphVertexFunctionCall;
|
|
41
|
+
}): void;
|
|
42
|
+
protected onDefaultFunctionCall({ call }: {
|
|
43
|
+
call: DataflowGraphVertexFunctionCall;
|
|
44
|
+
}): void;
|
|
45
|
+
protected onReplacementCall({ call, source, target }: {
|
|
46
|
+
call: DataflowGraphVertexFunctionCall;
|
|
47
|
+
source: NodeId | undefined;
|
|
48
|
+
target: NodeId | undefined;
|
|
49
|
+
}): void;
|
|
50
|
+
private processOperation;
|
|
51
|
+
private processDataFrameAssignment;
|
|
52
|
+
private processDataFrameExpression;
|
|
53
|
+
/** We only process vertices of leaf nodes and exit vertices (no entry nodes of complex nodes) */
|
|
54
|
+
private shouldSkipVertex;
|
|
55
|
+
/** Get all AST nodes for the predecessor vertices that are leaf nodes and exit vertices */
|
|
56
|
+
private getPredecessorNodes;
|
|
57
|
+
private shouldWiden;
|
|
58
|
+
private clearUnassignedInfo;
|
|
59
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DataFrameShapeInferenceVisitor = void 0;
|
|
4
|
+
const control_flow_graph_1 = require("../../control-flow/control-flow-graph");
|
|
5
|
+
const semantic_cfg_guided_visitor_1 = require("../../control-flow/semantic-cfg-guided-visitor");
|
|
6
|
+
const assert_1 = require("../../util/assert");
|
|
7
|
+
const absint_info_1 = require("./absint-info");
|
|
8
|
+
const domain_1 = require("./domain");
|
|
9
|
+
const access_mapper_1 = require("./mappers/access-mapper");
|
|
10
|
+
const assignment_mapper_1 = require("./mappers/assignment-mapper");
|
|
11
|
+
const function_mapper_1 = require("./mappers/function-mapper");
|
|
12
|
+
const replacement_mapper_1 = require("./mappers/replacement-mapper");
|
|
13
|
+
const semantics_1 = require("./semantics");
|
|
14
|
+
const shape_inference_1 = require("./shape-inference");
|
|
15
|
+
/**
|
|
16
|
+
* The control flow graph visitor to infer the shape of data frames using abstract interpretation
|
|
17
|
+
*/
|
|
18
|
+
class DataFrameShapeInferenceVisitor extends semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor {
|
|
19
|
+
/**
|
|
20
|
+
* The old domain of an AST node before processing the node retrieved from the attached {@link AbstractInterpretationInfo}.
|
|
21
|
+
* This is used to check whether the state has changed and successors should be visited again, and is also required for widening.
|
|
22
|
+
*/
|
|
23
|
+
oldDomain = new Map();
|
|
24
|
+
/**
|
|
25
|
+
* The new domain of an AST node during and after processing the node.
|
|
26
|
+
* This information is stored in the {@link AbstractInterpretationInfo} afterwards.
|
|
27
|
+
*/
|
|
28
|
+
newDomain = new Map();
|
|
29
|
+
constructor(config) {
|
|
30
|
+
super({ ...config, defaultVisitingOrder: 'forward', defaultVisitingType: 'exit' });
|
|
31
|
+
}
|
|
32
|
+
visitNode(nodeId) {
|
|
33
|
+
const vertex = this.getCfgVertex(nodeId);
|
|
34
|
+
// skip vertices representing mid markers or entries of complex nodes
|
|
35
|
+
if (vertex === undefined || this.shouldSkipVertex(vertex)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
const predecessors = this.getPredecessorNodes(vertex.id);
|
|
39
|
+
this.newDomain = (0, domain_1.joinDataFrameStates)(...predecessors.map(node => node.info.dataFrame?.domain ?? new Map()));
|
|
40
|
+
this.onVisitNode(nodeId);
|
|
41
|
+
const visitedCount = this.visited.get(vertex.id) ?? 0;
|
|
42
|
+
this.visited.set(vertex.id, visitedCount + 1);
|
|
43
|
+
// only continue visitor if the node has not been visited before or the data frame value of the node changed
|
|
44
|
+
return visitedCount === 0 || !(0, domain_1.equalDataFrameState)(this.oldDomain, this.newDomain);
|
|
45
|
+
}
|
|
46
|
+
visitDataflowNode(vertex) {
|
|
47
|
+
const node = this.getNormalizedAst((0, control_flow_graph_1.getVertexRootId)(vertex));
|
|
48
|
+
if (node === undefined) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.oldDomain = node.info.dataFrame?.domain ?? new Map();
|
|
52
|
+
super.visitDataflowNode(vertex);
|
|
53
|
+
if (this.shouldWiden(vertex)) {
|
|
54
|
+
this.newDomain = (0, domain_1.wideningDataFrameStates)(this.oldDomain, this.newDomain);
|
|
55
|
+
}
|
|
56
|
+
node.info.dataFrame ??= {};
|
|
57
|
+
node.info.dataFrame.domain = this.newDomain;
|
|
58
|
+
}
|
|
59
|
+
onVariableDefinition({ vertex }) {
|
|
60
|
+
const node = this.getNormalizedAst(vertex.id);
|
|
61
|
+
if (node !== undefined) {
|
|
62
|
+
// mark variable definitions as "unassigned", as the evaluation of the assigned expression is delayed until processing the assignment
|
|
63
|
+
node.info.dataFrame ??= { marker: absint_info_1.DataFrameInfoMarker.Unassigned };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
onAssignmentCall({ call, target, source }) {
|
|
67
|
+
const node = this.getNormalizedAst(call.id);
|
|
68
|
+
const targetNode = this.getNormalizedAst(target);
|
|
69
|
+
const sourceNode = this.getNormalizedAst(source);
|
|
70
|
+
if (node !== undefined && (0, assignment_mapper_1.isAssignmentTarget)(targetNode) && sourceNode !== undefined) {
|
|
71
|
+
node.info.dataFrame = (0, assignment_mapper_1.mapDataFrameVariableAssignment)(targetNode, sourceNode, this.config.dfg);
|
|
72
|
+
this.processOperation(node);
|
|
73
|
+
this.clearUnassignedInfo(targetNode);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
onAccessCall({ call }) {
|
|
77
|
+
const node = this.getNormalizedAst(call.id);
|
|
78
|
+
if (node !== undefined) {
|
|
79
|
+
node.info.dataFrame = (0, access_mapper_1.mapDataFrameAccess)(node, this.config.dfg);
|
|
80
|
+
this.processOperation(node);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
onDefaultFunctionCall({ call }) {
|
|
84
|
+
const node = this.getNormalizedAst(call.id);
|
|
85
|
+
if (node !== undefined) {
|
|
86
|
+
node.info.dataFrame = (0, function_mapper_1.mapDataFrameFunctionCall)(node, this.config.dfg, this.config.flowrConfig);
|
|
87
|
+
this.processOperation(node);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
onReplacementCall({ call, source, target }) {
|
|
91
|
+
const node = this.getNormalizedAst(call.id);
|
|
92
|
+
const targetNode = this.getNormalizedAst(target);
|
|
93
|
+
const sourceNode = this.getNormalizedAst(source);
|
|
94
|
+
if (node !== undefined && targetNode !== undefined && sourceNode !== undefined) {
|
|
95
|
+
node.info.dataFrame = (0, replacement_mapper_1.mapDataFrameReplacementFunction)(node, sourceNode, this.config.dfg);
|
|
96
|
+
this.processOperation(node);
|
|
97
|
+
this.clearUnassignedInfo(targetNode);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
processOperation(node) {
|
|
101
|
+
if ((0, absint_info_1.hasDataFrameAssignmentInfo)(node)) {
|
|
102
|
+
this.processDataFrameAssignment(node);
|
|
103
|
+
}
|
|
104
|
+
else if ((0, absint_info_1.hasDataFrameExpressionInfo)(node)) {
|
|
105
|
+
this.processDataFrameExpression(node);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
processDataFrameAssignment(node) {
|
|
109
|
+
const value = (0, shape_inference_1.resolveIdToDataFrameShape)(node.info.dataFrame.expression, this.config.dfg, this.newDomain);
|
|
110
|
+
if (value !== undefined) {
|
|
111
|
+
this.newDomain.set(node.info.dataFrame.identifier, value);
|
|
112
|
+
const identifier = this.getNormalizedAst(node.info.dataFrame.identifier);
|
|
113
|
+
if (identifier !== undefined) {
|
|
114
|
+
identifier.info.dataFrame ??= {};
|
|
115
|
+
identifier.info.dataFrame.domain = new Map(this.newDomain);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
processDataFrameExpression(node) {
|
|
120
|
+
let value = domain_1.DataFrameTop;
|
|
121
|
+
for (const { operation, operand, type, options, ...args } of node.info.dataFrame.operations) {
|
|
122
|
+
const operandValue = operand !== undefined ? (0, shape_inference_1.resolveIdToDataFrameShape)(operand, this.config.dfg, this.newDomain) : value;
|
|
123
|
+
value = (0, semantics_1.applySemantics)(operation, operandValue ?? domain_1.DataFrameTop, args, options);
|
|
124
|
+
const constraintType = type ?? (0, semantics_1.getConstraintType)(operation);
|
|
125
|
+
if (operand !== undefined && constraintType === semantics_1.ConstraintType.OperandModification) {
|
|
126
|
+
this.newDomain.set(operand, value);
|
|
127
|
+
for (const origin of (0, shape_inference_1.getVariableOrigins)(operand, this.config.dfg)) {
|
|
128
|
+
this.newDomain.set(origin.info.id, value);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (constraintType === semantics_1.ConstraintType.ResultPostcondition) {
|
|
132
|
+
this.newDomain.set(node.info.id, value);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** We only process vertices of leaf nodes and exit vertices (no entry nodes of complex nodes) */
|
|
137
|
+
shouldSkipVertex(vertex) {
|
|
138
|
+
return (0, control_flow_graph_1.isMarkerVertex)(vertex) ? vertex.type !== control_flow_graph_1.CfgVertexType.EndMarker : vertex.end !== undefined;
|
|
139
|
+
}
|
|
140
|
+
/** Get all AST nodes for the predecessor vertices that are leaf nodes and exit vertices */
|
|
141
|
+
getPredecessorNodes(vertexId) {
|
|
142
|
+
return this.config.controlFlow.graph.outgoingEdges(vertexId)?.keys() // outgoing dependency edges are incoming CFG edges
|
|
143
|
+
.map(id => this.getCfgVertex(id))
|
|
144
|
+
.flatMap(vertex => {
|
|
145
|
+
if (vertex === undefined) {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
else if (this.shouldSkipVertex(vertex)) {
|
|
149
|
+
return this.getPredecessorNodes(vertex.id);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
return [this.getNormalizedAst((0, control_flow_graph_1.getVertexRootId)(vertex))];
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
.filter(assert_1.isNotUndefined)
|
|
156
|
+
.toArray() ?? [];
|
|
157
|
+
}
|
|
158
|
+
shouldWiden(vertex) {
|
|
159
|
+
return (this.visited.get(vertex.id) ?? 0) >= this.config.flowrConfig.abstractInterpretation.dataFrame.wideningThreshold;
|
|
160
|
+
}
|
|
161
|
+
clearUnassignedInfo(node) {
|
|
162
|
+
if ((0, absint_info_1.hasDataFrameInfoMarker)(node, absint_info_1.DataFrameInfoMarker.Unassigned)) {
|
|
163
|
+
if (node.info.dataFrame?.domain !== undefined) {
|
|
164
|
+
node.info.dataFrame = { domain: node.info.dataFrame.domain };
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
delete node.info.dataFrame;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
exports.DataFrameShapeInferenceVisitor = DataFrameShapeInferenceVisitor;
|
|
173
|
+
//# sourceMappingURL=absint-visitor.js.map
|