@eagleoutice/flowr 2.9.9 → 2.9.10
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 +34 -29
- package/abstract-interpretation/absint-visitor.d.ts +16 -14
- package/abstract-interpretation/absint-visitor.js +91 -46
- package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -5
- package/abstract-interpretation/data-frame/shape-inference.js +4 -5
- package/abstract-interpretation/domains/abstract-domain.d.ts +4 -4
- package/abstract-interpretation/domains/abstract-domain.js +8 -8
- package/abstract-interpretation/domains/mapped-abstract-domain.d.ts +12 -5
- package/abstract-interpretation/domains/mapped-abstract-domain.js +47 -23
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +30 -1
- package/abstract-interpretation/domains/state-abstract-domain.js +130 -4
- package/control-flow/cfg-simplification.d.ts +1 -0
- package/control-flow/cfg-simplification.js +1 -0
- package/control-flow/extract-cfg.js +33 -15
- package/control-flow/semantic-cfg-guided-visitor.js +1 -0
- package/dataflow/environments/built-in.d.ts +4 -0
- package/dataflow/environments/built-in.js +17 -5
- package/dataflow/environments/default-builtin-config.d.ts +4 -8
- package/dataflow/environments/default-builtin-config.js +8 -5
- package/dataflow/environments/reference-to-maybe.d.ts +8 -0
- package/dataflow/environments/reference-to-maybe.js +46 -3
- package/dataflow/eval/resolve/alias-tracking.d.ts +1 -1
- package/dataflow/eval/resolve/alias-tracking.js +4 -5
- package/dataflow/eval/resolve/resolve.js +8 -7
- package/dataflow/graph/graph.d.ts +1 -1
- package/dataflow/graph/graph.js +9 -10
- package/dataflow/graph/unknown-side-effect.js +3 -1
- package/dataflow/info.d.ts +4 -0
- package/dataflow/info.js +2 -2
- package/dataflow/internal/linker.d.ts +2 -2
- package/dataflow/internal/linker.js +52 -27
- package/dataflow/internal/process/functions/call/argument/make-argument.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +15 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.js +4 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +22 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +22 -19
- package/dataflow/internal/process/functions/call/known-call-handling.js +0 -2
- package/documentation/wiki-absint.js +7 -8
- package/linter/rules/dead-code.js +1 -1
- package/linter/rules/seeded-randomness.js +1 -1
- package/linter/rules/unused-definition.js +1 -1
- package/package.json +7 -7
- package/project/plugins/file-plugins/files/flowr-description-file.d.ts +4 -0
- package/project/plugins/file-plugins/files/flowr-description-file.js +4 -0
- package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +1 -1
- package/queries/catalog/df-shape-query/df-shape-query-format.js +3 -3
- package/r-bridge/lang-4.x/ast/model/processing/decorate.js +23 -17
- package/r-bridge/lang-4.x/ast/model/processing/role.d.ts +18 -17
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +31 -13
- package/statistics/features/supported/data-access/data-access.js +2 -2
- package/util/mermaid/ast.js +1 -1
- package/util/mermaid/dfg.js +6 -5
- package/util/version.js +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ It offers a wide variety of features, for example:
|
|
|
24
24
|
|
|
25
25
|
```shell
|
|
26
26
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
27
|
-
flowR repl using flowR v2.9.
|
|
27
|
+
flowR repl using flowR v2.9.9, R grammar v14 (tree-sitter engine)
|
|
28
28
|
R> :query @linter "read.csv(\"/root/x.txt\")"
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -33,19 +33,19 @@ It offers a wide variety of features, for example:
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
```text
|
|
36
|
-
Query: linter (
|
|
36
|
+
Query: linter (3 ms)
|
|
37
37
|
╰ Deprecated Functions (deprecated-functions):
|
|
38
|
-
╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs:
|
|
38
|
+
╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 1, processTimeMs: 0
|
|
39
39
|
╰ File Path Validity (file-path-validity):
|
|
40
40
|
╰ certain:
|
|
41
41
|
╰ Path `/root/x.txt` at 1.1-23
|
|
42
|
-
╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs:
|
|
42
|
+
╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 0, processTimeMs: 0
|
|
43
43
|
╰ Seeded Randomness (seeded-randomness):
|
|
44
44
|
╰ Metadata: consumerCalls: 0, callsWithFunctionProducers: 0, callsWithAssignmentProducers: 0, callsWithNonConstantProducers: 0, callsWithOtherBranchProducers: 0, searchTimeMs: 0, processTimeMs: 0
|
|
45
45
|
╰ Absolute Paths (absolute-file-paths):
|
|
46
46
|
╰ certain:
|
|
47
47
|
╰ Path `/root/x.txt` at 1.1-23
|
|
48
|
-
╰ Metadata: totalConsidered: 1, totalUnknown: 0, searchTimeMs:
|
|
48
|
+
╰ Metadata: totalConsidered: 1, totalUnknown: 0, searchTimeMs: 1, processTimeMs: 0
|
|
49
49
|
╰ Unused Definitions (unused-definitions):
|
|
50
50
|
╰ Metadata: totalConsidered: 0, searchTimeMs: 0, processTimeMs: 0
|
|
51
51
|
╰ Naming Convention (naming-convention):
|
|
@@ -53,12 +53,12 @@ It offers a wide variety of features, for example:
|
|
|
53
53
|
╰ Network Functions (network-functions):
|
|
54
54
|
╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0
|
|
55
55
|
╰ Dataframe Access Validation (dataframe-access-validation):
|
|
56
|
-
╰ Metadata: numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs:
|
|
56
|
+
╰ Metadata: numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs: 0, processTimeMs: 0
|
|
57
57
|
╰ Dead Code (dead-code):
|
|
58
|
-
╰ Metadata: consideredNodes: 5, searchTimeMs:
|
|
58
|
+
╰ Metadata: consideredNodes: 5, searchTimeMs: 1, processTimeMs: 0
|
|
59
59
|
╰ Useless Loops (useless-loop):
|
|
60
60
|
╰ Metadata: numOfUselessLoops: 0, searchTimeMs: 0, processTimeMs: 0
|
|
61
|
-
All queries together required ≈
|
|
61
|
+
All queries together required ≈3 ms (1ms accuracy, total 4 ms)
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
|
|
@@ -82,7 +82,7 @@ It offers a wide variety of features, for example:
|
|
|
82
82
|
|
|
83
83
|
Query: **linter** (3 ms)\
|
|
84
84
|
╰ **Deprecated Functions** (deprecated-functions):\
|
|
85
|
-
╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs:
|
|
85
|
+
╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 1, processTimeMs: 0</code>\
|
|
86
86
|
╰ **File Path Validity** (file-path-validity):\
|
|
87
87
|
╰ certain:\
|
|
88
88
|
╰ Path `/root/x.txt` at 1.1-23\
|
|
@@ -92,7 +92,7 @@ It offers a wide variety of features, for example:
|
|
|
92
92
|
╰ **Absolute Paths** (absolute-file-paths):\
|
|
93
93
|
╰ certain:\
|
|
94
94
|
╰ Path `/root/x.txt` at 1.1-23\
|
|
95
|
-
╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs:
|
|
95
|
+
╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
96
96
|
╰ **Unused Definitions** (unused-definitions):\
|
|
97
97
|
╰ _Metadata_: <code>totalConsidered: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
98
98
|
╰ **Naming Convention** (naming-convention):\
|
|
@@ -100,7 +100,7 @@ It offers a wide variety of features, for example:
|
|
|
100
100
|
╰ **Network Functions** (network-functions):\
|
|
101
101
|
╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
102
102
|
╰ **Dataframe Access Validation** (dataframe-access-validation):\
|
|
103
|
-
╰ _Metadata_: <code>numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs:
|
|
103
|
+
╰ _Metadata_: <code>numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs: 1, processTimeMs: 0</code>\
|
|
104
104
|
╰ **Dead Code** (dead-code):\
|
|
105
105
|
╰ _Metadata_: <code>consideredNodes: 5, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
106
106
|
╰ **Useless Loops** (useless-loop):\
|
|
@@ -109,7 +109,7 @@ It offers a wide variety of features, for example:
|
|
|
109
109
|
|
|
110
110
|
<details> <summary style="color:gray">Show Detailed Results as Json</summary>
|
|
111
111
|
|
|
112
|
-
The analysis required _3.
|
|
112
|
+
The analysis required _3.1 ms_ (including parsing and normalization and the query) within the generation environment.
|
|
113
113
|
|
|
114
114
|
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.
|
|
115
115
|
Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those.
|
|
@@ -126,7 +126,7 @@ It offers a wide variety of features, for example:
|
|
|
126
126
|
".meta": {
|
|
127
127
|
"totalCalls": 0,
|
|
128
128
|
"totalFunctionDefinitions": 0,
|
|
129
|
-
"searchTimeMs":
|
|
129
|
+
"searchTimeMs": 1,
|
|
130
130
|
"processTimeMs": 0
|
|
131
131
|
}
|
|
132
132
|
},
|
|
@@ -181,7 +181,7 @@ It offers a wide variety of features, for example:
|
|
|
181
181
|
".meta": {
|
|
182
182
|
"totalConsidered": 1,
|
|
183
183
|
"totalUnknown": 0,
|
|
184
|
-
"searchTimeMs":
|
|
184
|
+
"searchTimeMs": 0,
|
|
185
185
|
"processTimeMs": 0
|
|
186
186
|
}
|
|
187
187
|
},
|
|
@@ -217,8 +217,8 @@ It offers a wide variety of features, for example:
|
|
|
217
217
|
"numOperations": 0,
|
|
218
218
|
"numAccesses": 0,
|
|
219
219
|
"totalAccessed": 0,
|
|
220
|
-
"searchTimeMs":
|
|
221
|
-
"processTimeMs":
|
|
220
|
+
"searchTimeMs": 1,
|
|
221
|
+
"processTimeMs": 0
|
|
222
222
|
}
|
|
223
223
|
},
|
|
224
224
|
"dead-code": {
|
|
@@ -308,7 +308,7 @@ It offers a wide variety of features, for example:
|
|
|
308
308
|
|
|
309
309
|
```shell
|
|
310
310
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
311
|
-
flowR repl using flowR v2.9.
|
|
311
|
+
flowR repl using flowR v2.9.9, R grammar v14 (tree-sitter engine)
|
|
312
312
|
R> :query @static-slice (11@sum) file://test/testfiles/example.R
|
|
313
313
|
```
|
|
314
314
|
|
|
@@ -322,7 +322,7 @@ It offers a wide variety of features, for example:
|
|
|
322
322
|
N <- 10
|
|
323
323
|
for(i in 1:(N-1)) sum <- sum + i + w
|
|
324
324
|
sum
|
|
325
|
-
All queries together required ≈3 ms (1ms accuracy, total
|
|
325
|
+
All queries together required ≈3 ms (1ms accuracy, total 4 ms)
|
|
326
326
|
```
|
|
327
327
|
|
|
328
328
|
|
|
@@ -356,7 +356,7 @@ It offers a wide variety of features, for example:
|
|
|
356
356
|
|
|
357
357
|
|
|
358
358
|
* 🚀 **fast call-graph, data-, and control-flow graphs**\
|
|
359
|
-
Within just [<i><span title="This measurement is automatically fetched from the latest benchmark!">
|
|
359
|
+
Within just [<i><span title="This measurement is automatically fetched from the latest benchmark!">112.3 ms</span></i> (as of Feb 9, 2026)](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark),
|
|
360
360
|
_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,
|
|
361
361
|
and consult the [wiki pages](https://github.com/flowr-analysis/flowr/wiki/wiki/dataflow-graph) for more details on the [dataflow graphs](https://github.com/flowr-analysis/flowr/wiki/wiki/dataflow-graph) as well as [call graphs](https://github.com/flowr-analysis/flowr/wiki/wiki/dataflow-graph#perspectives-cg).
|
|
362
362
|
|
|
@@ -392,7 +392,7 @@ It offers a wide variety of features, for example:
|
|
|
392
392
|
|
|
393
393
|
```shell
|
|
394
394
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
395
|
-
flowR repl using flowR v2.9.
|
|
395
|
+
flowR repl using flowR v2.9.9, R grammar v14 (tree-sitter engine)
|
|
396
396
|
R> :dataflow* test/testfiles/example.R
|
|
397
397
|
```
|
|
398
398
|
|
|
@@ -401,7 +401,7 @@ It offers a wide variety of features, for example:
|
|
|
401
401
|
|
|
402
402
|
|
|
403
403
|
```text
|
|
404
|
-
https://mermaid.live/view#base64:
|
|
404
|
+
https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMChbXCJgIzkxO1JTeW1ib2wjOTM7IHRlc3RcbiAgICAgICgwKVxuICAgICAgKjEuMS00KmBcIl0pXG4gICAlJSBObyBlZGdlcyBmb3VuZCBmb3IgMFxuICAgIDEoW1wiYCM5MTtSU3ltYm9sIzkzOyB0ZXN0ZmlsZXNcbiAgICAgICgxKVxuICAgICAgKjEuNi0xNCpgXCJdKVxuICAgJSUgTm8gZWRnZXMgZm91bmQgZm9yIDFcbiAgICAyW1tcImAjOTE7UkJpbmFyeU9wIzkzOyAvXG4gICAgICAoMilcbiAgICAgICoxLjEtMTQqXG4gICAgKDAsIDEpYFwiXV1cbiAgICBidWlsdC1pbjpfW1wiYEJ1aWx0LUluOlxuL2BcIl1cbiAgICBzdHlsZSBidWlsdC1pbjpfIHN0cm9rZTpncmF5LGZpbGw6Z3JheSxzdHJva2Utd2lkdGg6MnB4LG9wYWNpdHk6Ljg7XG4gICAgMyhbXCJgIzkxO1JTeW1ib2wjOTM7IGV4YW1wbGUuUlxuICAgICAgKDMpXG4gICAgICAqMS4xNi0yNCpgXCJdKVxuICAgJSUgTm8gZWRnZXMgZm91bmQgZm9yIDNcbiAgICA0W1tcImAjOTE7UkJpbmFyeU9wIzkzOyAvXG4gICAgICAoNClcbiAgICAgICoxLjEtMjQqXG4gICAgKDIsIDMpYFwiXV1cbiAgICAyIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAwXG4gICAgMiAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgMVxuICAgIDIgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDIgc3Ryb2tlOmdyYXk7XG4gICAgNCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgMlxuICAgIDQgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDNcbiAgICA0IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46X1xuICAgIGxpbmtTdHlsZSA1IHN0cm9rZTpncmF5OyIsIm1lcm1haWQiOnsiYXV0b1N5bmMiOnRydWV9fQ==
|
|
405
405
|
```
|
|
406
406
|
|
|
407
407
|
|
|
@@ -416,6 +416,7 @@ It offers a wide variety of features, for example:
|
|
|
416
416
|
1{{"`#91;RNumber#93; 0
|
|
417
417
|
(1)
|
|
418
418
|
*1.8*`"}}
|
|
419
|
+
%% No edges found for 1
|
|
419
420
|
0["`#91;RSymbol#93; sum
|
|
420
421
|
(0)
|
|
421
422
|
*1.1-3*`"]
|
|
@@ -429,6 +430,7 @@ It offers a wide variety of features, for example:
|
|
|
429
430
|
4{{"`#91;RNumber#93; 1
|
|
430
431
|
(4)
|
|
431
432
|
*2.12*`"}}
|
|
433
|
+
%% No edges found for 4
|
|
432
434
|
3["`#91;RSymbol#93; product
|
|
433
435
|
(3)
|
|
434
436
|
*2.1-7*`"]
|
|
@@ -439,6 +441,7 @@ It offers a wide variety of features, for example:
|
|
|
439
441
|
7{{"`#91;RNumber#93; 7
|
|
440
442
|
(7)
|
|
441
443
|
*3.6*`"}}
|
|
444
|
+
%% No edges found for 7
|
|
442
445
|
6["`#91;RSymbol#93; w
|
|
443
446
|
(6)
|
|
444
447
|
*3.1*`"]
|
|
@@ -449,6 +452,7 @@ It offers a wide variety of features, for example:
|
|
|
449
452
|
10{{"`#91;RNumber#93; 10
|
|
450
453
|
(10)
|
|
451
454
|
*4.6-7*`"}}
|
|
455
|
+
%% No edges found for 10
|
|
452
456
|
9["`#91;RSymbol#93; N
|
|
453
457
|
(9)
|
|
454
458
|
*4.1*`"]
|
|
@@ -462,12 +466,14 @@ It offers a wide variety of features, for example:
|
|
|
462
466
|
13{{"`#91;RNumber#93; 1
|
|
463
467
|
(13)
|
|
464
468
|
*6.11*`"}}
|
|
469
|
+
%% No edges found for 13
|
|
465
470
|
16(["`#91;RSymbol#93; N
|
|
466
471
|
(16)
|
|
467
472
|
*6.14*`"])
|
|
468
473
|
17{{"`#91;RNumber#93; 1
|
|
469
474
|
(17)
|
|
470
475
|
*6.16*`"}}
|
|
476
|
+
%% No edges found for 17
|
|
471
477
|
18[["`#91;RBinaryOp#93; #45;
|
|
472
478
|
(18)
|
|
473
479
|
*6.14-16*
|
|
@@ -544,16 +550,15 @@ It offers a wide variety of features, for example:
|
|
|
544
550
|
38{{"`#91;RString#93; #34;Sum#58;#34;
|
|
545
551
|
(38)
|
|
546
552
|
*11.5-10*`"}}
|
|
553
|
+
%% No edges found for 38
|
|
547
554
|
40(["`#91;RSymbol#93; sum
|
|
548
555
|
(40)
|
|
549
556
|
*11.13-15*`"])
|
|
550
|
-
built-in:sum["`Built-In:
|
|
551
|
-
sum`"]
|
|
552
|
-
style built-in:sum stroke:gray,fill:gray,stroke-width:2px,opacity:.8;
|
|
553
557
|
42{{"`#91;RString#93; #34;
|
|
554
558
|
#34;
|
|
555
559
|
(42)
|
|
556
560
|
*11.18-21*`"}}
|
|
561
|
+
%% No edges found for 42
|
|
557
562
|
44[["`#91;RFunctionCall#93; cat
|
|
558
563
|
(44)
|
|
559
564
|
*11.1-22*
|
|
@@ -564,6 +569,7 @@ It offers a wide variety of features, for example:
|
|
|
564
569
|
46{{"`#91;RString#93; #34;Product#58;#34;
|
|
565
570
|
(46)
|
|
566
571
|
*12.5-14*`"}}
|
|
572
|
+
%% No edges found for 46
|
|
567
573
|
48(["`#91;RSymbol#93; product
|
|
568
574
|
(48)
|
|
569
575
|
*12.17-23*`"])
|
|
@@ -571,6 +577,7 @@ It offers a wide variety of features, for example:
|
|
|
571
577
|
#34;
|
|
572
578
|
(50)
|
|
573
579
|
*12.26-29*`"}}
|
|
580
|
+
%% No edges found for 50
|
|
574
581
|
52[["`#91;RFunctionCall#93; cat
|
|
575
582
|
(52)
|
|
576
583
|
*12.1-30*
|
|
@@ -680,24 +687,22 @@ It offers a wide variety of features, for example:
|
|
|
680
687
|
linkStyle 75 stroke:gray;
|
|
681
688
|
40 -->|"reads"| 0
|
|
682
689
|
40 -->|"reads"| 23
|
|
683
|
-
40 -.->|"reads"| built-in:sum
|
|
684
|
-
linkStyle 78 stroke:gray;
|
|
685
690
|
44 -->|"argument"| 38
|
|
686
691
|
44 -->|"reads, argument"| 40
|
|
687
692
|
44 -->|"argument"| 42
|
|
688
693
|
44 -.->|"reads, calls"| built-in:cat
|
|
689
|
-
linkStyle
|
|
694
|
+
linkStyle 81 stroke:gray;
|
|
690
695
|
48 -->|"reads"| 3
|
|
691
696
|
48 -->|"reads"| 30
|
|
692
697
|
52 -->|"argument"| 46
|
|
693
698
|
52 -->|"reads, argument"| 48
|
|
694
699
|
52 -->|"argument"| 50
|
|
695
700
|
52 -.->|"reads, calls"| built-in:cat
|
|
696
|
-
linkStyle
|
|
701
|
+
linkStyle 87 stroke:gray;
|
|
697
702
|
```
|
|
698
703
|
|
|
699
704
|
|
|
700
|
-
(The analysis required _1.
|
|
705
|
+
(The analysis required _1.9 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
|
|
701
706
|
|
|
702
707
|
|
|
703
708
|
|
|
@@ -10,31 +10,37 @@ import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/
|
|
|
10
10
|
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
11
11
|
import { type AnyAbstractDomain } from './domains/abstract-domain';
|
|
12
12
|
import type { StateAbstractDomain } from './domains/state-abstract-domain';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
13
|
+
import { MutableStateAbstractDomain } from './domains/state-abstract-domain';
|
|
14
|
+
export type AbsintVisitorConfiguration = Omit<SemanticCfgGuidedVisitorConfiguration<NoInfo, ControlFlowInformation, NormalizedAst>, 'defaultVisitingOrder' | 'defaultVisitingType'>;
|
|
16
15
|
/**
|
|
17
16
|
* A control flow graph visitor to perform abstract interpretation.
|
|
18
17
|
*
|
|
19
18
|
* However, the visitor does not yet support inter-procedural abstract interpretation and abstract condition semantics.
|
|
20
19
|
*/
|
|
21
|
-
export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAbstractDomain, Config extends AbsintVisitorConfiguration
|
|
20
|
+
export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAbstractDomain, Config extends AbsintVisitorConfiguration = AbsintVisitorConfiguration> extends SemanticCfgGuidedVisitor<NoInfo, ControlFlowInformation, NormalizedAst, DataflowGraph, Config & {
|
|
22
21
|
defaultVisitingOrder: 'forward';
|
|
23
22
|
defaultVisitingType: 'exit';
|
|
24
23
|
}> {
|
|
25
24
|
/**
|
|
26
25
|
* The abstract trace of the abstract interpretation visitor mapping node IDs to the abstract state at the respective node.
|
|
27
26
|
*/
|
|
28
|
-
protected readonly trace: Map<NodeId,
|
|
27
|
+
protected readonly trace: Map<NodeId, MutableStateAbstractDomain<Domain>>;
|
|
29
28
|
/**
|
|
30
29
|
* The current abstract state domain at the currently processed AST node.
|
|
31
30
|
*/
|
|
32
|
-
|
|
31
|
+
private _currentState;
|
|
33
32
|
/**
|
|
34
33
|
* A set of nodes representing variable definitions that have already been visited but whose assignment has not yet been processed.
|
|
35
34
|
*/
|
|
36
35
|
private readonly unassigned;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the current abstract state has been copied/cloned and is save to modify in place.
|
|
38
|
+
*/
|
|
39
|
+
private stateCopied;
|
|
37
40
|
constructor(config: Config);
|
|
41
|
+
get currentState(): StateAbstractDomain<Domain>;
|
|
42
|
+
removeState(node: NodeId): void;
|
|
43
|
+
updateState(node: NodeId, value: Domain): void;
|
|
38
44
|
/**
|
|
39
45
|
* Resolves the inferred abstract value of an AST node.
|
|
40
46
|
* This requires that the abstract interpretation visitor has been completed, or at least started.
|
|
@@ -62,6 +68,7 @@ export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAb
|
|
|
62
68
|
*/
|
|
63
69
|
getAbstractTrace(): ReadonlyMap<NodeId, StateAbstractDomain<Domain>>;
|
|
64
70
|
start(): void;
|
|
71
|
+
protected startVisitor(start: readonly NodeId[]): void;
|
|
65
72
|
protected visitNode(vertexId: NodeId): boolean;
|
|
66
73
|
protected onDispatchFunctionCallOrigin(call: DataflowGraphVertexFunctionCall, origin: BuiltInProcName): void;
|
|
67
74
|
protected onVariableDefinition({ vertex }: {
|
|
@@ -93,21 +100,16 @@ export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAb
|
|
|
93
100
|
protected getPredecessorNodes(vertexId: NodeId): NodeId[];
|
|
94
101
|
/** Gets each variable origin that has already been visited and whose assignment has already been processed */
|
|
95
102
|
protected getVariableOrigins(nodeId: NodeId): NodeId[];
|
|
96
|
-
/** We only perform widening at `for`, `while`, or `repeat` loops with more than one
|
|
103
|
+
/** We only perform widening at `for`, `while`, or `repeat` loops with more than one ingoing CFG edge */
|
|
97
104
|
protected isWideningPoint(nodeId: NodeId): boolean;
|
|
98
|
-
/**
|
|
99
|
-
* Checks whether to continue visiting the control flow graph after a widening point.
|
|
100
|
-
* By default, we only continue visiting if the widening point is visited for the first time or the abstract state at the widening point changed.
|
|
101
|
-
*/
|
|
102
|
-
protected shouldContinueVisiting(wideningPoint: CfgVertex, oldState: StateAbstractDomain<Domain>): boolean;
|
|
103
105
|
/**
|
|
104
106
|
* Checks whether a control flow graph vertex should be skipped during visitation.
|
|
105
|
-
* By default, we only process vertices of leaf nodes and exit vertices (no entry nodes of complex nodes).
|
|
107
|
+
* By default, we only process entry vertices of widening points, vertices of leaf nodes, and exit vertices (no entry nodes of complex nodes).
|
|
106
108
|
*/
|
|
107
109
|
protected shouldSkipVertex(vertex: CfgVertex): boolean;
|
|
108
110
|
/**
|
|
109
111
|
* Whether widening should be performed at a widening point.
|
|
110
|
-
* By default, we perform widening when the number of
|
|
112
|
+
* By default, we perform widening when the number of visits of the widening point reaches the widening threshold of the config.
|
|
111
113
|
*/
|
|
112
114
|
protected shouldWiden(wideningPoint: CfgVertex): boolean;
|
|
113
115
|
}
|
|
@@ -10,6 +10,7 @@ const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-functi
|
|
|
10
10
|
const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
|
|
11
11
|
const assert_1 = require("../util/assert");
|
|
12
12
|
const abstract_domain_1 = require("./domains/abstract-domain");
|
|
13
|
+
const state_abstract_domain_1 = require("./domains/state-abstract-domain");
|
|
13
14
|
/**
|
|
14
15
|
* A control flow graph visitor to perform abstract interpretation.
|
|
15
16
|
*
|
|
@@ -23,14 +24,35 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
23
24
|
/**
|
|
24
25
|
* The current abstract state domain at the currently processed AST node.
|
|
25
26
|
*/
|
|
26
|
-
|
|
27
|
+
_currentState;
|
|
27
28
|
/**
|
|
28
29
|
* A set of nodes representing variable definitions that have already been visited but whose assignment has not yet been processed.
|
|
29
30
|
*/
|
|
30
31
|
unassigned = new Set();
|
|
32
|
+
/**
|
|
33
|
+
* Whether the current abstract state has been copied/cloned and is save to modify in place.
|
|
34
|
+
*/
|
|
35
|
+
stateCopied = false;
|
|
31
36
|
constructor(config) {
|
|
32
37
|
super({ ...config, defaultVisitingOrder: 'forward', defaultVisitingType: 'exit' });
|
|
33
|
-
this.
|
|
38
|
+
this._currentState = new state_abstract_domain_1.MutableStateAbstractDomain(new Map());
|
|
39
|
+
}
|
|
40
|
+
get currentState() {
|
|
41
|
+
return this._currentState;
|
|
42
|
+
}
|
|
43
|
+
removeState(node) {
|
|
44
|
+
if (!this.stateCopied) {
|
|
45
|
+
this._currentState = this._currentState.create(this.currentState.value);
|
|
46
|
+
this.stateCopied = true;
|
|
47
|
+
}
|
|
48
|
+
this._currentState.remove(node);
|
|
49
|
+
}
|
|
50
|
+
updateState(node, value) {
|
|
51
|
+
if (!this.stateCopied) {
|
|
52
|
+
this._currentState = this._currentState.create(this.currentState.value);
|
|
53
|
+
this.stateCopied = true;
|
|
54
|
+
}
|
|
55
|
+
this._currentState.set(node, value);
|
|
34
56
|
}
|
|
35
57
|
/**
|
|
36
58
|
* Resolves the inferred abstract value of an AST node.
|
|
@@ -49,7 +71,7 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
49
71
|
return state.get(node.info.id);
|
|
50
72
|
}
|
|
51
73
|
const vertex = this.getDataflowGraph(node.info.id);
|
|
52
|
-
const call =
|
|
74
|
+
const call = (0, vertex_1.isFunctionCallVertex)(vertex) ? vertex : undefined;
|
|
53
75
|
const origins = Array.isArray(call?.origin) ? call.origin : [];
|
|
54
76
|
if (node.type === type_1.RType.Symbol) {
|
|
55
77
|
const values = this.getVariableOrigins(node.info.id).map(origin => state?.get(origin));
|
|
@@ -100,9 +122,9 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
100
122
|
*/
|
|
101
123
|
getEndState() {
|
|
102
124
|
const exitPoints = this.config.controlFlow.exitPoints.map(id => this.getCfgVertex(id)).filter(assert_1.isNotUndefined);
|
|
103
|
-
const exitNodes = exitPoints.map(
|
|
104
|
-
const states = exitNodes.map(node => this.
|
|
105
|
-
return
|
|
125
|
+
const exitNodes = exitPoints.map(control_flow_graph_1.CfgVertex.getRootId).filter(assert_1.isNotUndefined);
|
|
126
|
+
const states = exitNodes.map(node => this.trace.get(node)).filter(assert_1.isNotUndefined);
|
|
127
|
+
return abstract_domain_1.AbstractDomain.joinAll(states, this._currentState.top());
|
|
106
128
|
}
|
|
107
129
|
/**
|
|
108
130
|
* Gets the inferred abstract trace mapping AST nodes to the inferred abstract state at the respective node.
|
|
@@ -116,38 +138,66 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
116
138
|
super.start();
|
|
117
139
|
this.unassigned.clear();
|
|
118
140
|
}
|
|
141
|
+
startVisitor(start) {
|
|
142
|
+
const stack = Array.from(start);
|
|
143
|
+
while (stack.length > 0) {
|
|
144
|
+
const current = stack.pop();
|
|
145
|
+
if (!this.visitNode(current)) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
for (const next of this.config.controlFlow.graph.ingoingEdges(current)?.keys().toArray().reverse() ?? []) {
|
|
149
|
+
if (!stack.includes(next)) { // prevent double entries in working list
|
|
150
|
+
stack.push(next);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
119
155
|
visitNode(vertexId) {
|
|
120
156
|
const vertex = this.getCfgVertex(vertexId);
|
|
121
|
-
|
|
157
|
+
// skip exit vertices of widening points and entry vertices of complex nodes
|
|
158
|
+
if (vertex === undefined || this.shouldSkipVertex(vertex)) {
|
|
122
159
|
return true;
|
|
123
160
|
}
|
|
161
|
+
const predecessors = this.getPredecessorNodes(control_flow_graph_1.CfgVertex.getId(vertex));
|
|
162
|
+
const predecessorStates = predecessors.map(pred => this.trace.get(pred)).filter(assert_1.isNotUndefined);
|
|
163
|
+
// retrieve new abstract state by joining states of predecessor nodes
|
|
164
|
+
if (predecessorStates.length === 1) {
|
|
165
|
+
this._currentState = predecessorStates[0];
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
this._currentState = abstract_domain_1.AbstractDomain.joinAll(predecessorStates, this._currentState.top());
|
|
169
|
+
this.stateCopied = true;
|
|
170
|
+
}
|
|
124
171
|
const nodeId = control_flow_graph_1.CfgVertex.getRootId(vertex);
|
|
172
|
+
// differentiate between widening points and other vertices
|
|
125
173
|
if (this.isWideningPoint(nodeId)) {
|
|
126
|
-
|
|
127
|
-
if (control_flow_graph_1.CfgVertex.isMarker(vertex)) {
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
const oldState = this.getAbstractState(nodeId) ?? this.config.domain.bottom();
|
|
131
|
-
const predecessorDomains = this.getPredecessorNodes(control_flow_graph_1.CfgVertex.getId(vertex)).map(pred => this.getAbstractState(pred)).filter(assert_1.isNotUndefined);
|
|
132
|
-
this.currentState = this.config.domain.bottom().joinAll(predecessorDomains);
|
|
174
|
+
const oldState = this.trace.get(nodeId) ?? this._currentState.top();
|
|
133
175
|
if (this.shouldWiden(vertex)) {
|
|
134
|
-
this.
|
|
176
|
+
this._currentState = oldState.widen(this._currentState);
|
|
177
|
+
this.stateCopied = true;
|
|
135
178
|
}
|
|
136
|
-
this.trace.set(nodeId, this.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
179
|
+
this.trace.set(nodeId, this._currentState);
|
|
180
|
+
this.stateCopied = false;
|
|
181
|
+
const visitedCount = this.visited.get(nodeId) ?? 0;
|
|
182
|
+
this.visited.set(nodeId, visitedCount + 1);
|
|
183
|
+
// continue visiting after widening point if visited for the first time or the state changed
|
|
184
|
+
return visitedCount === 0 || !oldState.equals(this._currentState);
|
|
141
185
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
186
|
+
else {
|
|
187
|
+
this.onVisitNode(vertexId);
|
|
188
|
+
// discard the inferred abstract state when encountering functions with unknown side effects (e.g. `eval`)
|
|
189
|
+
if (this.config.dfg.unknownSideEffects.has(nodeId)) {
|
|
190
|
+
this._currentState = this._currentState.top();
|
|
191
|
+
this.stateCopied = true;
|
|
192
|
+
}
|
|
193
|
+
this.trace.set(nodeId, this._currentState);
|
|
194
|
+
this.stateCopied = false;
|
|
195
|
+
const predecessorVisits = predecessors.map(pred => this.visited.get(pred) ?? 0);
|
|
196
|
+
const visitedCount = this.visited.get(nodeId) ?? 0;
|
|
197
|
+
this.visited.set(nodeId, visitedCount + 1);
|
|
198
|
+
// continue visiting if vertex is not a join vertex or number of visits of predecessors is the same
|
|
199
|
+
return predecessors.length <= 1 || predecessorVisits.every(visits => visits === predecessorVisits[0]);
|
|
148
200
|
}
|
|
149
|
-
this.trace.set(nodeId, this.currentState);
|
|
150
|
-
return true;
|
|
151
201
|
}
|
|
152
202
|
onDispatchFunctionCallOrigin(call, origin) {
|
|
153
203
|
super.onDispatchFunctionCallOrigin(call, origin);
|
|
@@ -183,8 +233,9 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
183
233
|
const value = this.getAbstractValue(source);
|
|
184
234
|
this.unassigned.delete(target);
|
|
185
235
|
if (value !== undefined) {
|
|
186
|
-
this.
|
|
187
|
-
this.trace.set(target, this.
|
|
236
|
+
this.updateState(target, value);
|
|
237
|
+
this.trace.set(target, this._currentState);
|
|
238
|
+
this.stateCopied = false;
|
|
188
239
|
}
|
|
189
240
|
}
|
|
190
241
|
onReplacementCall({ target }) {
|
|
@@ -204,7 +255,7 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
204
255
|
onFunctionCall(_data) { }
|
|
205
256
|
/** Gets all AST nodes for the predecessor vertices that are leaf nodes and exit vertices */
|
|
206
257
|
getPredecessorNodes(vertexId) {
|
|
207
|
-
return this.config.controlFlow.graph.outgoingEdges(vertexId)?.keys() // outgoing dependency edges are
|
|
258
|
+
return this.config.controlFlow.graph.outgoingEdges(vertexId)?.keys() // outgoing dependency edges are ingoing CFG edges
|
|
208
259
|
.map(id => this.getCfgVertex(id))
|
|
209
260
|
.flatMap(vertex => {
|
|
210
261
|
if (vertex === undefined) {
|
|
@@ -226,10 +277,10 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
226
277
|
.map(origin => origin.id)
|
|
227
278
|
.filter(origin => this.trace.has(origin) && !this.unassigned.has(origin)) ?? [];
|
|
228
279
|
}
|
|
229
|
-
/** We only perform widening at `for`, `while`, or `repeat` loops with more than one
|
|
280
|
+
/** We only perform widening at `for`, `while`, or `repeat` loops with more than one ingoing CFG edge */
|
|
230
281
|
isWideningPoint(nodeId) {
|
|
231
|
-
const
|
|
232
|
-
if (
|
|
282
|
+
const ingoingEdges = this.config.controlFlow.graph.outgoingEdges(nodeId)?.size; // outgoing dependency edges are ingoing CFG edges
|
|
283
|
+
if (ingoingEdges === undefined || ingoingEdges <= 1) {
|
|
233
284
|
return false;
|
|
234
285
|
}
|
|
235
286
|
const node = this.getNormalizedAst(nodeId);
|
|
@@ -243,26 +294,20 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
243
294
|
const origin = dataflowVertex.origin;
|
|
244
295
|
return origin.includes(built_in_1.BuiltInProcName.ForLoop) || origin.includes(built_in_1.BuiltInProcName.WhileLoop) || origin.includes(built_in_1.BuiltInProcName.RepeatLoop);
|
|
245
296
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Checks whether to continue visiting the control flow graph after a widening point.
|
|
248
|
-
* By default, we only continue visiting if the widening point is visited for the first time or the abstract state at the widening point changed.
|
|
249
|
-
*/
|
|
250
|
-
shouldContinueVisiting(wideningPoint, oldState) {
|
|
251
|
-
const wid = control_flow_graph_1.CfgVertex.getId(wideningPoint);
|
|
252
|
-
const visitedCount = this.visited.get(wid) ?? 0;
|
|
253
|
-
this.visited.set(wid, visitedCount + 1);
|
|
254
|
-
return visitedCount === 0 || !oldState.equals(this.currentState);
|
|
255
|
-
}
|
|
256
297
|
/**
|
|
257
298
|
* Checks whether a control flow graph vertex should be skipped during visitation.
|
|
258
|
-
* By default, we only process vertices of leaf nodes and exit vertices (no entry nodes of complex nodes).
|
|
299
|
+
* By default, we only process entry vertices of widening points, vertices of leaf nodes, and exit vertices (no entry nodes of complex nodes).
|
|
259
300
|
*/
|
|
260
301
|
shouldSkipVertex(vertex) {
|
|
302
|
+
if (this.isWideningPoint(control_flow_graph_1.CfgVertex.getRootId(vertex))) {
|
|
303
|
+
// skip exit vertices of widening points
|
|
304
|
+
return control_flow_graph_1.CfgVertex.isMarker(vertex);
|
|
305
|
+
}
|
|
261
306
|
return !control_flow_graph_1.CfgVertex.isMarker(vertex) && !control_flow_graph_1.CfgVertex.isBlock(vertex) && control_flow_graph_1.CfgVertex.getEnd(vertex) !== undefined;
|
|
262
307
|
}
|
|
263
308
|
/**
|
|
264
309
|
* Whether widening should be performed at a widening point.
|
|
265
|
-
* By default, we perform widening when the number of
|
|
310
|
+
* By default, we perform widening when the number of visits of the widening point reaches the widening threshold of the config.
|
|
266
311
|
*/
|
|
267
312
|
shouldWiden(wideningPoint) {
|
|
268
313
|
return (this.visited.get(control_flow_graph_1.CfgVertex.getId(wideningPoint)) ?? 0) >= this.config.ctx.config.abstractInterpretation.wideningThreshold;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { DataflowGraphVertexFunctionCall } from '../../dataflow/graph/vertex';
|
|
2
2
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
3
|
import { AbstractInterpretationVisitor, type AbsintVisitorConfiguration } from '../absint-visitor';
|
|
4
|
-
import { StateAbstractDomain } from '../domains/state-abstract-domain';
|
|
5
4
|
import { DataFrameDomain } from './dataframe-domain';
|
|
6
5
|
import { ConstraintType, type DataFrameOperationArgs, type DataFrameOperationName, type DataFrameOperationOptions } from './semantics';
|
|
7
6
|
interface Operation<Name extends DataFrameOperationName> {
|
|
@@ -30,15 +29,13 @@ export type DataFrameOperationType<OperationName extends DataFrameOperationName
|
|
|
30
29
|
* A possible `undefined` array of abstract data frame operations (see {@link DataFrameOperation}).
|
|
31
30
|
*/
|
|
32
31
|
export type DataFrameOperations<OperationName extends DataFrameOperationName = DataFrameOperationName> = DataFrameOperation<OperationName>[] | undefined;
|
|
33
|
-
interface DataFrameShapeInferenceConfiguration extends
|
|
32
|
+
interface DataFrameShapeInferenceConfiguration extends AbsintVisitorConfiguration {
|
|
34
33
|
readonly trackOperations?: boolean;
|
|
35
34
|
}
|
|
36
35
|
/**
|
|
37
36
|
* The control flow graph visitor to infer the shape of data frames using abstract interpretation
|
|
38
37
|
*/
|
|
39
|
-
export declare class DataFrameShapeInferenceVisitor extends AbstractInterpretationVisitor<DataFrameDomain, DataFrameShapeInferenceConfiguration
|
|
40
|
-
domain: StateAbstractDomain<DataFrameDomain>;
|
|
41
|
-
}> {
|
|
38
|
+
export declare class DataFrameShapeInferenceVisitor extends AbstractInterpretationVisitor<DataFrameDomain, DataFrameShapeInferenceConfiguration> {
|
|
42
39
|
/**
|
|
43
40
|
* The abstract data frame operations the function call nodes are mapped to.
|
|
44
41
|
*/
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataFrameShapeInferenceVisitor = void 0;
|
|
4
4
|
const absint_visitor_1 = require("../absint-visitor");
|
|
5
|
-
const state_abstract_domain_1 = require("../domains/state-abstract-domain");
|
|
6
5
|
const dataframe_domain_1 = require("./dataframe-domain");
|
|
7
6
|
const access_mapper_1 = require("./mappers/access-mapper");
|
|
8
7
|
const function_mapper_1 = require("./mappers/function-mapper");
|
|
@@ -17,7 +16,7 @@ class DataFrameShapeInferenceVisitor extends absint_visitor_1.AbstractInterpreta
|
|
|
17
16
|
*/
|
|
18
17
|
operations;
|
|
19
18
|
constructor({ trackOperations = true, ...config }) {
|
|
20
|
-
super(
|
|
19
|
+
super(config);
|
|
21
20
|
if (trackOperations) {
|
|
22
21
|
this.operations = new Map();
|
|
23
22
|
}
|
|
@@ -74,13 +73,13 @@ class DataFrameShapeInferenceVisitor extends absint_visitor_1.AbstractInterpreta
|
|
|
74
73
|
value = (0, semantics_1.applyDataFrameSemantics)(operation, operandValue ?? dataframe_domain_1.DataFrameDomain.top(maxColNames), args, options);
|
|
75
74
|
const constraintType = type ?? (0, semantics_1.getConstraintType)(operation);
|
|
76
75
|
if (operand !== undefined && constraintType === semantics_1.ConstraintType.OperandModification) {
|
|
77
|
-
this.
|
|
76
|
+
this.updateState(operand, value);
|
|
78
77
|
for (const origin of this.getVariableOrigins(operand)) {
|
|
79
|
-
this.
|
|
78
|
+
this.updateState(origin, value);
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
else if (constraintType === semantics_1.ConstraintType.ResultPostcondition) {
|
|
83
|
-
this.
|
|
82
|
+
this.updateState(node.info.id, value);
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
85
|
}
|
|
@@ -55,14 +55,14 @@ export declare abstract class AbstractDomain<Concrete, Abstract, Top, Bot, Value
|
|
|
55
55
|
abstract isValue(): this is AbstractDomain<Concrete, Abstract, Top, Bot, Abstract>;
|
|
56
56
|
/**
|
|
57
57
|
* Joins an array of abstract values by joining the first abstract value with the other values in the array.
|
|
58
|
-
* The provided array of abstract values
|
|
58
|
+
* The provided array of abstract values must not be empty or a default value must be provided!
|
|
59
59
|
*/
|
|
60
|
-
static joinAll<Domain extends AnyAbstractDomain>(values: Domain[]): Domain;
|
|
60
|
+
static joinAll<Domain extends AnyAbstractDomain>(values: Domain[], defaultValue?: Domain): Domain;
|
|
61
61
|
/**
|
|
62
62
|
* Meets an array of abstract values by meeting the first abstract value with the other values in the array.
|
|
63
|
-
* The provided array of abstract values
|
|
63
|
+
* The provided array of abstract values must not be empty or a default value must be provided!
|
|
64
64
|
*/
|
|
65
|
-
static meetAll<Domain extends AnyAbstractDomain>(values: Domain[]): Domain;
|
|
65
|
+
static meetAll<Domain extends AnyAbstractDomain>(values: Domain[], defaultValue?: Domain): Domain;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* A type representing any abstract domain without additional information.
|