@eagleoutice/flowr 2.8.6 → 2.8.7
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 +13 -13
- package/abstract-interpretation/absint-visitor.d.ts +20 -68
- package/abstract-interpretation/absint-visitor.js +44 -54
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -9
- package/abstract-interpretation/data-frame/dataframe-domain.js +1 -14
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +1 -1
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +2 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +5 -2
- package/abstract-interpretation/data-frame/shape-inference.d.ts +15 -7
- package/abstract-interpretation/data-frame/shape-inference.js +20 -17
- package/abstract-interpretation/domains/abstract-domain.d.ts +1 -1
- package/abstract-interpretation/domains/abstract-domain.js +1 -2
- package/abstract-interpretation/domains/product-domain.d.ts +1 -1
- package/abstract-interpretation/domains/product-domain.js +1 -1
- package/abstract-interpretation/domains/set-range-domain.d.ts +1 -1
- package/abstract-interpretation/domains/set-range-domain.js +1 -1
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +3 -1
- package/abstract-interpretation/domains/state-abstract-domain.js +6 -0
- package/abstract-interpretation/normalized-ast-fold.d.ts +2 -1
- package/abstract-interpretation/normalized-ast-fold.js +8 -1
- package/cli/repl/commands/repl-query.js +7 -9
- package/cli/wiki.d.ts +2 -1
- package/cli/wiki.js +2 -0
- package/control-flow/cfg-dead-code.js +3 -0
- package/control-flow/extract-cfg.js +27 -7
- package/control-flow/semantic-cfg-guided-visitor.d.ts +57 -4
- package/control-flow/semantic-cfg-guided-visitor.js +89 -28
- package/control-flow/useless-loop.d.ts +2 -1
- package/control-flow/useless-loop.js +13 -6
- package/dataflow/environments/built-in-config.d.ts +6 -5
- package/dataflow/environments/built-in.d.ts +107 -34
- package/dataflow/environments/built-in.js +115 -39
- package/dataflow/environments/default-builtin-config.d.ts +113 -67
- package/dataflow/environments/default-builtin-config.js +71 -66
- package/dataflow/environments/diff.js +2 -2
- package/dataflow/environments/environment.js +7 -7
- package/dataflow/environments/identifier.d.ts +4 -2
- package/dataflow/environments/identifier.js +2 -0
- package/dataflow/environments/reference-to-maybe.d.ts +2 -2
- package/dataflow/environments/reference-to-maybe.js +11 -11
- package/dataflow/environments/resolve-by-name.js +17 -6
- package/dataflow/eval/resolve/alias-tracking.js +1 -1
- package/dataflow/eval/resolve/resolve.js +6 -6
- package/dataflow/eval/values/intervals/interval-constants.js +3 -3
- package/dataflow/eval/values/scalar/{scalar-consatnts.d.ts → scalar-constants.d.ts} +2 -2
- package/dataflow/eval/values/scalar/{scalar-consatnts.js → scalar-constants.js} +3 -3
- package/dataflow/eval/values/sets/set-constants.d.ts +4 -2
- package/dataflow/eval/values/sets/set-constants.js +4 -2
- package/dataflow/extractor.js +1 -1
- package/dataflow/fn/exceptions-of-function.d.ts +1 -1
- package/dataflow/fn/exceptions-of-function.js +3 -3
- package/dataflow/graph/call-graph.js +2 -2
- package/dataflow/graph/dataflowgraph-builder.d.ts +4 -4
- package/dataflow/graph/dataflowgraph-builder.js +14 -14
- package/dataflow/graph/diff-dataflow-graph.js +3 -3
- package/dataflow/graph/graph.d.ts +1 -1
- package/dataflow/graph/graph.js +4 -4
- package/dataflow/graph/vertex.d.ts +3 -3
- package/dataflow/info.d.ts +3 -3
- package/dataflow/info.js +11 -11
- package/dataflow/internal/linker.d.ts +9 -0
- package/dataflow/internal/linker.js +33 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +16 -12
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +11 -10
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +20 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.d.ts +5 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +11 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +0 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +39 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-get.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.d.ts +12 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +36 -12
- package/dataflow/internal/process/functions/call/built-in/built-in-library.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-library.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-local.d.ts +18 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-local.js +67 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +11 -10
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.js +5 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +7 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.d.ts +18 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.js +103 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +8 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.js +13 -12
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.js +6 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +7 -6
- package/dataflow/internal/process/functions/call/common.js +7 -7
- package/dataflow/internal/process/functions/call/known-call-handling.js +7 -8
- package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -2
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -6
- package/dataflow/internal/process/functions/process-argument.js +2 -2
- package/dataflow/internal/process/functions/process-parameter.js +3 -3
- package/dataflow/internal/process/process-symbol.js +3 -3
- package/dataflow/internal/process/process-uninteresting-leaf.d.ts +3 -1
- package/dataflow/internal/process/process-uninteresting-leaf.js +3 -1
- package/dataflow/internal/process/process-value.d.ts +1 -1
- package/dataflow/internal/process/process-value.js +4 -4
- package/dataflow/origin/dfg-get-symbol-refs.js +1 -1
- package/dataflow/processor.d.ts +1 -1
- package/documentation/doc-util/doc-structure.js +1 -1
- package/documentation/doc-util/doc-types.d.ts +10 -3
- package/documentation/doc-util/doc-types.js +110 -33
- package/documentation/wiki-absint.d.ts +6 -0
- package/documentation/wiki-absint.js +149 -0
- package/documentation/wiki-dataflow-graph.js +11 -10
- package/documentation/wiki-interface.js +2 -1
- package/documentation/wiki-mk/doc-context.d.ts +3 -3
- package/documentation/wiki-mk/doc-context.js +2 -2
- package/documentation/wiki-mk/doc-maker.js +2 -2
- package/documentation/wiki-normalized-ast.d.ts +9 -0
- package/documentation/wiki-normalized-ast.js +40 -52
- package/linter/linter-rules.d.ts +1 -1
- package/linter/rules/seeded-randomness.js +5 -4
- package/linter/rules/useless-loop.d.ts +3 -3
- package/package.json +1 -1
- 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 +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +4 -0
- package/queries/catalog/dependencies-query/dependencies-query-format.js +5 -0
- package/queries/catalog/dependencies-query/function-info/test-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/test-functions.js +82 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +3 -2
- package/queries/catalog/df-shape-query/df-shape-query-format.js +3 -3
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.d.ts +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.js +1 -1
- package/r-bridge/data/data.d.ts +6 -1
- package/r-bridge/data/data.js +8 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +7 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.js +19 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-project.d.ts +4 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-project.js +7 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +2 -1
- package/r-bridge/lang-4.x/convert-values.d.ts +5 -0
- package/search/flowr-search-filters.d.ts +2 -2
- package/slicing/static/static-slicer.js +2 -2
- package/util/mermaid/cfg.d.ts +10 -3
- package/util/mermaid/cfg.js +39 -10
- package/util/mermaid/dfg.js +5 -5
- package/util/simple-df/dfg-view.js +1 -1
- package/util/text/ansi.d.ts +4 -0
- package/util/text/ansi.js +7 -0
- 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.8.
|
|
27
|
+
flowR repl using flowR v2.8.6, R grammar v14 (tree-sitter engine)
|
|
28
28
|
R> :query @linter "read.csv(\"/root/x.txt\")"
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -33,9 +33,9 @@ It offers a wide variety of features, for example:
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
```text
|
|
36
|
-
Query: linter (
|
|
36
|
+
Query: linter (1 ms)
|
|
37
37
|
╰ Deprecated Functions (deprecated-functions):
|
|
38
|
-
╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs:
|
|
38
|
+
╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0
|
|
39
39
|
╰ File Path Validity (file-path-validity):
|
|
40
40
|
╰ certain:
|
|
41
41
|
╰ Path `/root/x.txt` at 1.1-23
|
|
@@ -58,7 +58,7 @@ It offers a wide variety of features, for example:
|
|
|
58
58
|
╰ Metadata: consideredNodes: 5, searchTimeMs: 0, 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 ≈1 ms (1ms accuracy, total 2 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** (2 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\
|
|
@@ -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 _2.
|
|
112
|
+
The analysis required _2.7 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,8 +126,8 @@ It offers a wide variety of features, for example:
|
|
|
126
126
|
".meta": {
|
|
127
127
|
"totalCalls": 0,
|
|
128
128
|
"totalFunctionDefinitions": 0,
|
|
129
|
-
"searchTimeMs":
|
|
130
|
-
"processTimeMs":
|
|
129
|
+
"searchTimeMs": 1,
|
|
130
|
+
"processTimeMs": 0
|
|
131
131
|
}
|
|
132
132
|
},
|
|
133
133
|
"file-path-validity": {
|
|
@@ -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.8.
|
|
311
|
+
flowR repl using flowR v2.8.6, 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!">118.2 ms</span></i> (as of Jan 13, 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/dataflow-graph) for more details on the dataflow graphs as well as call graphs.
|
|
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.8.
|
|
395
|
+
flowR repl using flowR v2.8.6, R grammar v14 (tree-sitter engine)
|
|
396
396
|
R> :dataflow* test/testfiles/example.R
|
|
397
397
|
```
|
|
398
398
|
|
|
@@ -697,7 +697,7 @@ It offers a wide variety of features, for example:
|
|
|
697
697
|
```
|
|
698
698
|
|
|
699
699
|
|
|
700
|
-
(The analysis required
|
|
700
|
+
(The analysis required _2.0 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
|
|
701
701
|
|
|
702
702
|
|
|
703
703
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CfgSimpleVertex, ControlFlowInformation } from '../control-flow/control-flow-graph';
|
|
2
2
|
import type { SemanticCfgGuidedVisitorConfiguration } from '../control-flow/semantic-cfg-guided-visitor';
|
|
3
3
|
import { SemanticCfgGuidedVisitor } from '../control-flow/semantic-cfg-guided-visitor';
|
|
4
|
+
import { BuiltInProcessorMapper } from '../dataflow/environments/built-in';
|
|
4
5
|
import type { DataflowGraph } from '../dataflow/graph/graph';
|
|
5
6
|
import { type DataflowGraphVertexFunctionCall, type DataflowGraphVertexVariableDefinition } from '../dataflow/graph/vertex';
|
|
6
7
|
import type { NoInfo, RNode } from '../r-bridge/lang-4.x/ast/model/model';
|
|
@@ -8,7 +9,7 @@ import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/
|
|
|
8
9
|
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
9
10
|
import { type AnyAbstractDomain } from './domains/abstract-domain';
|
|
10
11
|
import type { StateAbstractDomain } from './domains/state-abstract-domain';
|
|
11
|
-
export interface AbsintVisitorConfiguration<Domain extends AnyAbstractDomain
|
|
12
|
+
export interface AbsintVisitorConfiguration<Domain extends AnyAbstractDomain> extends Omit<SemanticCfgGuidedVisitorConfiguration<NoInfo, ControlFlowInformation, NormalizedAst>, 'defaultVisitingOrder' | 'defaultVisitingType'> {
|
|
12
13
|
readonly domain: StateAbstractDomain<Domain>;
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
@@ -16,7 +17,7 @@ export interface AbsintVisitorConfiguration<Domain extends AnyAbstractDomain, Ot
|
|
|
16
17
|
*
|
|
17
18
|
* However, the visitor does not yet support inter-procedural abstract interpretation and abstract condition semantics.
|
|
18
19
|
*/
|
|
19
|
-
export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAbstractDomain,
|
|
20
|
+
export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAbstractDomain, Config extends AbsintVisitorConfiguration<Domain> = AbsintVisitorConfiguration<Domain>> extends SemanticCfgGuidedVisitor<NoInfo, ControlFlowInformation, NormalizedAst, DataflowGraph, Config & {
|
|
20
21
|
defaultVisitingOrder: 'forward';
|
|
21
22
|
defaultVisitingType: 'exit';
|
|
22
23
|
}> {
|
|
@@ -25,13 +26,13 @@ export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAb
|
|
|
25
26
|
*/
|
|
26
27
|
protected readonly trace: Map<NodeId, StateAbstractDomain<Domain>>;
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
+
* The current abstract state domain at the currently processed AST node.
|
|
29
30
|
*/
|
|
30
|
-
|
|
31
|
+
protected currentState: StateAbstractDomain<Domain>;
|
|
31
32
|
/**
|
|
32
|
-
*
|
|
33
|
+
* A set of nodes representing variable definitions that have already been visited but whose assignment has not yet been processed.
|
|
33
34
|
*/
|
|
34
|
-
private
|
|
35
|
+
private readonly unassigned;
|
|
35
36
|
constructor(config: Config);
|
|
36
37
|
/**
|
|
37
38
|
* Resolves the inferred abstract value of an AST node.
|
|
@@ -40,7 +41,7 @@ export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAb
|
|
|
40
41
|
* @param state - An optional state abstract domain used to resolve the inferred abstract value (defaults to the state at the requested node)
|
|
41
42
|
* @returns The inferred abstract value of the node, or `undefined` if no value was inferred for the node
|
|
42
43
|
*/
|
|
43
|
-
getAbstractValue(id: RNode<ParentInformation
|
|
44
|
+
getAbstractValue(id: RNode<ParentInformation> | NodeId | undefined, state?: StateAbstractDomain<Domain>): Domain | undefined;
|
|
44
45
|
/**
|
|
45
46
|
* Gets the inferred abstract state at the location of a specific AST node.
|
|
46
47
|
* This requires that the abstract interpretation visitor has been completed, or at least started.
|
|
@@ -61,6 +62,7 @@ export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAb
|
|
|
61
62
|
getAbstractTrace(): ReadonlyMap<NodeId, StateAbstractDomain<Domain>>;
|
|
62
63
|
start(): void;
|
|
63
64
|
protected visitNode(vertexId: NodeId): boolean;
|
|
65
|
+
protected onDispatchFunctionCallOrigin(call: DataflowGraphVertexFunctionCall, origin: keyof typeof BuiltInProcessorMapper | string): void;
|
|
64
66
|
protected onVariableDefinition({ vertex }: {
|
|
65
67
|
vertex: DataflowGraphVertexVariableDefinition;
|
|
66
68
|
}): void;
|
|
@@ -69,73 +71,23 @@ export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAb
|
|
|
69
71
|
target?: NodeId;
|
|
70
72
|
source?: NodeId;
|
|
71
73
|
}): void;
|
|
72
|
-
protected onReplacementCall({
|
|
74
|
+
protected onReplacementCall({ target }: {
|
|
73
75
|
call: DataflowGraphVertexFunctionCall;
|
|
74
76
|
target?: NodeId;
|
|
75
77
|
source?: NodeId;
|
|
76
78
|
}): void;
|
|
77
|
-
protected onAccessCall({ call }: {
|
|
78
|
-
call: DataflowGraphVertexFunctionCall;
|
|
79
|
-
}): void;
|
|
80
|
-
protected onUnnamedCall({ call }: {
|
|
81
|
-
call: DataflowGraphVertexFunctionCall;
|
|
82
|
-
}): void;
|
|
83
|
-
protected onEvalFunctionCall({ call }: {
|
|
84
|
-
call: DataflowGraphVertexFunctionCall;
|
|
85
|
-
}): void;
|
|
86
|
-
protected onApplyFunctionCall({ call }: {
|
|
87
|
-
call: DataflowGraphVertexFunctionCall;
|
|
88
|
-
}): void;
|
|
89
|
-
protected onSourceCall({ call }: {
|
|
90
|
-
call: DataflowGraphVertexFunctionCall;
|
|
91
|
-
}): void;
|
|
92
|
-
protected onGetCall({ call }: {
|
|
93
|
-
call: DataflowGraphVertexFunctionCall;
|
|
94
|
-
}): void;
|
|
95
|
-
protected onRmCall({ call }: {
|
|
96
|
-
call: DataflowGraphVertexFunctionCall;
|
|
97
|
-
}): void;
|
|
98
|
-
protected onListCall({ call }: {
|
|
99
|
-
call: DataflowGraphVertexFunctionCall;
|
|
100
|
-
}): void;
|
|
101
|
-
protected onVectorCall({ call }: {
|
|
102
|
-
call: DataflowGraphVertexFunctionCall;
|
|
103
|
-
}): void;
|
|
104
|
-
protected onSpecialBinaryOpCall({ call }: {
|
|
105
|
-
call: DataflowGraphVertexFunctionCall;
|
|
106
|
-
}): void;
|
|
107
|
-
protected onQuoteCall({ call }: {
|
|
108
|
-
call: DataflowGraphVertexFunctionCall;
|
|
109
|
-
}): void;
|
|
110
|
-
protected onLibraryCall({ call }: {
|
|
111
|
-
call: DataflowGraphVertexFunctionCall;
|
|
112
|
-
}): void;
|
|
113
|
-
protected onDefaultFunctionCall({ call }: {
|
|
114
|
-
call: DataflowGraphVertexFunctionCall;
|
|
115
|
-
}): void;
|
|
116
|
-
/**
|
|
117
|
-
* Evaluates any function call visited by the abstract interpretation visitor by applying the abstract semantics of the function call to the current abstract state.
|
|
118
|
-
* @param call - The data flow vertex of the function call to evaluate
|
|
119
|
-
* @param state - The current abstract state before the evaluation of the function call
|
|
120
|
-
* @returns The abstract state after applying the abstract semantics of the function call
|
|
121
|
-
*/
|
|
122
|
-
protected abstract evalFunctionCall(call: DataflowGraphVertexFunctionCall, state: StateAbstractDomain<Domain>): StateAbstractDomain<Domain>;
|
|
123
79
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
80
|
+
* This event triggers for every function call that is not a condition, loop, assignment, replacement call, or access operation.
|
|
81
|
+
*
|
|
82
|
+
*
|
|
83
|
+
* For example, this triggers for `data.frame` in `x <- data.frame(id = 1:5, name = letters[1:5])`.
|
|
84
|
+
*
|
|
85
|
+
* This bundles all function calls that are no conditions, loops, assignments, replacement calls, and access operations.
|
|
86
|
+
* @protected
|
|
130
87
|
*/
|
|
131
|
-
protected
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
* @param call - The data flow vertex of the access operation to evaluate
|
|
135
|
-
* @param state - The current abstract state before the evaluation of the access operation
|
|
136
|
-
* @returns The abstract state after applying the abstract semantics of the access operation
|
|
137
|
-
*/
|
|
138
|
-
protected abstract evalAccessCall(call: DataflowGraphVertexFunctionCall, state: StateAbstractDomain<Domain>): StateAbstractDomain<Domain>;
|
|
88
|
+
protected onFunctionCall(_data: {
|
|
89
|
+
call: DataflowGraphVertexFunctionCall;
|
|
90
|
+
}): void;
|
|
139
91
|
/** Gets all AST nodes for the predecessor vertices that are leaf nodes and exit vertices */
|
|
140
92
|
protected getPredecessorNodes(vertexId: NodeId): NodeId[];
|
|
141
93
|
/** Gets each variable origin that has already been visited and whose assignment has already been processed */
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AbstractInterpretationVisitor = void 0;
|
|
4
4
|
const control_flow_graph_1 = require("../control-flow/control-flow-graph");
|
|
5
5
|
const semantic_cfg_guided_visitor_1 = require("../control-flow/semantic-cfg-guided-visitor");
|
|
6
|
+
const built_in_1 = require("../dataflow/environments/built-in");
|
|
6
7
|
const vertex_1 = require("../dataflow/graph/vertex");
|
|
7
8
|
const dfg_get_origin_1 = require("../dataflow/origin/dfg-get-origin");
|
|
8
9
|
const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
@@ -19,14 +20,14 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
19
20
|
* The abstract trace of the abstract interpretation visitor mapping node IDs to the abstract state at the respective node.
|
|
20
21
|
*/
|
|
21
22
|
trace = new Map();
|
|
22
|
-
/**
|
|
23
|
-
* A set of nodes representing variable definitions that have already been visited but whose assignment has not yet been processed.
|
|
24
|
-
*/
|
|
25
|
-
unassigned = new Set();
|
|
26
23
|
/**
|
|
27
24
|
* The current abstract state domain at the currently processed AST node.
|
|
28
25
|
*/
|
|
29
26
|
currentState;
|
|
27
|
+
/**
|
|
28
|
+
* A set of nodes representing variable definitions that have already been visited but whose assignment has not yet been processed.
|
|
29
|
+
*/
|
|
30
|
+
unassigned = new Set();
|
|
30
31
|
constructor(config) {
|
|
31
32
|
super({ ...config, defaultVisitingOrder: 'forward', defaultVisitingType: 'exit' });
|
|
32
33
|
this.currentState = config.domain.bottom();
|
|
@@ -60,9 +61,9 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
60
61
|
return this.getAbstractValue(node.value, state);
|
|
61
62
|
}
|
|
62
63
|
else if (node.type === type_1.RType.ExpressionList && node.children.length > 0) {
|
|
63
|
-
return this.getAbstractValue(node.children
|
|
64
|
+
return this.getAbstractValue(node.children.at(-1), state);
|
|
64
65
|
}
|
|
65
|
-
else if (origins.includes(
|
|
66
|
+
else if (origins.includes(built_in_1.BuiltInProcName.Pipe)) {
|
|
66
67
|
if (node.type === type_1.RType.Pipe || node.type === type_1.RType.BinaryOp) {
|
|
67
68
|
return this.getAbstractValue(node.rhs, state);
|
|
68
69
|
}
|
|
@@ -70,7 +71,7 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
70
71
|
return this.getAbstractValue(call.args[1].nodeId, state);
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
|
-
else if (origins.includes(
|
|
74
|
+
else if (origins.includes(built_in_1.BuiltInProcName.IfThenElse)) {
|
|
74
75
|
let values = [];
|
|
75
76
|
if (node.type === type_1.RType.IfThenElse && node.otherwise !== undefined) {
|
|
76
77
|
values = [node.then, node.otherwise].map(entry => this.getAbstractValue(entry, state));
|
|
@@ -90,7 +91,7 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
90
91
|
* @returns The abstract state at the node, or `undefined` if the node has no abstract state (i.e. the node has not been visited or is unreachable).
|
|
91
92
|
*/
|
|
92
93
|
getAbstractState(id) {
|
|
93
|
-
return id
|
|
94
|
+
return id === undefined ? undefined : this.trace.get(id);
|
|
94
95
|
}
|
|
95
96
|
/**
|
|
96
97
|
* Gets the inferred abstract state at the end of the program (exit nodes of the control flow graph).
|
|
@@ -148,8 +149,28 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
148
149
|
this.trace.set(nodeId, this.currentState);
|
|
149
150
|
return true;
|
|
150
151
|
}
|
|
152
|
+
onDispatchFunctionCallOrigin(call, origin) {
|
|
153
|
+
super.onDispatchFunctionCallOrigin(call, origin);
|
|
154
|
+
if (!(origin in built_in_1.BuiltInProcessorMapper)) {
|
|
155
|
+
return this.onFunctionCall({ call });
|
|
156
|
+
}
|
|
157
|
+
switch (origin) {
|
|
158
|
+
case 'builtin:expression-list':
|
|
159
|
+
case 'builtin:if-then-else':
|
|
160
|
+
case 'builtin:for-loop':
|
|
161
|
+
case 'builtin:while-loop':
|
|
162
|
+
case 'builtin:repeat-loop':
|
|
163
|
+
case 'builtin:assignment':
|
|
164
|
+
case 'builtin:assignment-like':
|
|
165
|
+
case 'builtin:replacement':
|
|
166
|
+
case 'builtin:access':
|
|
167
|
+
return;
|
|
168
|
+
default:
|
|
169
|
+
return this.onFunctionCall({ call });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
151
172
|
onVariableDefinition({ vertex }) {
|
|
152
|
-
if (this.
|
|
173
|
+
if (this.currentState.get(vertex.id) === undefined) {
|
|
153
174
|
this.unassigned.add(vertex.id);
|
|
154
175
|
}
|
|
155
176
|
}
|
|
@@ -164,52 +185,21 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
164
185
|
this.trace.set(target, this.currentState.create(this.currentState.value));
|
|
165
186
|
}
|
|
166
187
|
}
|
|
167
|
-
onReplacementCall({
|
|
168
|
-
if (
|
|
169
|
-
|
|
188
|
+
onReplacementCall({ target }) {
|
|
189
|
+
if (target !== undefined) {
|
|
190
|
+
this.unassigned.delete(target);
|
|
170
191
|
}
|
|
171
|
-
this.currentState = this.evalReplacementCall(call, target, source, this.currentState);
|
|
172
|
-
this.unassigned.delete(target);
|
|
173
|
-
}
|
|
174
|
-
onAccessCall({ call }) {
|
|
175
|
-
this.currentState = this.evalAccessCall(call, this.currentState);
|
|
176
|
-
}
|
|
177
|
-
onUnnamedCall({ call }) {
|
|
178
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
179
|
-
}
|
|
180
|
-
onEvalFunctionCall({ call }) {
|
|
181
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
182
|
-
}
|
|
183
|
-
onApplyFunctionCall({ call }) {
|
|
184
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
185
|
-
}
|
|
186
|
-
onSourceCall({ call }) {
|
|
187
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
188
|
-
}
|
|
189
|
-
onGetCall({ call }) {
|
|
190
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
191
|
-
}
|
|
192
|
-
onRmCall({ call }) {
|
|
193
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
194
|
-
}
|
|
195
|
-
onListCall({ call }) {
|
|
196
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
197
|
-
}
|
|
198
|
-
onVectorCall({ call }) {
|
|
199
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
200
|
-
}
|
|
201
|
-
onSpecialBinaryOpCall({ call }) {
|
|
202
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
203
|
-
}
|
|
204
|
-
onQuoteCall({ call }) {
|
|
205
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
206
|
-
}
|
|
207
|
-
onLibraryCall({ call }) {
|
|
208
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
209
|
-
}
|
|
210
|
-
onDefaultFunctionCall({ call }) {
|
|
211
|
-
this.currentState = this.evalFunctionCall(call, this.currentState);
|
|
212
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* This event triggers for every function call that is not a condition, loop, assignment, replacement call, or access operation.
|
|
195
|
+
*
|
|
196
|
+
*
|
|
197
|
+
* For example, this triggers for `data.frame` in `x <- data.frame(id = 1:5, name = letters[1:5])`.
|
|
198
|
+
*
|
|
199
|
+
* This bundles all function calls that are no conditions, loops, assignments, replacement calls, and access operations.
|
|
200
|
+
* @protected
|
|
201
|
+
*/
|
|
202
|
+
onFunctionCall(_data) { }
|
|
213
203
|
/** Gets all AST nodes for the predecessor vertices that are leaf nodes and exit vertices */
|
|
214
204
|
getPredecessorNodes(vertexId) {
|
|
215
205
|
return this.config.controlFlow.graph.outgoingEdges(vertexId)?.keys() // outgoing dependency edges are incoming CFG edges
|
|
@@ -249,7 +239,7 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
249
239
|
return false;
|
|
250
240
|
}
|
|
251
241
|
const origin = dataflowVertex.origin;
|
|
252
|
-
return origin.includes(
|
|
242
|
+
return origin.includes(built_in_1.BuiltInProcName.ForLoop) || origin.includes(built_in_1.BuiltInProcName.WhileLoop) || origin.includes(built_in_1.BuiltInProcName.RepeatLoop);
|
|
253
243
|
}
|
|
254
244
|
/**
|
|
255
245
|
* Checks whether to continue visiting the control flow graph after a widening point.
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
1
|
import type { AbstractDomainValue } from '../domains/abstract-domain';
|
|
3
2
|
import { PosIntervalDomain } from '../domains/positive-interval-domain';
|
|
4
3
|
import { ProductDomain } from '../domains/product-domain';
|
|
5
4
|
import { SetRangeDomain } from '../domains/set-range-domain';
|
|
6
|
-
import { StateAbstractDomain } from '../domains/state-abstract-domain';
|
|
7
5
|
/** The type of the abstract product representing the shape of data frames */
|
|
8
6
|
export type AbstractDataFrameShape = {
|
|
9
7
|
colnames: SetRangeDomain<string>;
|
|
@@ -34,10 +32,3 @@ export declare class DataFrameDomain extends ProductDomain<AbstractDataFrameShap
|
|
|
34
32
|
static top(maxColNames?: number): DataFrameDomain;
|
|
35
33
|
private static refine;
|
|
36
34
|
}
|
|
37
|
-
/**
|
|
38
|
-
* The data frame state abstract domain as state domain mapping AST node IDs to inferred abstract data frame shapes.
|
|
39
|
-
*/
|
|
40
|
-
export declare class DataFrameStateDomain extends StateAbstractDomain<DataFrameDomain> {
|
|
41
|
-
create(value: ReadonlyMap<NodeId, DataFrameDomain>): this;
|
|
42
|
-
static bottom(): DataFrameStateDomain;
|
|
43
|
-
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DataFrameDomain = void 0;
|
|
4
4
|
const lattice_1 = require("../domains/lattice");
|
|
5
5
|
const positive_interval_domain_1 = require("../domains/positive-interval-domain");
|
|
6
6
|
const product_domain_1 = require("../domains/product-domain");
|
|
7
7
|
const set_range_domain_1 = require("../domains/set-range-domain");
|
|
8
|
-
const state_abstract_domain_1 = require("../domains/state-abstract-domain");
|
|
9
8
|
/**
|
|
10
9
|
* The data frame abstract domain as product domain of a column names domain, column count domain, and row count domain.
|
|
11
10
|
*/
|
|
@@ -69,16 +68,4 @@ class DataFrameDomain extends product_domain_1.ProductDomain {
|
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
70
|
exports.DataFrameDomain = DataFrameDomain;
|
|
72
|
-
/**
|
|
73
|
-
* The data frame state abstract domain as state domain mapping AST node IDs to inferred abstract data frame shapes.
|
|
74
|
-
*/
|
|
75
|
-
class DataFrameStateDomain extends state_abstract_domain_1.StateAbstractDomain {
|
|
76
|
-
create(value) {
|
|
77
|
-
return new DataFrameStateDomain(value);
|
|
78
|
-
}
|
|
79
|
-
static bottom() {
|
|
80
|
-
return new DataFrameStateDomain(new Map());
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
exports.DataFrameStateDomain = DataFrameStateDomain;
|
|
84
71
|
//# sourceMappingURL=dataframe-domain.js.map
|
|
@@ -558,7 +558,7 @@ function mapDataFrameFunctionCall(node, inference, dfg, ctx) {
|
|
|
558
558
|
}
|
|
559
559
|
function isDataFrameFunction(functionName) {
|
|
560
560
|
// a check with `functionName in DataFrameFunctionMapper` would return true for "toString"
|
|
561
|
-
return Object.
|
|
561
|
+
return Object.hasOwn(DataFrameFunctionMapper, functionName);
|
|
562
562
|
}
|
|
563
563
|
function getOtherDataFrameFunction(functionName) {
|
|
564
564
|
return OtherDataFrameFunctions.find(entry => entry.names.includes(functionName));
|
|
@@ -6,6 +6,8 @@ import type { DataFrameOperations, DataFrameShapeInferenceVisitor } from '../sha
|
|
|
6
6
|
/**
|
|
7
7
|
* Maps a concrete data frame replacement function call to abstract data frame operations.
|
|
8
8
|
* @param node - The R node of the replacement function call
|
|
9
|
+
* @param expression - The assigned expression node of the replacement function call
|
|
10
|
+
* @param inference - The data frame shape inference visitor for checking data frame arguments
|
|
9
11
|
* @param dfg - The data flow graph for resolving the arguments
|
|
10
12
|
* @param ctx - The current flowR analysis context
|
|
11
13
|
* @returns The mapped abstract data frame operations for the replacement function call, or `undefined` if the node does not represent a data frame replacement function call
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.mapDataFrameReplacementFunction = mapDataFrameReplacementFunction;
|
|
4
4
|
const config_1 = require("../../../config");
|
|
5
|
+
const built_in_1 = require("../../../dataflow/environments/built-in");
|
|
5
6
|
const vertex_1 = require("../../../dataflow/graph/vertex");
|
|
6
7
|
const make_argument_1 = require("../../../dataflow/internal/process/functions/call/argument/make-argument");
|
|
7
8
|
const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
@@ -20,6 +21,8 @@ const DataFrameReplacementFunctionMapper = {
|
|
|
20
21
|
/**
|
|
21
22
|
* Maps a concrete data frame replacement function call to abstract data frame operations.
|
|
22
23
|
* @param node - The R node of the replacement function call
|
|
24
|
+
* @param expression - The assigned expression node of the replacement function call
|
|
25
|
+
* @param inference - The data frame shape inference visitor for checking data frame arguments
|
|
23
26
|
* @param dfg - The data flow graph for resolving the arguments
|
|
24
27
|
* @param ctx - The current flowR analysis context
|
|
25
28
|
* @returns The mapped abstract data frame operations for the replacement function call, or `undefined` if the node does not represent a data frame replacement function call
|
|
@@ -51,11 +54,11 @@ function mapDataFrameReplacementFunction(node, expression, inference, dfg, ctx)
|
|
|
51
54
|
}
|
|
52
55
|
function isDataFrameReplacement(functionName) {
|
|
53
56
|
// a check with `functionName in DataFrameReplacementFunctionMapper` would return true for "toString"
|
|
54
|
-
return Object.
|
|
57
|
+
return Object.hasOwn(DataFrameReplacementFunctionMapper, functionName);
|
|
55
58
|
}
|
|
56
59
|
function hasParentReplacement(node, dfg) {
|
|
57
60
|
const parentVertex = node.info.parent ? dfg.getVertex(node.info.parent) : undefined;
|
|
58
|
-
return (0, vertex_1.isFunctionCallVertex)(parentVertex) && parentVertex.origin.includes(
|
|
61
|
+
return (0, vertex_1.isFunctionCallVertex)(parentVertex) && parentVertex.origin.includes(built_in_1.BuiltInProcName.Replacement);
|
|
59
62
|
}
|
|
60
63
|
function mapDataFrameContentAssignment(access, expression, inference) {
|
|
61
64
|
const dataFrame = access.accessed;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { DataflowGraphVertexFunctionCall } from '../../dataflow/graph/vertex';
|
|
2
|
-
import type { NoInfo } from '../../r-bridge/lang-4.x/ast/model/model';
|
|
3
2
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
4
3
|
import { AbstractInterpretationVisitor, type AbsintVisitorConfiguration } from '../absint-visitor';
|
|
5
|
-
import {
|
|
4
|
+
import { StateAbstractDomain } from '../domains/state-abstract-domain';
|
|
5
|
+
import { DataFrameDomain } from './dataframe-domain';
|
|
6
6
|
import { ConstraintType, type DataFrameOperationArgs, type DataFrameOperationName, type DataFrameOperationOptions } from './semantics';
|
|
7
7
|
interface Operation<Name extends DataFrameOperationName> {
|
|
8
8
|
/** The type of the abstract data frame operation (see {@link DataFrameOperationName}) */
|
|
@@ -36,8 +36,8 @@ interface DataFrameShapeInferenceConfiguration extends Omit<AbsintVisitorConfigu
|
|
|
36
36
|
/**
|
|
37
37
|
* The control flow graph visitor to infer the shape of data frames using abstract interpretation
|
|
38
38
|
*/
|
|
39
|
-
export declare class DataFrameShapeInferenceVisitor extends AbstractInterpretationVisitor<DataFrameDomain,
|
|
40
|
-
domain:
|
|
39
|
+
export declare class DataFrameShapeInferenceVisitor extends AbstractInterpretationVisitor<DataFrameDomain, DataFrameShapeInferenceConfiguration & {
|
|
40
|
+
domain: StateAbstractDomain<DataFrameDomain>;
|
|
41
41
|
}> {
|
|
42
42
|
/**
|
|
43
43
|
* The abstract data frame operations the function call nodes are mapped to.
|
|
@@ -51,9 +51,17 @@ export declare class DataFrameShapeInferenceVisitor extends AbstractInterpretati
|
|
|
51
51
|
* @returns The mapped abstract data frame operations for the node, or `undefined` if no abstract operation was mapped for the node or storing mapped abstract operations is disabled via the visitor config.
|
|
52
52
|
*/
|
|
53
53
|
getAbstractOperations(id: NodeId | undefined): Readonly<DataFrameOperations>;
|
|
54
|
-
protected
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
protected onFunctionCall({ call }: {
|
|
55
|
+
call: DataflowGraphVertexFunctionCall;
|
|
56
|
+
}): void;
|
|
57
|
+
protected onReplacementCall({ call, target, source }: {
|
|
58
|
+
call: DataflowGraphVertexFunctionCall;
|
|
59
|
+
target?: NodeId;
|
|
60
|
+
source?: NodeId;
|
|
61
|
+
}): void;
|
|
62
|
+
protected onAccessCall({ call }: {
|
|
63
|
+
call: DataflowGraphVertexFunctionCall;
|
|
64
|
+
}): void;
|
|
57
65
|
private applyDataFrameExpression;
|
|
58
66
|
}
|
|
59
67
|
export {};
|
|
@@ -2,6 +2,7 @@
|
|
|
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");
|
|
5
6
|
const dataframe_domain_1 = require("./dataframe-domain");
|
|
6
7
|
const access_mapper_1 = require("./mappers/access-mapper");
|
|
7
8
|
const function_mapper_1 = require("./mappers/function-mapper");
|
|
@@ -16,7 +17,7 @@ class DataFrameShapeInferenceVisitor extends absint_visitor_1.AbstractInterpreta
|
|
|
16
17
|
*/
|
|
17
18
|
operations;
|
|
18
19
|
constructor({ trackOperations = true, ...config }) {
|
|
19
|
-
super({ ...config, domain:
|
|
20
|
+
super({ ...config, domain: state_abstract_domain_1.StateAbstractDomain.bottom() });
|
|
20
21
|
if (trackOperations) {
|
|
21
22
|
this.operations = new Map();
|
|
22
23
|
}
|
|
@@ -30,35 +31,38 @@ class DataFrameShapeInferenceVisitor extends absint_visitor_1.AbstractInterpreta
|
|
|
30
31
|
getAbstractOperations(id) {
|
|
31
32
|
return id !== undefined ? this.operations?.get(id) : undefined;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
onFunctionCall({ call }) {
|
|
35
|
+
super.onFunctionCall({ call });
|
|
34
36
|
const node = this.getNormalizedAst(call.id);
|
|
35
37
|
if (node === undefined) {
|
|
36
|
-
return
|
|
38
|
+
return;
|
|
37
39
|
}
|
|
38
40
|
const operations = (0, function_mapper_1.mapDataFrameFunctionCall)(node, this, this.config.dfg, this.config.ctx);
|
|
39
|
-
|
|
41
|
+
this.applyDataFrameExpression(node, operations);
|
|
40
42
|
}
|
|
41
|
-
|
|
43
|
+
onReplacementCall({ call, target, source }) {
|
|
44
|
+
super.onReplacementCall({ call, target, source });
|
|
42
45
|
const node = this.getNormalizedAst(call.id);
|
|
43
46
|
const targetNode = this.getNormalizedAst(target);
|
|
44
47
|
const sourceNode = this.getNormalizedAst(source);
|
|
45
48
|
if (node === undefined || targetNode === undefined || sourceNode === undefined) {
|
|
46
|
-
return
|
|
49
|
+
return;
|
|
47
50
|
}
|
|
48
51
|
const operations = (0, replacement_mapper_1.mapDataFrameReplacementFunction)(node, sourceNode, this, this.config.dfg, this.config.ctx);
|
|
49
|
-
|
|
52
|
+
this.applyDataFrameExpression(node, operations);
|
|
50
53
|
}
|
|
51
|
-
|
|
54
|
+
onAccessCall({ call }) {
|
|
55
|
+
super.onAccessCall({ call });
|
|
52
56
|
const node = this.getNormalizedAst(call.id);
|
|
53
57
|
if (node === undefined) {
|
|
54
|
-
return
|
|
58
|
+
return;
|
|
55
59
|
}
|
|
56
60
|
const operations = (0, access_mapper_1.mapDataFrameAccess)(node, this, this.config.dfg, this.config.ctx);
|
|
57
|
-
|
|
61
|
+
this.applyDataFrameExpression(node, operations);
|
|
58
62
|
}
|
|
59
|
-
applyDataFrameExpression(node, operations
|
|
63
|
+
applyDataFrameExpression(node, operations) {
|
|
60
64
|
if (operations === undefined) {
|
|
61
|
-
return
|
|
65
|
+
return;
|
|
62
66
|
}
|
|
63
67
|
else if (this.operations !== undefined) {
|
|
64
68
|
this.operations.set(node.info.id, operations);
|
|
@@ -66,20 +70,19 @@ class DataFrameShapeInferenceVisitor extends absint_visitor_1.AbstractInterpreta
|
|
|
66
70
|
const maxColNames = this.config.ctx.config.abstractInterpretation.dataFrame.maxColNames;
|
|
67
71
|
let value = dataframe_domain_1.DataFrameDomain.top(maxColNames);
|
|
68
72
|
for (const { operation, operand, type, options, ...args } of operations) {
|
|
69
|
-
const operandValue = operand !== undefined ? this.getAbstractValue(operand,
|
|
73
|
+
const operandValue = operand !== undefined ? this.getAbstractValue(operand, this.currentState) : value;
|
|
70
74
|
value = (0, semantics_1.applyDataFrameSemantics)(operation, operandValue ?? dataframe_domain_1.DataFrameDomain.top(maxColNames), args, options);
|
|
71
75
|
const constraintType = type ?? (0, semantics_1.getConstraintType)(operation);
|
|
72
76
|
if (operand !== undefined && constraintType === semantics_1.ConstraintType.OperandModification) {
|
|
73
|
-
|
|
77
|
+
this.currentState.set(operand, value);
|
|
74
78
|
for (const origin of this.getVariableOrigins(operand)) {
|
|
75
|
-
|
|
79
|
+
this.currentState.set(origin, value);
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
else if (constraintType === semantics_1.ConstraintType.ResultPostcondition) {
|
|
79
|
-
|
|
83
|
+
this.currentState.set(node.info.id, value);
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
|
-
return state;
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
exports.DataFrameShapeInferenceVisitor = DataFrameShapeInferenceVisitor;
|