@eagleoutice/flowr 2.9.8 → 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.
Files changed (61) hide show
  1. package/README.md +34 -29
  2. package/abstract-interpretation/absint-visitor.d.ts +16 -14
  3. package/abstract-interpretation/absint-visitor.js +91 -46
  4. package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -5
  5. package/abstract-interpretation/data-frame/shape-inference.js +4 -5
  6. package/abstract-interpretation/domains/abstract-domain.d.ts +4 -4
  7. package/abstract-interpretation/domains/abstract-domain.js +8 -8
  8. package/abstract-interpretation/domains/mapped-abstract-domain.d.ts +12 -5
  9. package/abstract-interpretation/domains/mapped-abstract-domain.js +47 -23
  10. package/abstract-interpretation/domains/state-abstract-domain.d.ts +30 -1
  11. package/abstract-interpretation/domains/state-abstract-domain.js +130 -4
  12. package/control-flow/cfg-simplification.d.ts +1 -0
  13. package/control-flow/cfg-simplification.js +1 -0
  14. package/control-flow/extract-cfg.js +33 -15
  15. package/control-flow/semantic-cfg-guided-visitor.js +1 -0
  16. package/dataflow/environments/built-in.d.ts +4 -0
  17. package/dataflow/environments/built-in.js +17 -5
  18. package/dataflow/environments/default-builtin-config.d.ts +4 -8
  19. package/dataflow/environments/default-builtin-config.js +8 -5
  20. package/dataflow/environments/reference-to-maybe.d.ts +8 -0
  21. package/dataflow/environments/reference-to-maybe.js +46 -3
  22. package/dataflow/eval/resolve/alias-tracking.d.ts +1 -1
  23. package/dataflow/eval/resolve/alias-tracking.js +4 -5
  24. package/dataflow/eval/resolve/resolve.js +8 -7
  25. package/dataflow/graph/graph.d.ts +1 -1
  26. package/dataflow/graph/graph.js +9 -10
  27. package/dataflow/graph/unknown-side-effect.js +3 -1
  28. package/dataflow/info.d.ts +4 -0
  29. package/dataflow/info.js +2 -2
  30. package/dataflow/internal/linker.d.ts +2 -2
  31. package/dataflow/internal/linker.js +52 -27
  32. package/dataflow/internal/process/functions/call/argument/make-argument.js +2 -1
  33. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +15 -6
  34. package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +2 -2
  35. package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.js +4 -4
  36. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +22 -11
  37. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +22 -19
  38. package/dataflow/internal/process/functions/call/known-call-handling.js +0 -2
  39. package/documentation/wiki-absint.js +7 -8
  40. package/linter/rules/dead-code.js +1 -1
  41. package/linter/rules/seeded-randomness.js +1 -1
  42. package/linter/rules/unused-definition.js +1 -1
  43. package/package.json +7 -7
  44. package/project/context/flowr-file.d.ts +5 -0
  45. package/project/context/flowr-file.js +7 -0
  46. package/project/plugins/file-plugins/files/flowr-description-file.d.ts +5 -0
  47. package/project/plugins/file-plugins/files/flowr-description-file.js +9 -0
  48. package/project/plugins/file-plugins/files/flowr-namespace-file.d.ts +4 -0
  49. package/project/plugins/file-plugins/files/flowr-namespace-file.js +8 -0
  50. package/project/plugins/file-plugins/files/flowr-news-file.d.ts +4 -0
  51. package/project/plugins/file-plugins/files/flowr-news-file.js +8 -0
  52. package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
  53. package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +1 -1
  54. package/queries/catalog/df-shape-query/df-shape-query-format.js +3 -3
  55. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +23 -17
  56. package/r-bridge/lang-4.x/ast/model/processing/role.d.ts +18 -17
  57. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +31 -13
  58. package/statistics/features/supported/data-access/data-access.js +2 -2
  59. package/util/mermaid/ast.js +1 -1
  60. package/util/mermaid/dfg.js +6 -5
  61. 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.7, R grammar v14 (tree-sitter engine)
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 (2 ms)
36
+ Query: linter (3 ms)
37
37
  ╰ Deprecated Functions (deprecated-functions):
38
- ╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0
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: 1, processTimeMs: 0
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: 0, processTimeMs: 0
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: 1, processTimeMs: 0
56
+ ╰ Metadata: numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs: 0, processTimeMs: 0
57
57
  ╰ Dead Code (dead-code):
58
- ╰ Metadata: consideredNodes: 5, searchTimeMs: 0, processTimeMs: 0
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 ≈2 ms (1ms accuracy, total 3 ms)
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
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0</code>\
85
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 1, processTimeMs: 0</code>\
86
86
  &nbsp;&nbsp;&nbsp;╰ **File Path Validity** (file-path-validity):\
87
87
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ certain:\
88
88
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ Path `/root/x.txt` at 1.1-23\
@@ -92,7 +92,7 @@ It offers a wide variety of features, for example:
92
92
  &nbsp;&nbsp;&nbsp;╰ **Absolute Paths** (absolute-file-paths):\
93
93
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ certain:\
94
94
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ Path `/root/x.txt` at 1.1-23\
95
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs: 1, processTimeMs: 0</code>\
95
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs: 0, processTimeMs: 0</code>\
96
96
  &nbsp;&nbsp;&nbsp;╰ **Unused Definitions** (unused-definitions):\
97
97
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalConsidered: 0, searchTimeMs: 0, processTimeMs: 0</code>\
98
98
  &nbsp;&nbsp;&nbsp;╰ **Naming Convention** (naming-convention):\
@@ -100,7 +100,7 @@ It offers a wide variety of features, for example:
100
100
  &nbsp;&nbsp;&nbsp;╰ **Network Functions** (network-functions):\
101
101
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0</code>\
102
102
  &nbsp;&nbsp;&nbsp;╰ **Dataframe Access Validation** (dataframe-access-validation):\
103
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs: 0, processTimeMs: 1</code>\
103
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs: 1, processTimeMs: 0</code>\
104
104
  &nbsp;&nbsp;&nbsp;╰ **Dead Code** (dead-code):\
105
105
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>consideredNodes: 5, searchTimeMs: 0, processTimeMs: 0</code>\
106
106
  &nbsp;&nbsp;&nbsp;╰ **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.3 ms_ (including parsing and normalization and the query) within the generation environment.
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": 0,
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": 1,
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": 0,
221
- "processTimeMs": 1
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.7, R grammar v14 (tree-sitter engine)
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 3 ms)
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!">111.7 ms</span></i> (as of Feb 7, 2026)](https://flowr-analysis.github.io/flowr/wiki/stats/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&nbsp;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.7, R grammar v14 (tree-sitter engine)
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:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMChbXCJgIzkxO1JTeW1ib2wjOTM7IHRlc3RcbiAgICAgICgwKVxuICAgICAgKjEuMS00KmBcIl0pXG4gICAgMShbXCJgIzkxO1JTeW1ib2wjOTM7IHRlc3RmaWxlc1xuICAgICAgKDEpXG4gICAgICAqMS42LTE0KmBcIl0pXG4gICAgMltbXCJgIzkxO1JCaW5hcnlPcCM5MzsgL1xuICAgICAgKDIpXG4gICAgICAqMS4xLTE0KlxuICAgICgwLCAxKWBcIl1dXG4gICAgYnVpbHQtaW46X1tcImBCdWlsdC1Jbjpcbi9gXCJdXG4gICAgc3R5bGUgYnVpbHQtaW46XyBzdHJva2U6Z3JheSxmaWxsOmdyYXksc3Ryb2tlLXdpZHRoOjJweCxvcGFjaXR5Oi44O1xuICAgIDMoW1wiYCM5MTtSU3ltYm9sIzkzOyBleGFtcGxlLlJcbiAgICAgICgzKVxuICAgICAgKjEuMTYtMjQqYFwiXSlcbiAgICA0W1tcImAjOTE7UkJpbmFyeU9wIzkzOyAvXG4gICAgICAoNClcbiAgICAgICoxLjEtMjQqXG4gICAgKDIsIDMpYFwiXV1cbiAgICAyIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAwXG4gICAgMiAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgMVxuICAgIDIgLS4tPnxcInJlYWRzLCBjYWxsc1wifCBidWlsdC1pbjpfXG4gICAgbGlua1N0eWxlIDIgc3Ryb2tlOmdyYXk7XG4gICAgNCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgMlxuICAgIDQgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDNcbiAgICA0IC0uLT58XCJyZWFkcywgY2FsbHNcInwgYnVpbHQtaW46X1xuICAgIGxpbmtTdHlsZSA1IHN0cm9rZTpncmF5OyIsIm1lcm1haWQiOnsiYXV0b1N5bmMiOnRydWV9fQ==
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 82 stroke:gray;
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 88 stroke:gray;
701
+ linkStyle 87 stroke:gray;
697
702
  ```
698
703
 
699
704
 
700
- (The analysis required _1.8 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
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
- export interface AbsintVisitorConfiguration<Domain extends AnyAbstractDomain> extends Omit<SemanticCfgGuidedVisitorConfiguration<NoInfo, ControlFlowInformation, NormalizedAst>, 'defaultVisitingOrder' | 'defaultVisitingType'> {
14
- readonly domain: StateAbstractDomain<Domain>;
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<Domain> = AbsintVisitorConfiguration<Domain>> extends SemanticCfgGuidedVisitor<NoInfo, ControlFlowInformation, NormalizedAst, DataflowGraph, Config & {
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, StateAbstractDomain<Domain>>;
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
- protected currentState: StateAbstractDomain<Domain>;
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 incoming CFG edge */
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 visitation of the widening point reaches the widening threshold of the config.
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
- currentState;
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.currentState = config.domain.bottom();
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 = vertex?.tag === vertex_1.VertexType.FunctionCall ? vertex : undefined;
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(vertex => control_flow_graph_1.CfgVertex.getRootId(vertex)).filter(assert_1.isNotUndefined);
104
- const states = exitNodes.map(node => this.getAbstractState(node)).filter(assert_1.isNotUndefined);
105
- return this.config.domain.bottom().joinAll(states);
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
- if (vertex === undefined) {
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
- // only check widening points at the entry vertex
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.currentState = oldState.widen(this.currentState);
176
+ this._currentState = oldState.widen(this._currentState);
177
+ this.stateCopied = true;
135
178
  }
136
- this.trace.set(nodeId, this.currentState);
137
- return this.shouldContinueVisiting(vertex, oldState);
138
- }
139
- else if (this.shouldSkipVertex(vertex)) {
140
- return true;
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
- const predecessorDomains = this.getPredecessorNodes(control_flow_graph_1.CfgVertex.getId(vertex)).map(pred => this.getAbstractState(pred)).filter(assert_1.isNotUndefined);
143
- this.currentState = this.config.domain.bottom().joinAll(predecessorDomains);
144
- this.onVisitNode(vertexId);
145
- // discard the inferred abstract state when encountering functions with unknown side effects (e.g. `eval`)
146
- if (this.config.dfg.unknownSideEffects.has(nodeId)) {
147
- this.currentState = this.currentState.bottom();
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.currentState.set(target, value);
187
- this.trace.set(target, this.currentState.create(this.currentState.value));
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 incoming CFG edges
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 incoming CFG edge */
280
+ /** We only perform widening at `for`, `while`, or `repeat` loops with more than one ingoing CFG edge */
230
281
  isWideningPoint(nodeId) {
231
- const incomingEdges = this.config.controlFlow.graph.outgoingEdges(nodeId)?.size; // outgoing dependency edges are incoming CFG edges
232
- if (incomingEdges === undefined || incomingEdges <= 1) {
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 visitation of the widening point reaches the widening threshold of the config.
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 Omit<AbsintVisitorConfiguration<DataFrameDomain>, 'domain'> {
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({ ...config, domain: state_abstract_domain_1.StateAbstractDomain.bottom() });
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.currentState.set(operand, value);
76
+ this.updateState(operand, value);
78
77
  for (const origin of this.getVariableOrigins(operand)) {
79
- this.currentState.set(origin, value);
78
+ this.updateState(origin, value);
80
79
  }
81
80
  }
82
81
  else if (constraintType === semantics_1.ConstraintType.ResultPostcondition) {
83
- this.currentState.set(node.info.id, value);
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 cannot be empty!
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 cannot be empty!
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.