@eagleoutice/flowr 2.2.15 → 2.2.16
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 +210 -6
- package/benchmark/slicer.d.ts +3 -1
- package/benchmark/slicer.js +8 -5
- package/benchmark/summarizer/first-phase/process.d.ts +2 -1
- package/benchmark/summarizer/first-phase/process.js +2 -2
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +4 -1
- package/cli/benchmark-helper-app.d.ts +1 -0
- package/cli/benchmark-helper-app.js +7 -8
- package/cli/common/options.js +2 -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 +12 -10
- package/config.js +26 -42
- 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 +1 -0
- package/control-flow/control-flow-graph.js +4 -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 +19 -1
- package/control-flow/semantic-cfg-guided-visitor.js +23 -3
- 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 +7 -1
- package/dataflow/environments/built-in.js +2 -2
- 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 +9 -6
- 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 +18 -15
- package/dataflow/eval/resolve/resolve.js +20 -18
- 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 +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +15 -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 +3 -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 +1 -2
- package/documentation/print-linter-issue.d.ts +1 -0
- package/documentation/print-linter-issue.js +71 -0
- package/documentation/print-linter-wiki.js +219 -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 +1 -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 +155 -16
- package/linter/linter-rules.js +12 -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/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 +164 -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 +4 -1
- 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/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 +15 -15
- 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/objects.d.ts +5 -4
- 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/README.md
CHANGED
|
@@ -12,6 +12,210 @@ 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.15, 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
|
+
[;3mAll queries together required ≈2 ms (1ms accuracy, total 7 ms)[0m[0m
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
The linter will analyze the code and return any issues found.
|
|
59
|
+
Formatted more nicely, this returns:
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
[ { "type": "linter" } ]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
_Results (prettified and summarized):_
|
|
72
|
+
|
|
73
|
+
Query: **linter** (10 ms)\
|
|
74
|
+
╰ **Deprecated Functions** (deprecated-functions):\
|
|
75
|
+
╰ _Metadata_: <code>{"totalDeprecatedCalls":0,"totalDeprecatedFunctionDefinitions":0,"searchTimeMs":2,"processTimeMs":0}</code>\
|
|
76
|
+
╰ **File Path Validity** (file-path-validity):\
|
|
77
|
+
╰ definitely:\
|
|
78
|
+
╰ Path `/root/x.txt` at 1.1-23\
|
|
79
|
+
╰ _Metadata_: <code>{"totalReads":1,"totalUnknown":0,"totalWritesBeforeAlways":0,"totalValid":0,"searchTimeMs":4,"processTimeMs":1}</code>\
|
|
80
|
+
╰ **Seeded Randomness** (seeded-randomness):\
|
|
81
|
+
╰ _Metadata_: <code>{"consumerCalls":0,"callsWithFunctionProducers":0,"callsWithAssignmentProducers":0,"callsWithNonConstantProducers":0,"searchTimeMs":0,"processTimeMs":0}</code>\
|
|
82
|
+
╰ **Absolute Paths** (absolute-file-paths):\
|
|
83
|
+
╰ definitely:\
|
|
84
|
+
╰ Path `/root/x.txt` at 1.1-23\
|
|
85
|
+
╰ _Metadata_: <code>{"totalConsidered":1,"totalUnknown":0,"searchTimeMs":1,"processTimeMs":1}</code>\
|
|
86
|
+
╰ **Unused Definitions** (unused-definitions):\
|
|
87
|
+
╰ _Metadata_: <code>{"totalConsidered":0,"searchTimeMs":0,"processTimeMs":0}</code>\
|
|
88
|
+
╰ **Naming Convention** (naming-convention):\
|
|
89
|
+
╰ _Metadata_: <code>{"numMatches":0,"numBreak":0,"searchTimeMs":0,"processTimeMs":0}</code>\
|
|
90
|
+
_All queries together required ≈10 ms (1ms accuracy, total 208 ms)_
|
|
91
|
+
|
|
92
|
+
<details> <summary style="color:gray">Show Detailed Results as Json</summary>
|
|
93
|
+
|
|
94
|
+
The analysis required _207.6 ms_ (including parsing and normalization and the query) within the generation environment.
|
|
95
|
+
|
|
96
|
+
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.
|
|
97
|
+
Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those.
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"linter": {
|
|
105
|
+
"results": {
|
|
106
|
+
"deprecated-functions": {
|
|
107
|
+
"results": [],
|
|
108
|
+
".meta": {
|
|
109
|
+
"totalDeprecatedCalls": 0,
|
|
110
|
+
"totalDeprecatedFunctionDefinitions": 0,
|
|
111
|
+
"searchTimeMs": 2,
|
|
112
|
+
"processTimeMs": 0
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"file-path-validity": {
|
|
116
|
+
"results": [
|
|
117
|
+
{
|
|
118
|
+
"range": [
|
|
119
|
+
1,
|
|
120
|
+
1,
|
|
121
|
+
1,
|
|
122
|
+
23
|
|
123
|
+
],
|
|
124
|
+
"filePath": "/root/x.txt",
|
|
125
|
+
"certainty": "definitely"
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
".meta": {
|
|
129
|
+
"totalReads": 1,
|
|
130
|
+
"totalUnknown": 0,
|
|
131
|
+
"totalWritesBeforeAlways": 0,
|
|
132
|
+
"totalValid": 0,
|
|
133
|
+
"searchTimeMs": 4,
|
|
134
|
+
"processTimeMs": 1
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"seeded-randomness": {
|
|
138
|
+
"results": [],
|
|
139
|
+
".meta": {
|
|
140
|
+
"consumerCalls": 0,
|
|
141
|
+
"callsWithFunctionProducers": 0,
|
|
142
|
+
"callsWithAssignmentProducers": 0,
|
|
143
|
+
"callsWithNonConstantProducers": 0,
|
|
144
|
+
"searchTimeMs": 0,
|
|
145
|
+
"processTimeMs": 0
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"absolute-file-paths": {
|
|
149
|
+
"results": [
|
|
150
|
+
{
|
|
151
|
+
"certainty": "definitely",
|
|
152
|
+
"filePath": "/root/x.txt",
|
|
153
|
+
"range": [
|
|
154
|
+
1,
|
|
155
|
+
1,
|
|
156
|
+
1,
|
|
157
|
+
23
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
".meta": {
|
|
162
|
+
"totalConsidered": 1,
|
|
163
|
+
"totalUnknown": 0,
|
|
164
|
+
"searchTimeMs": 1,
|
|
165
|
+
"processTimeMs": 1
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"unused-definitions": {
|
|
169
|
+
"results": [],
|
|
170
|
+
".meta": {
|
|
171
|
+
"totalConsidered": 0,
|
|
172
|
+
"searchTimeMs": 0,
|
|
173
|
+
"processTimeMs": 0
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"naming-convention": {
|
|
177
|
+
"results": [],
|
|
178
|
+
".meta": {
|
|
179
|
+
"numMatches": 0,
|
|
180
|
+
"numBreak": 0,
|
|
181
|
+
"searchTimeMs": 0,
|
|
182
|
+
"processTimeMs": 0
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
".meta": {
|
|
187
|
+
"timing": 10
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
".meta": {
|
|
191
|
+
"timing": 10
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
</details>
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
</details>
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
</details>
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
15
219
|
* 🍕 **program slicing**\
|
|
16
220
|
Given a point of interest like the visualization of a plot, _flowR_ reduces the program to just the parts which are relevant
|
|
17
221
|
for the computation of the point of interest.
|
|
@@ -51,7 +255,7 @@ It offers a wide variety of features, for example:
|
|
|
51
255
|
|
|
52
256
|
```shell
|
|
53
257
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
54
|
-
flowR repl using flowR v2.2.
|
|
258
|
+
flowR repl using flowR v2.2.15, R v4.5.0 (r-shell engine)
|
|
55
259
|
R> :slicer test/testfiles/example.R --criterion "11@sum"
|
|
56
260
|
```
|
|
57
261
|
|
|
@@ -98,7 +302,7 @@ It offers a wide variety of features, for example:
|
|
|
98
302
|
|
|
99
303
|
|
|
100
304
|
* 🚀 **fast data- and control-flow graphs**\
|
|
101
|
-
Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">
|
|
305
|
+
Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">136.2 ms</span></i> (as of Jun 2, 2025),
|
|
102
306
|
_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
307
|
and consult the [wiki pages](https://github.com/flowr-analysis/flowr/wiki/Dataflow-Graph) for more details on the dataflow graph.
|
|
104
308
|
|
|
@@ -134,7 +338,7 @@ It offers a wide variety of features, for example:
|
|
|
134
338
|
|
|
135
339
|
```shell
|
|
136
340
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
137
|
-
flowR repl using flowR v2.2.
|
|
341
|
+
flowR repl using flowR v2.2.15, R v4.5.0 (r-shell engine)
|
|
138
342
|
R> :dataflow* test/testfiles/example.R
|
|
139
343
|
```
|
|
140
344
|
|
|
@@ -411,7 +615,7 @@ It offers a wide variety of features, for example:
|
|
|
411
615
|
linkStyle 68 stroke:gray;
|
|
412
616
|
35 -->|"CD-True"| 36
|
|
413
617
|
linkStyle 69 stroke:gray,color:gray;
|
|
414
|
-
36 -->|"
|
|
618
|
+
36 -->|"argument"| 12
|
|
415
619
|
36 -->|"reads, argument"| 20
|
|
416
620
|
36 -->|"argument, non-standard-evaluation"| 35
|
|
417
621
|
36 -.->|"reads, calls"| built-in:for
|
|
@@ -435,7 +639,7 @@ It offers a wide variety of features, for example:
|
|
|
435
639
|
```
|
|
436
640
|
|
|
437
641
|
|
|
438
|
-
(The analysis required
|
|
642
|
+
(The analysis required _13.9 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
|
|
439
643
|
|
|
440
644
|
|
|
441
645
|
|
|
@@ -478,7 +682,7 @@ You can enter <span title="Description (Repl Command): Show help information (al
|
|
|
478
682
|
|
|
479
683
|
<summary>Example REPL session</summary>
|
|
480
684
|
|
|
481
|
-

|
|
685
|
+

|
|
482
686
|
|
|
483
687
|
</details>
|
|
484
688
|
|
package/benchmark/slicer.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { RParseRequestFromFile, RParseRequestFromText } from '../r-bridge/r
|
|
|
13
13
|
import type { SlicingCriteriaFilter } from '../slicing/criterion/collect-all';
|
|
14
14
|
import type { AutoSelectPredicate } from '../reconstruct/auto-select/auto-select-defaults';
|
|
15
15
|
import type { KnownParserName } from '../r-bridge/parser';
|
|
16
|
+
import type { FlowrConfigOptions } from '../config';
|
|
16
17
|
/**
|
|
17
18
|
* The logger to be used for benchmarking as a global object.
|
|
18
19
|
*/
|
|
@@ -69,7 +70,7 @@ export declare class BenchmarkSlicer {
|
|
|
69
70
|
* Initialize the slicer on the given request.
|
|
70
71
|
* Can only be called once for each instance.
|
|
71
72
|
*/
|
|
72
|
-
init(request: RParseRequestFromFile | RParseRequestFromText, autoSelectIf?: AutoSelectPredicate, threshold?: number): Promise<void>;
|
|
73
|
+
init(request: RParseRequestFromFile | RParseRequestFromText, config: FlowrConfigOptions, autoSelectIf?: AutoSelectPredicate, threshold?: number): Promise<void>;
|
|
73
74
|
private calculateStatsAfterInit;
|
|
74
75
|
/**
|
|
75
76
|
* Counts the number of stored indices in the dataflow graph created by the pointer analysis.
|
|
@@ -113,6 +114,7 @@ export declare class BenchmarkSlicer {
|
|
|
113
114
|
sampleCount?: number;
|
|
114
115
|
maxSliceCount?: number;
|
|
115
116
|
sampleStrategy?: SamplingStrategy;
|
|
117
|
+
seed?: string;
|
|
116
118
|
}): Promise<number>;
|
|
117
119
|
/**
|
|
118
120
|
* Retrieves the final stats and closes the shell session.
|
package/benchmark/slicer.js
CHANGED
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.BenchmarkSlicer = exports.benchmarkLogger = void 0;
|
|
11
11
|
const stopwatch_1 = require("./stopwatch");
|
|
12
12
|
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const seedrandom_1 = __importDefault(require("seedrandom"));
|
|
13
14
|
const log_1 = require("../util/log");
|
|
14
15
|
const assert_1 = require("../util/assert");
|
|
15
16
|
const strings_1 = require("../util/text/strings");
|
|
@@ -24,6 +25,7 @@ const tree_sitter_types_1 = require("../r-bridge/lang-4.x/tree-sitter/tree-sitte
|
|
|
24
25
|
const tree_sitter_executor_1 = require("../r-bridge/lang-4.x/tree-sitter/tree-sitter-executor");
|
|
25
26
|
const vertex_1 = require("../dataflow/graph/vertex");
|
|
26
27
|
const arrays_1 = require("../util/collections/arrays");
|
|
28
|
+
const config_1 = require("../config");
|
|
27
29
|
/**
|
|
28
30
|
* The logger to be used for benchmarking as a global object.
|
|
29
31
|
*/
|
|
@@ -51,15 +53,15 @@ class BenchmarkSlicer {
|
|
|
51
53
|
* Initialize the slicer on the given request.
|
|
52
54
|
* Can only be called once for each instance.
|
|
53
55
|
*/
|
|
54
|
-
async init(request, autoSelectIf, threshold) {
|
|
56
|
+
async init(request, config, autoSelectIf, threshold) {
|
|
55
57
|
(0, assert_1.guard)(this.stats === undefined, 'cannot initialize the slicer twice');
|
|
56
58
|
// we know these are in sync so we just cast to one of them
|
|
57
59
|
this.parser = await this.commonMeasurements.measure('initialize R session', async () => {
|
|
58
60
|
if (this.parserName === 'r-shell') {
|
|
59
|
-
return new shell_1.RShell();
|
|
61
|
+
return new shell_1.RShell((0, config_1.getEngineConfig)(config, 'r-shell'));
|
|
60
62
|
}
|
|
61
63
|
else {
|
|
62
|
-
await tree_sitter_executor_1.TreeSitterExecutor.initTreeSitter();
|
|
64
|
+
await tree_sitter_executor_1.TreeSitterExecutor.initTreeSitter((0, config_1.getEngineConfig)(config, 'tree-sitter'));
|
|
63
65
|
return new tree_sitter_executor_1.TreeSitterExecutor();
|
|
64
66
|
}
|
|
65
67
|
});
|
|
@@ -68,7 +70,7 @@ class BenchmarkSlicer {
|
|
|
68
70
|
criterion: [],
|
|
69
71
|
autoSelectIf,
|
|
70
72
|
threshold,
|
|
71
|
-
});
|
|
73
|
+
}, config);
|
|
72
74
|
this.loadedXml = (await this.measureCommonStep('parse', 'retrieve AST from R code')).parsed;
|
|
73
75
|
this.normalizedAst = await this.measureCommonStep('normalize', 'normalize R AST');
|
|
74
76
|
this.dataflow = await this.measureCommonStep('dataflow', 'produce dataflow information');
|
|
@@ -301,7 +303,8 @@ class BenchmarkSlicer {
|
|
|
301
303
|
allCriteria = (0, arrays_1.equidistantSampling)(allCriteria, sampleCount, 'ceil');
|
|
302
304
|
}
|
|
303
305
|
else {
|
|
304
|
-
|
|
306
|
+
const random = options.seed ? (0, seedrandom_1.default)(options.seed) : Math.random;
|
|
307
|
+
allCriteria.sort(() => random() - 0.5);
|
|
305
308
|
allCriteria.length = Math.min(allCriteria.length, sampleCount);
|
|
306
309
|
}
|
|
307
310
|
}
|
|
@@ -2,11 +2,12 @@ import type { Reduction, SummarizedSlicerStats, TimePerToken } from '../data';
|
|
|
2
2
|
import type { SummarizedMeasurement } from '../../../util/summarizer';
|
|
3
3
|
import type { PerSliceStats, SlicerStats } from '../../stats/stats';
|
|
4
4
|
import type { SlicingCriteria } from '../../../slicing/criterion/parse';
|
|
5
|
+
import type { RShellEngineConfig } from '../../../config';
|
|
5
6
|
/**
|
|
6
7
|
* Summarizes the given stats by calculating the min, max, median, mean, and the standard deviation for each measurement.
|
|
7
8
|
* @see Slicer
|
|
8
9
|
*/
|
|
9
|
-
export declare function summarizeSlicerStats(stats: SlicerStats, report?: (criteria: SlicingCriteria, stats: PerSliceStats) => void): Promise<Readonly<SummarizedSlicerStats>>;
|
|
10
|
+
export declare function summarizeSlicerStats(stats: SlicerStats, report?: (criteria: SlicingCriteria, stats: PerSliceStats) => void, engineConf?: RShellEngineConfig): Promise<Readonly<SummarizedSlicerStats>>;
|
|
10
11
|
export declare function summarizeSummarizedMeasurement(data: SummarizedMeasurement[]): SummarizedMeasurement;
|
|
11
12
|
export declare function summarizeSummarizedReductions(reductions: Reduction<SummarizedMeasurement>[]): Reduction<SummarizedMeasurement>;
|
|
12
13
|
export declare function summarizeSummarizedTimePerToken(times: TimePerToken[]): TimePerToken;
|
|
@@ -107,10 +107,10 @@ function calculateReductionForSlice(input, dataflow, perSlice, ignoreFluff) {
|
|
|
107
107
|
* @see Slicer
|
|
108
108
|
*/
|
|
109
109
|
async function summarizeSlicerStats(stats, report = () => {
|
|
110
|
-
}) {
|
|
110
|
+
}, engineConf) {
|
|
111
111
|
const collect = new defaultmap_1.DefaultMap(() => []);
|
|
112
112
|
const sizeOfSliceCriteria = [];
|
|
113
|
-
const reParseShellSession = new shell_1.RShell();
|
|
113
|
+
const reParseShellSession = new shell_1.RShell(engineConf);
|
|
114
114
|
const sliceTimes = [];
|
|
115
115
|
const reconstructTimes = [];
|
|
116
116
|
const totalTimes = [];
|
package/cli/benchmark-app.d.ts
CHANGED
package/cli/benchmark-app.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const fs_1 = __importDefault(require("fs"));
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const seedrandom_1 = __importDefault(require("seedrandom"));
|
|
8
9
|
const assert_1 = require("../util/assert");
|
|
9
10
|
const files_1 = require("../util/files");
|
|
10
11
|
const log_1 = require("../util/log");
|
|
@@ -56,8 +57,9 @@ async function benchmark() {
|
|
|
56
57
|
}
|
|
57
58
|
if (options.limit) {
|
|
58
59
|
log_1.log.info(`limiting to ${options.limit} files`);
|
|
60
|
+
const random = options.seed ? (0, seedrandom_1.default)(options.seed) : Math.random;
|
|
59
61
|
// shuffle and limit
|
|
60
|
-
files.sort(() =>
|
|
62
|
+
files.sort(() => random() - 0.5);
|
|
61
63
|
}
|
|
62
64
|
const limit = options.limit ?? files.length;
|
|
63
65
|
const verboseAdd = options.verbose ? ['--verbose'] : [];
|
|
@@ -71,6 +73,7 @@ async function benchmark() {
|
|
|
71
73
|
'--max-slices', `${options['max-file-slices']}`,
|
|
72
74
|
...(options.threshold ? ['--threshold', `${options.threshold}`] : []),
|
|
73
75
|
'--sampling-strategy', options['sampling-strategy'],
|
|
76
|
+
...(options.seed ? ['--seed', options.seed] : []),
|
|
74
77
|
]);
|
|
75
78
|
const runs = options.runs ?? 1;
|
|
76
79
|
for (let i = 1; i <= runs; i++) {
|
|
@@ -39,12 +39,11 @@ async function benchmark() {
|
|
|
39
39
|
fs_1.default.mkdirSync(directory, { recursive: true });
|
|
40
40
|
}
|
|
41
41
|
// Enable pointer analysis if requested, otherwise disable it
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
42
|
+
const config = (0, config_1.getConfig)();
|
|
43
|
+
(0, config_1.amendConfig)(config, c => {
|
|
44
|
+
c.solver.pointerTracking = options['enable-pointer-tracking'];
|
|
45
|
+
return c;
|
|
46
|
+
});
|
|
48
47
|
// ensure the file exists
|
|
49
48
|
const fileStat = fs_1.default.statSync(options.input);
|
|
50
49
|
(0, assert_1.guard)(fileStat.isFile(), `File ${options.input} does not exist or is no file`);
|
|
@@ -52,7 +51,7 @@ async function benchmark() {
|
|
|
52
51
|
const maxSlices = options['max-slices'] ?? -1;
|
|
53
52
|
const slicer = new slicer_1.BenchmarkSlicer(options.parser);
|
|
54
53
|
try {
|
|
55
|
-
await slicer.init(request, undefined, options.threshold);
|
|
54
|
+
await slicer.init(request, config, undefined, options.threshold);
|
|
56
55
|
// ${escape}1F${escape}1G${escape}2K for line reset
|
|
57
56
|
if (options.slice === 'all') {
|
|
58
57
|
const count = await slicer.sliceForAll(all_variables_1.DefaultAllVariablesFilter, (i, total, arr) => console.log(`${prefix} Slicing ${i + 1}/${total} [${JSON.stringify(arr[i])}]`), { maxSliceCount: maxSlices });
|
|
@@ -66,7 +65,7 @@ async function benchmark() {
|
|
|
66
65
|
else {
|
|
67
66
|
const limit = parseInt(options.slice);
|
|
68
67
|
console.log(`${prefix} Slicing up to ${limit} possible slices`);
|
|
69
|
-
const count = await slicer.sliceForAll(all_variables_1.DefaultAllVariablesFilter, (i, total, arr) => console.log(`${prefix} Slicing ${i + 1}/${total} [${JSON.stringify(arr[i])}]`), { sampleCount: limit, maxSliceCount: maxSlices, sampleStrategy: options['sampling-strategy'] });
|
|
68
|
+
const count = await slicer.sliceForAll(all_variables_1.DefaultAllVariablesFilter, (i, total, arr) => console.log(`${prefix} Slicing ${i + 1}/${total} [${JSON.stringify(arr[i])}]`), { sampleCount: limit, maxSliceCount: maxSlices, sampleStrategy: options['sampling-strategy'], seed: options.seed });
|
|
70
69
|
console.log(`${prefix} Completed Slicing`);
|
|
71
70
|
(0, assert_1.guard)(count >= 0, `Number of slices exceeded limit of ${maxSlices} with ${-count} slices, skipping in count`);
|
|
72
71
|
(0, assert_1.guard)(count > 0, `No possible slices found for ${options.input}, skipping in count`);
|
package/cli/common/options.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.benchmarkOptions = [
|
|
|
16
16
|
{ name: 'help', alias: 'h', type: Boolean, description: 'Print this usage guide' },
|
|
17
17
|
{ name: 'limit', alias: 'l', type: Number, description: 'Limit the number of files to process (if given, this will choose these files randomly and add the chosen names to the output' },
|
|
18
18
|
{ name: 'runs', alias: 'r', type: Number, description: 'The amount of benchmark runs that should be done, out of which an average will be calculated' },
|
|
19
|
+
{ name: 'seed', type: String, description: 'The random seed for sampling the files if a limit is set, and for sampling the slicing criteria if a maximum is set' },
|
|
19
20
|
{ name: 'input', alias: 'i', type: String, description: 'Pass a folder or file as src to read from. Alternatively, pass a single JSON file that contains a list of paths.', multiple: true, defaultOption: true, defaultValue: [], typeLabel: '{underline files/folders}' },
|
|
20
21
|
{ name: 'parallel', alias: 'p', type: String, description: 'Number of parallel executors (defaults to {italic max(cpu.count-1, 1)})', defaultValue: Math.max(os_1.default.cpus().length - 1, 1), typeLabel: '{underline number}' },
|
|
21
22
|
{ name: 'slice', alias: 's', type: String, description: 'Automatically slice for *all* variables (default) or *no* slicing and only parsing/dataflow construction. Numbers will indicate: sample X random slices from all.', defaultValue: 'all', typeLabel: '{underline all/no}' },
|
|
@@ -40,6 +41,7 @@ exports.benchmarkHelperOptions = [
|
|
|
40
41
|
{ name: 'max-slices', type: Number, description: 'If file has more than passed number of slices, the file is not processed', defaultValue: -1, typeLabel: '{underline number}' },
|
|
41
42
|
{ name: 'threshold', alias: 't', type: Number, description: 'How many re-visits of the same node are ok?', defaultValue: undefined, typeLabel: '{underline number}' },
|
|
42
43
|
{ name: 'sampling-strategy', type: String, description: 'Which strategy to use, when sampling is enabled', defaultValue: 'random', typeLabel: '{underline random/equidistant}' },
|
|
44
|
+
{ name: 'seed', type: String, description: 'The random seed for sampling the slicing criteria if a maximum is set' },
|
|
43
45
|
];
|
|
44
46
|
exports.exportQuadsOptions = [
|
|
45
47
|
{ name: 'verbose', alias: 'v', type: Boolean, description: 'Run with verbose logging' },
|
package/cli/export-quads-app.js
CHANGED
|
@@ -10,6 +10,7 @@ const files_1 = require("../util/files");
|
|
|
10
10
|
const script_1 = require("./common/script");
|
|
11
11
|
const shell_1 = require("../r-bridge/shell");
|
|
12
12
|
const retriever_1 = require("../r-bridge/retriever");
|
|
13
|
+
const config_1 = require("../config");
|
|
13
14
|
const options = (0, script_1.processCommandLineArgs)('export-quads', [], {
|
|
14
15
|
subtitle: 'Generate RDF N-Quads from the AST of a given R script',
|
|
15
16
|
examples: [
|
|
@@ -17,7 +18,7 @@ const options = (0, script_1.processCommandLineArgs)('export-quads', [], {
|
|
|
17
18
|
'{bold --help}'
|
|
18
19
|
]
|
|
19
20
|
});
|
|
20
|
-
const shell = new shell_1.RShell();
|
|
21
|
+
const shell = new shell_1.RShell((0, config_1.getEngineConfig)((0, config_1.getConfig)(), 'r-shell'));
|
|
21
22
|
async function writeQuadForSingleFile(request, output) {
|
|
22
23
|
const normalized = await (0, retriever_1.retrieveNormalizedAstFromRCode)(request, shell);
|
|
23
24
|
const serialized = (0, quads_1.serialize2quads)(normalized.ast, { context: request.content });
|