@eagleoutice/flowr 2.9.9 → 2.9.11
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 +57 -54
- package/abstract-interpretation/absint-visitor.d.ts +16 -14
- package/abstract-interpretation/absint-visitor.js +93 -47
- package/abstract-interpretation/data-frame/mappers/arguments.d.ts +1 -1
- package/abstract-interpretation/data-frame/mappers/arguments.js +2 -2
- 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/set-range-domain.js +1 -1
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +30 -1
- package/abstract-interpretation/domains/state-abstract-domain.js +130 -4
- package/abstract-interpretation/normalized-ast-fold.d.ts +2 -2
- package/abstract-interpretation/normalized-ast-fold.js +4 -3
- package/benchmark/slicer.js +5 -5
- package/benchmark/summarizer/first-phase/process.js +4 -4
- package/cli/repl/commands/repl-normalize.js +2 -2
- package/cli/repl/core.js +2 -2
- package/config.js +1 -1
- package/control-flow/cfg-simplification.d.ts +1 -0
- package/control-flow/cfg-simplification.js +1 -0
- package/control-flow/control-flow-graph.d.ts +1 -1
- package/control-flow/control-flow-graph.js +1 -2
- package/control-flow/extract-cfg.js +34 -15
- package/control-flow/semantic-cfg-guided-visitor.js +1 -0
- package/dataflow/cluster.js +1 -1
- package/dataflow/environments/built-in.d.ts +6 -15
- package/dataflow/environments/built-in.js +25 -33
- 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 +2 -2
- package/dataflow/eval/resolve/alias-tracking.js +6 -6
- package/dataflow/eval/resolve/resolve.js +12 -10
- package/dataflow/fn/exceptions-of-function.d.ts +1 -1
- package/dataflow/fn/exceptions-of-function.js +2 -1
- package/dataflow/graph/call-graph.d.ts +1 -1
- package/dataflow/graph/call-graph.js +4 -3
- package/dataflow/graph/dataflowgraph-builder.d.ts +1 -1
- package/dataflow/graph/dataflowgraph-builder.js +21 -21
- package/dataflow/graph/graph.d.ts +5 -5
- package/dataflow/graph/graph.js +36 -32
- 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 +4 -4
- package/dataflow/internal/linker.js +59 -33
- package/dataflow/internal/process/functions/call/argument/make-argument.d.ts +2 -1
- package/dataflow/internal/process/functions/call/argument/make-argument.js +3 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +3 -5
- 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 +6 -5
- 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-function-definition.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-local.js +3 -3
- 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-replacement.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.js +7 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.js +3 -3
- 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/common.d.ts +1 -1
- package/dataflow/internal/process/functions/call/common.js +43 -35
- package/dataflow/internal/process/functions/call/known-call-handling.js +0 -2
- package/dataflow/internal/process/functions/process-argument.d.ts +1 -1
- package/dataflow/internal/process/functions/process-argument.js +3 -3
- package/dataflow/internal/process/functions/process-parameter.js +2 -2
- package/dataflow/origin/dfg-get-origin.d.ts +1 -1
- package/dataflow/origin/dfg-get-origin.js +2 -2
- package/documentation/doc-util/doc-types.js +1 -1
- package/documentation/wiki-absint.js +7 -8
- package/documentation/wiki-cfg.js +3 -3
- package/documentation/wiki-mk/doc-context.d.ts +8 -0
- package/documentation/wiki-mk/doc-context.js +4 -0
- package/documentation/wiki-normalized-ast.d.ts +1 -1
- package/documentation/wiki-normalized-ast.js +9 -6
- package/linter/linter-format.d.ts +10 -0
- package/linter/linter-format.js +15 -0
- package/linter/rules/absolute-path.js +3 -3
- package/linter/rules/dead-code.js +1 -1
- package/linter/rules/file-path-validity.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 +9 -0
- package/project/plugins/file-plugins/files/flowr-description-file.js +12 -0
- package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +1 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +4 -5
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +2 -1
- package/queries/catalog/dependencies-query/dependencies-query-format.js +6 -5
- 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/queries/catalog/does-call-query/does-call-query-executor.js +3 -3
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.d.ts +1 -1
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.js +2 -2
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +1 -1
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.js +1 -1
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.d.ts +1 -1
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.js +1 -1
- package/queries/query-print.d.ts +1 -1
- package/queries/query-print.js +4 -3
- package/r-bridge/lang-4.x/ast/model/model.d.ts +151 -4
- package/r-bridge/lang-4.x/ast/model/model.js +249 -0
- package/r-bridge/lang-4.x/ast/model/nodes/info/r-delimiter.d.ts +11 -1
- package/r-bridge/lang-4.x/ast/model/nodes/info/r-delimiter.js +13 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +19 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.js +26 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +36 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.js +48 -13
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.js +21 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +11 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-break.js +14 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +8 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.js +11 -5
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +23 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.js +32 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +11 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.js +14 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +19 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.js +26 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +11 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.js +14 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +11 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.js +14 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +12 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.js +14 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +20 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-logical.js +26 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +12 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-next.js +14 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +8 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +11 -5
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +17 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.js +22 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.js +22 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-project.d.ts +45 -8
- package/r-bridge/lang-4.x/ast/model/nodes/r-project.js +57 -16
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +12 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.js +14 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +15 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +21 -6
- package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +21 -6
- package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.js +22 -5
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.js +21 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +11 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.js +14 -0
- package/r-bridge/lang-4.x/ast/model/processing/decorate.js +23 -17
- package/r-bridge/lang-4.x/ast/model/processing/node-id.d.ts +39 -2
- package/r-bridge/lang-4.x/ast/model/processing/node-id.js +52 -9
- package/r-bridge/lang-4.x/ast/model/processing/role.d.ts +18 -17
- package/r-bridge/lang-4.x/ast/model/processing/visitor.d.ts +8 -7
- package/r-bridge/lang-4.x/ast/model/processing/visitor.js +6 -13
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +4 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-number.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-string.js +2 -2
- package/r-bridge/lang-4.x/convert-values.d.ts +14 -5
- package/r-bridge/lang-4.x/convert-values.js +76 -72
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +33 -15
- package/r-bridge/roxygen2/roxygen-parse.js +1 -1
- package/r-bridge/shell-executor.js +1 -1
- package/reconstruct/auto-select/magic-comments.js +4 -4
- package/reconstruct/reconstruct.js +2 -1
- package/search/search-executor/search-generators.js +2 -2
- package/slicing/criterion/filters/all-variables.js +1 -1
- package/slicing/criterion/parse.d.ts +1 -1
- package/slicing/criterion/parse.js +5 -3
- package/slicing/static/slice-call.d.ts +1 -1
- package/slicing/static/slice-call.js +2 -2
- package/statistics/features/supported/assignments/assignments.js +2 -2
- package/statistics/features/supported/control-flow/control-flow.js +2 -2
- package/statistics/features/supported/data-access/data-access.js +6 -5
- package/statistics/features/supported/defined-functions/defined-functions.js +9 -8
- package/statistics/features/supported/expression-list/statistics-expression-list.js +2 -2
- package/statistics/features/supported/loops/loops.js +6 -5
- package/statistics/features/supported/used-functions/used-functions.js +2 -2
- package/statistics/features/supported/variables/variables.js +8 -8
- package/util/mermaid/ast.js +3 -3
- package/util/mermaid/cfg.js +3 -4
- package/util/mermaid/dfg.d.ts +1 -1
- package/util/mermaid/dfg.js +13 -12
- package/util/simple-df/dfg-ascii.js +1 -1
- package/util/version.js +1 -1
- package/r-bridge/lang-4.x/ast/model/collect.d.ts +0 -10
- package/r-bridge/lang-4.x/ast/model/collect.js +0 -25
|
@@ -6,10 +6,12 @@ const semantic_cfg_guided_visitor_1 = require("../control-flow/semantic-cfg-guid
|
|
|
6
6
|
const built_in_1 = require("../dataflow/environments/built-in");
|
|
7
7
|
const vertex_1 = require("../dataflow/graph/vertex");
|
|
8
8
|
const dfg_get_origin_1 = require("../dataflow/origin/dfg-get-origin");
|
|
9
|
+
const model_1 = require("../r-bridge/lang-4.x/ast/model/model");
|
|
9
10
|
const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
10
11
|
const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
|
|
11
12
|
const assert_1 = require("../util/assert");
|
|
12
13
|
const abstract_domain_1 = require("./domains/abstract-domain");
|
|
14
|
+
const state_abstract_domain_1 = require("./domains/state-abstract-domain");
|
|
13
15
|
/**
|
|
14
16
|
* A control flow graph visitor to perform abstract interpretation.
|
|
15
17
|
*
|
|
@@ -23,14 +25,35 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
23
25
|
/**
|
|
24
26
|
* The current abstract state domain at the currently processed AST node.
|
|
25
27
|
*/
|
|
26
|
-
|
|
28
|
+
_currentState;
|
|
27
29
|
/**
|
|
28
30
|
* A set of nodes representing variable definitions that have already been visited but whose assignment has not yet been processed.
|
|
29
31
|
*/
|
|
30
32
|
unassigned = new Set();
|
|
33
|
+
/**
|
|
34
|
+
* Whether the current abstract state has been copied/cloned and is save to modify in place.
|
|
35
|
+
*/
|
|
36
|
+
stateCopied = false;
|
|
31
37
|
constructor(config) {
|
|
32
38
|
super({ ...config, defaultVisitingOrder: 'forward', defaultVisitingType: 'exit' });
|
|
33
|
-
this.
|
|
39
|
+
this._currentState = new state_abstract_domain_1.MutableStateAbstractDomain(new Map());
|
|
40
|
+
}
|
|
41
|
+
get currentState() {
|
|
42
|
+
return this._currentState;
|
|
43
|
+
}
|
|
44
|
+
removeState(node) {
|
|
45
|
+
if (!this.stateCopied) {
|
|
46
|
+
this._currentState = this._currentState.create(this.currentState.value);
|
|
47
|
+
this.stateCopied = true;
|
|
48
|
+
}
|
|
49
|
+
this._currentState.remove(node);
|
|
50
|
+
}
|
|
51
|
+
updateState(node, value) {
|
|
52
|
+
if (!this.stateCopied) {
|
|
53
|
+
this._currentState = this._currentState.create(this.currentState.value);
|
|
54
|
+
this.stateCopied = true;
|
|
55
|
+
}
|
|
56
|
+
this._currentState.set(node, value);
|
|
34
57
|
}
|
|
35
58
|
/**
|
|
36
59
|
* Resolves the inferred abstract value of an AST node.
|
|
@@ -49,7 +72,7 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
49
72
|
return state.get(node.info.id);
|
|
50
73
|
}
|
|
51
74
|
const vertex = this.getDataflowGraph(node.info.id);
|
|
52
|
-
const call =
|
|
75
|
+
const call = (0, vertex_1.isFunctionCallVertex)(vertex) ? vertex : undefined;
|
|
53
76
|
const origins = Array.isArray(call?.origin) ? call.origin : [];
|
|
54
77
|
if (node.type === type_1.RType.Symbol) {
|
|
55
78
|
const values = this.getVariableOrigins(node.info.id).map(origin => state?.get(origin));
|
|
@@ -100,9 +123,9 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
100
123
|
*/
|
|
101
124
|
getEndState() {
|
|
102
125
|
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
|
|
126
|
+
const exitNodes = exitPoints.map(control_flow_graph_1.CfgVertex.getRootId).filter(assert_1.isNotUndefined);
|
|
127
|
+
const states = exitNodes.map(node => this.trace.get(node)).filter(assert_1.isNotUndefined);
|
|
128
|
+
return abstract_domain_1.AbstractDomain.joinAll(states, this._currentState.top());
|
|
106
129
|
}
|
|
107
130
|
/**
|
|
108
131
|
* Gets the inferred abstract trace mapping AST nodes to the inferred abstract state at the respective node.
|
|
@@ -116,38 +139,66 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
116
139
|
super.start();
|
|
117
140
|
this.unassigned.clear();
|
|
118
141
|
}
|
|
142
|
+
startVisitor(start) {
|
|
143
|
+
const stack = Array.from(start);
|
|
144
|
+
while (stack.length > 0) {
|
|
145
|
+
const current = stack.pop();
|
|
146
|
+
if (!this.visitNode(current)) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
for (const next of this.config.controlFlow.graph.ingoingEdges(current)?.keys().toArray().reverse() ?? []) {
|
|
150
|
+
if (!stack.includes(next)) { // prevent double entries in working list
|
|
151
|
+
stack.push(next);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
119
156
|
visitNode(vertexId) {
|
|
120
157
|
const vertex = this.getCfgVertex(vertexId);
|
|
121
|
-
|
|
158
|
+
// skip exit vertices of widening points and entry vertices of complex nodes
|
|
159
|
+
if (vertex === undefined || this.shouldSkipVertex(vertex)) {
|
|
122
160
|
return true;
|
|
123
161
|
}
|
|
162
|
+
const predecessors = this.getPredecessorNodes(control_flow_graph_1.CfgVertex.getId(vertex));
|
|
163
|
+
const predecessorStates = predecessors.map(pred => this.trace.get(pred)).filter(assert_1.isNotUndefined);
|
|
164
|
+
// retrieve new abstract state by joining states of predecessor nodes
|
|
165
|
+
if (predecessorStates.length === 1) {
|
|
166
|
+
this._currentState = predecessorStates[0];
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this._currentState = abstract_domain_1.AbstractDomain.joinAll(predecessorStates, this._currentState.top());
|
|
170
|
+
this.stateCopied = true;
|
|
171
|
+
}
|
|
124
172
|
const nodeId = control_flow_graph_1.CfgVertex.getRootId(vertex);
|
|
173
|
+
// differentiate between widening points and other vertices
|
|
125
174
|
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);
|
|
175
|
+
const oldState = this.trace.get(nodeId) ?? this._currentState.top();
|
|
133
176
|
if (this.shouldWiden(vertex)) {
|
|
134
|
-
this.
|
|
177
|
+
this._currentState = oldState.widen(this._currentState);
|
|
178
|
+
this.stateCopied = true;
|
|
135
179
|
}
|
|
136
|
-
this.trace.set(nodeId, this.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
180
|
+
this.trace.set(nodeId, this._currentState);
|
|
181
|
+
this.stateCopied = false;
|
|
182
|
+
const visitedCount = this.visited.get(nodeId) ?? 0;
|
|
183
|
+
this.visited.set(nodeId, visitedCount + 1);
|
|
184
|
+
// continue visiting after widening point if visited for the first time or the state changed
|
|
185
|
+
return visitedCount === 0 || !oldState.equals(this._currentState);
|
|
141
186
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
187
|
+
else {
|
|
188
|
+
this.onVisitNode(vertexId);
|
|
189
|
+
// discard the inferred abstract state when encountering functions with unknown side effects (e.g. `eval`)
|
|
190
|
+
if (this.config.dfg.unknownSideEffects.has(nodeId)) {
|
|
191
|
+
this._currentState = this._currentState.top();
|
|
192
|
+
this.stateCopied = true;
|
|
193
|
+
}
|
|
194
|
+
this.trace.set(nodeId, this._currentState);
|
|
195
|
+
this.stateCopied = false;
|
|
196
|
+
const predecessorVisits = predecessors.map(pred => this.visited.get(pred) ?? 0);
|
|
197
|
+
const visitedCount = this.visited.get(nodeId) ?? 0;
|
|
198
|
+
this.visited.set(nodeId, visitedCount + 1);
|
|
199
|
+
// continue visiting if vertex is not a join vertex or number of visits of predecessors is the same
|
|
200
|
+
return predecessors.length <= 1 || predecessorVisits.every(visits => visits === predecessorVisits[0]);
|
|
148
201
|
}
|
|
149
|
-
this.trace.set(nodeId, this.currentState);
|
|
150
|
-
return true;
|
|
151
202
|
}
|
|
152
203
|
onDispatchFunctionCallOrigin(call, origin) {
|
|
153
204
|
super.onDispatchFunctionCallOrigin(call, origin);
|
|
@@ -183,8 +234,9 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
183
234
|
const value = this.getAbstractValue(source);
|
|
184
235
|
this.unassigned.delete(target);
|
|
185
236
|
if (value !== undefined) {
|
|
186
|
-
this.
|
|
187
|
-
this.trace.set(target, this.
|
|
237
|
+
this.updateState(target, value);
|
|
238
|
+
this.trace.set(target, this._currentState);
|
|
239
|
+
this.stateCopied = false;
|
|
188
240
|
}
|
|
189
241
|
}
|
|
190
242
|
onReplacementCall({ target }) {
|
|
@@ -204,7 +256,7 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
204
256
|
onFunctionCall(_data) { }
|
|
205
257
|
/** Gets all AST nodes for the predecessor vertices that are leaf nodes and exit vertices */
|
|
206
258
|
getPredecessorNodes(vertexId) {
|
|
207
|
-
return this.config.controlFlow.graph.outgoingEdges(vertexId)?.keys() // outgoing dependency edges are
|
|
259
|
+
return this.config.controlFlow.graph.outgoingEdges(vertexId)?.keys() // outgoing dependency edges are ingoing CFG edges
|
|
208
260
|
.map(id => this.getCfgVertex(id))
|
|
209
261
|
.flatMap(vertex => {
|
|
210
262
|
if (vertex === undefined) {
|
|
@@ -226,14 +278,14 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
226
278
|
.map(origin => origin.id)
|
|
227
279
|
.filter(origin => this.trace.has(origin) && !this.unassigned.has(origin)) ?? [];
|
|
228
280
|
}
|
|
229
|
-
/** We only perform widening at `for`, `while`, or `repeat` loops with more than one
|
|
281
|
+
/** We only perform widening at `for`, `while`, or `repeat` loops with more than one ingoing CFG edge */
|
|
230
282
|
isWideningPoint(nodeId) {
|
|
231
|
-
const
|
|
232
|
-
if (
|
|
283
|
+
const ingoingEdges = this.config.controlFlow.graph.outgoingEdges(nodeId)?.size; // outgoing dependency edges are ingoing CFG edges
|
|
284
|
+
if (ingoingEdges === undefined || ingoingEdges <= 1) {
|
|
233
285
|
return false;
|
|
234
286
|
}
|
|
235
287
|
const node = this.getNormalizedAst(nodeId);
|
|
236
|
-
if (
|
|
288
|
+
if (model_1.RLoopConstructs.is(node)) {
|
|
237
289
|
return true;
|
|
238
290
|
}
|
|
239
291
|
const dataflowVertex = this.getDataflowGraph(nodeId);
|
|
@@ -243,26 +295,20 @@ class AbstractInterpretationVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
243
295
|
const origin = dataflowVertex.origin;
|
|
244
296
|
return origin.includes(built_in_1.BuiltInProcName.ForLoop) || origin.includes(built_in_1.BuiltInProcName.WhileLoop) || origin.includes(built_in_1.BuiltInProcName.RepeatLoop);
|
|
245
297
|
}
|
|
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
298
|
/**
|
|
257
299
|
* 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).
|
|
300
|
+
* By default, we only process entry vertices of widening points, vertices of leaf nodes, and exit vertices (no entry nodes of complex nodes).
|
|
259
301
|
*/
|
|
260
302
|
shouldSkipVertex(vertex) {
|
|
303
|
+
if (this.isWideningPoint(control_flow_graph_1.CfgVertex.getRootId(vertex))) {
|
|
304
|
+
// skip exit vertices of widening points
|
|
305
|
+
return control_flow_graph_1.CfgVertex.isMarker(vertex);
|
|
306
|
+
}
|
|
261
307
|
return !control_flow_graph_1.CfgVertex.isMarker(vertex) && !control_flow_graph_1.CfgVertex.isBlock(vertex) && control_flow_graph_1.CfgVertex.getEnd(vertex) !== undefined;
|
|
262
308
|
}
|
|
263
309
|
/**
|
|
264
310
|
* Whether widening should be performed at a widening point.
|
|
265
|
-
* By default, we perform widening when the number of
|
|
311
|
+
* By default, we perform widening when the number of visits of the widening point reaches the widening threshold of the config.
|
|
266
312
|
*/
|
|
267
313
|
shouldWiden(wideningPoint) {
|
|
268
314
|
return (this.visited.get(control_flow_graph_1.CfgVertex.getId(wideningPoint)) ?? 0) >= this.config.ctx.config.abstractInterpretation.wideningThreshold;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ResolveInfo } from '../../../dataflow/eval/resolve/alias-tracking';
|
|
2
2
|
import type { DataflowGraph } from '../../../dataflow/graph/graph';
|
|
3
|
-
import
|
|
3
|
+
import { RNode } from '../../../r-bridge/lang-4.x/ast/model/model';
|
|
4
4
|
import type { RArgument } from '../../../r-bridge/lang-4.x/ast/model/nodes/r-argument';
|
|
5
5
|
import { type RFunctionArgument, type RFunctionCall, EmptyArgument } from '../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
6
|
import type { RSymbol } from '../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
@@ -15,8 +15,8 @@ exports.isValidColName = isValidColName;
|
|
|
15
15
|
exports.parseRequestContent = parseRequestContent;
|
|
16
16
|
const vertex_1 = require("../../../dataflow/graph/vertex");
|
|
17
17
|
const make_argument_1 = require("../../../dataflow/internal/process/functions/call/argument/make-argument");
|
|
18
|
+
const model_1 = require("../../../r-bridge/lang-4.x/ast/model/model");
|
|
18
19
|
const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
19
|
-
const visitor_1 = require("../../../r-bridge/lang-4.x/ast/model/processing/visitor");
|
|
20
20
|
const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
|
|
21
21
|
const convert_values_1 = require("../../../r-bridge/lang-4.x/convert-values");
|
|
22
22
|
const assert_1 = require("../../../util/assert");
|
|
@@ -133,7 +133,7 @@ function getUnresolvedSymbolsInExpression(expression, dfg) {
|
|
|
133
133
|
return [];
|
|
134
134
|
}
|
|
135
135
|
const unresolvedSymbols = [];
|
|
136
|
-
|
|
136
|
+
model_1.RNode.visitAst(expression, node => {
|
|
137
137
|
if (node.type === type_1.RType.Symbol) {
|
|
138
138
|
const vertex = dfg.get(node.info.id);
|
|
139
139
|
if ((0, vertex_1.isUseVertex)(vertex?.[0]) && vertex[1].size === 0) {
|
|
@@ -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.
|
|
@@ -48,19 +48,19 @@ class AbstractDomain {
|
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* Joins an array of abstract values by joining the first abstract value with the other values in the array.
|
|
51
|
-
* The provided array of abstract values
|
|
51
|
+
* The provided array of abstract values must not be empty or a default value must be provided!
|
|
52
52
|
*/
|
|
53
|
-
static joinAll(values) {
|
|
54
|
-
(0, assert_1.guard)(values.length > 0, 'Abstract values to join cannot be empty');
|
|
55
|
-
return values[0]
|
|
53
|
+
static joinAll(values, defaultValue) {
|
|
54
|
+
(0, assert_1.guard)(values.length > 0 || defaultValue !== undefined, 'Abstract values to join cannot be empty');
|
|
55
|
+
return values[0]?.joinAll(values.slice(1)) ?? defaultValue;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
58
|
* Meets an array of abstract values by meeting the first abstract value with the other values in the array.
|
|
59
|
-
* The provided array of abstract values
|
|
59
|
+
* The provided array of abstract values must not be empty or a default value must be provided!
|
|
60
60
|
*/
|
|
61
|
-
static meetAll(values) {
|
|
62
|
-
(0, assert_1.guard)(values.length > 0, 'Abstract values to meet cannot be empty');
|
|
63
|
-
return values[0]
|
|
61
|
+
static meetAll(values, defaultValue) {
|
|
62
|
+
(0, assert_1.guard)(values.length > 0 || defaultValue !== undefined, 'Abstract values to meet cannot be empty');
|
|
63
|
+
return values[0]?.meetAll(values.slice(1)) ?? defaultValue;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
exports.AbstractDomain = AbstractDomain;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { AbstractDomain, type AnyAbstractDomain, type ConcreteDomain } from './abstract-domain';
|
|
2
2
|
import { Top } from './lattice';
|
|
3
3
|
/** The type of the concrete mapping of the concrete domain of a mapped abstract domain mapping keys to a concrete value in the concrete domain */
|
|
4
|
-
type ConcreteMap<Key, Domain extends AnyAbstractDomain> = ReadonlyMap<Key, ConcreteDomain<Domain>>;
|
|
4
|
+
export type ConcreteMap<Key, Domain extends AnyAbstractDomain> = ReadonlyMap<Key, ConcreteDomain<Domain>>;
|
|
5
5
|
/**
|
|
6
6
|
* A mapped abstract domain as mapping of keys to abstract values of an abstract domain.
|
|
7
7
|
* The Bottom element is defined as empty mapping and the Top element is defined as mapping every existing key to Top.
|
|
8
8
|
* @template Key - Type of the keys of the mapping to abstract values
|
|
9
9
|
* @template Domain - Type of the abstract domain to map the keys to
|
|
10
10
|
*/
|
|
11
|
-
export declare
|
|
11
|
+
export declare class MappedAbstractDomain<Key, Domain extends AnyAbstractDomain> extends AbstractDomain<ConcreteMap<Key, Domain>, ReadonlyMap<Key, Domain>, ReadonlyMap<Key, Domain>, ReadonlyMap<Key, Domain>> {
|
|
12
12
|
constructor(value: ReadonlyMap<Key, Domain>);
|
|
13
|
-
|
|
13
|
+
create(value: ReadonlyMap<Key, Domain>): this;
|
|
14
14
|
get(key: Key): Domain | undefined;
|
|
15
15
|
has(key: Key): boolean;
|
|
16
|
-
set(key: Key, value: Domain): void;
|
|
16
|
+
protected set(key: Key, value: Domain): void;
|
|
17
17
|
protected remove(key: Key): void;
|
|
18
18
|
bottom(): this;
|
|
19
19
|
top(): this;
|
|
@@ -31,4 +31,11 @@ export declare abstract class MappedAbstractDomain<Key, Domain extends AnyAbstra
|
|
|
31
31
|
isBottom(): this is this;
|
|
32
32
|
isValue(): this is this;
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* A mutable version of the {@link MappedAbstractDomain} with {@link MutableMappedAbstractDomain#set|`set`} and {@link MutableMappedAbstractDomain#remove|`remove`}.
|
|
36
|
+
*/
|
|
37
|
+
export declare class MutableMappedAbstractDomain<Key, Domain extends AnyAbstractDomain> extends MappedAbstractDomain<Key, Domain> {
|
|
38
|
+
create(value: ReadonlyMap<Key, Domain>): this;
|
|
39
|
+
set(key: Key, value: Domain): void;
|
|
40
|
+
remove(key: Key): void;
|
|
41
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MappedAbstractDomain = void 0;
|
|
3
|
+
exports.MutableMappedAbstractDomain = exports.MappedAbstractDomain = void 0;
|
|
4
4
|
const abstract_domain_1 = require("./abstract-domain");
|
|
5
5
|
const lattice_1 = require("./lattice");
|
|
6
6
|
/**
|
|
@@ -13,6 +13,9 @@ class MappedAbstractDomain extends abstract_domain_1.AbstractDomain {
|
|
|
13
13
|
constructor(value) {
|
|
14
14
|
super(new Map(value));
|
|
15
15
|
}
|
|
16
|
+
create(value) {
|
|
17
|
+
return new MappedAbstractDomain(value);
|
|
18
|
+
}
|
|
16
19
|
get(key) {
|
|
17
20
|
return this._value.get(key);
|
|
18
21
|
}
|
|
@@ -122,50 +125,56 @@ class MappedAbstractDomain extends abstract_domain_1.AbstractDomain {
|
|
|
122
125
|
return result;
|
|
123
126
|
}
|
|
124
127
|
concretize(limit) {
|
|
125
|
-
if (this.value.
|
|
128
|
+
if (this.value.size === 0) {
|
|
126
129
|
return new Set();
|
|
127
130
|
}
|
|
128
|
-
let
|
|
131
|
+
let mappings = new Set([new Map()]);
|
|
129
132
|
for (const [key, value] of this.value) {
|
|
130
133
|
const concreteValues = value.concretize(limit);
|
|
131
134
|
if (concreteValues === lattice_1.Top) {
|
|
132
135
|
return lattice_1.Top;
|
|
133
136
|
}
|
|
134
|
-
const
|
|
135
|
-
for (const state of
|
|
137
|
+
const newMappings = new Set();
|
|
138
|
+
for (const state of mappings) {
|
|
136
139
|
for (const concrete of concreteValues) {
|
|
137
|
-
if (
|
|
140
|
+
if (newMappings.size > limit) {
|
|
138
141
|
return lattice_1.Top;
|
|
139
142
|
}
|
|
140
143
|
const map = new Map(state);
|
|
141
144
|
map.set(key, concrete);
|
|
142
|
-
|
|
145
|
+
newMappings.add(map);
|
|
143
146
|
}
|
|
144
147
|
}
|
|
145
|
-
|
|
148
|
+
mappings = newMappings;
|
|
146
149
|
}
|
|
147
|
-
return
|
|
150
|
+
return mappings;
|
|
148
151
|
}
|
|
149
152
|
abstract(concrete) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
if (concrete === lattice_1.Top) {
|
|
154
|
+
return this.top();
|
|
155
|
+
}
|
|
156
|
+
else if (concrete.size === 0) {
|
|
157
|
+
return this.bottom();
|
|
158
|
+
}
|
|
159
|
+
const domain = this.value.values().toArray()[0];
|
|
160
|
+
if (domain === undefined) {
|
|
161
|
+
return this.top();
|
|
162
|
+
}
|
|
163
|
+
const mapping = new Map();
|
|
164
|
+
for (const concreteMapping of concrete) {
|
|
165
|
+
for (const [key, value] of concreteMapping) {
|
|
166
|
+
const set = mapping.get(key);
|
|
167
|
+
if (set === undefined) {
|
|
168
|
+
mapping.set(key, new Set([value]));
|
|
160
169
|
}
|
|
161
170
|
else {
|
|
162
|
-
|
|
171
|
+
set.add(value);
|
|
163
172
|
}
|
|
164
173
|
}
|
|
165
174
|
}
|
|
166
175
|
const result = new Map();
|
|
167
|
-
for (const [key, values] of
|
|
168
|
-
result.set(key,
|
|
176
|
+
for (const [key, values] of mapping) {
|
|
177
|
+
result.set(key, domain.abstract(values));
|
|
169
178
|
}
|
|
170
179
|
return this.create(result);
|
|
171
180
|
}
|
|
@@ -176,7 +185,7 @@ class MappedAbstractDomain extends abstract_domain_1.AbstractDomain {
|
|
|
176
185
|
return '(' + this.value.entries().toArray().map(([key, value]) => `${(0, abstract_domain_1.domainElementToString)(key)} -> ${value.toString()}`).join(', ') + ')';
|
|
177
186
|
}
|
|
178
187
|
isTop() {
|
|
179
|
-
return this.value.
|
|
188
|
+
return this.value.values().some(entry => entry.isTop());
|
|
180
189
|
}
|
|
181
190
|
isBottom() {
|
|
182
191
|
return this.value.size === 0;
|
|
@@ -186,4 +195,19 @@ class MappedAbstractDomain extends abstract_domain_1.AbstractDomain {
|
|
|
186
195
|
}
|
|
187
196
|
}
|
|
188
197
|
exports.MappedAbstractDomain = MappedAbstractDomain;
|
|
198
|
+
/**
|
|
199
|
+
* A mutable version of the {@link MappedAbstractDomain} with {@link MutableMappedAbstractDomain#set|`set`} and {@link MutableMappedAbstractDomain#remove|`remove`}.
|
|
200
|
+
*/
|
|
201
|
+
class MutableMappedAbstractDomain extends MappedAbstractDomain {
|
|
202
|
+
create(value) {
|
|
203
|
+
return new MutableMappedAbstractDomain(value);
|
|
204
|
+
}
|
|
205
|
+
set(key, value) {
|
|
206
|
+
super.set(key, value);
|
|
207
|
+
}
|
|
208
|
+
remove(key) {
|
|
209
|
+
super.remove(key);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exports.MutableMappedAbstractDomain = MutableMappedAbstractDomain;
|
|
189
213
|
//# sourceMappingURL=mapped-abstract-domain.js.map
|
|
@@ -61,7 +61,7 @@ class SetRangeDomain extends abstract_domain_1.AbstractDomain {
|
|
|
61
61
|
if (this.value === lattice_1.Bottom) {
|
|
62
62
|
return lattice_1.Bottom;
|
|
63
63
|
}
|
|
64
|
-
else if (this.value.range
|
|
64
|
+
else if (this.value.range === lattice_1.Top) {
|
|
65
65
|
return lattice_1.Top;
|
|
66
66
|
}
|
|
67
67
|
return this.value.min.union(this.value.range);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
2
|
import type { AnyAbstractDomain } from './abstract-domain';
|
|
3
|
+
import { Top } from './lattice';
|
|
4
|
+
import type { ConcreteMap } from './mapped-abstract-domain';
|
|
3
5
|
import { MappedAbstractDomain } from './mapped-abstract-domain';
|
|
4
6
|
/**
|
|
5
7
|
* A state abstract domain as mapping of AST node IDs of a program to abstract values of an abstract domain.
|
|
@@ -8,8 +10,35 @@ import { MappedAbstractDomain } from './mapped-abstract-domain';
|
|
|
8
10
|
* @see {@link NodeId} for the node IDs of the AST nodes
|
|
9
11
|
*/
|
|
10
12
|
export declare class StateAbstractDomain<Domain extends AnyAbstractDomain> extends MappedAbstractDomain<NodeId, Domain> {
|
|
13
|
+
private _isBottom;
|
|
14
|
+
constructor(value: ReadonlyMap<NodeId, Domain>, bottom?: boolean);
|
|
15
|
+
create(value: ReadonlyMap<NodeId, Domain>, bottom?: boolean): this;
|
|
16
|
+
static top<Domain extends AnyAbstractDomain>(): StateAbstractDomain<Domain>;
|
|
17
|
+
get(key: NodeId, ignoreBottom?: boolean): Domain | undefined;
|
|
18
|
+
protected set(key: NodeId, value: Domain): void;
|
|
19
|
+
bottom(): this;
|
|
20
|
+
top(): this;
|
|
21
|
+
equals(other: this): boolean;
|
|
22
|
+
leq(other: this): boolean;
|
|
23
|
+
join(other: this): this;
|
|
24
|
+
meet(other: this): this;
|
|
25
|
+
widen(other: this): this;
|
|
26
|
+
narrow(other: this): this;
|
|
27
|
+
concretize(limit: number): ReadonlySet<ConcreteMap<NodeId, Domain>> | typeof Top;
|
|
28
|
+
abstract(concrete: typeof Top | ReadonlySet<ConcreteMap<NodeId, Domain>>): this;
|
|
29
|
+
toJson(): unknown;
|
|
30
|
+
toString(): string;
|
|
31
|
+
isTop(): this is this;
|
|
32
|
+
isBottom(): this is this;
|
|
33
|
+
isValue(): this is this;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A mutable version of the {@link StateAbstractDomain} with {@link MutableStateAbstractDomain#set|`set`} and {@link MutableStateAbstractDomain#remove|`remove`}.
|
|
37
|
+
*/
|
|
38
|
+
export declare class MutableStateAbstractDomain<Domain extends AnyAbstractDomain> extends StateAbstractDomain<Domain> {
|
|
11
39
|
create(value: ReadonlyMap<NodeId, Domain>): this;
|
|
12
|
-
|
|
40
|
+
set(key: NodeId, value: Domain): void;
|
|
41
|
+
remove(key: NodeId): void;
|
|
13
42
|
}
|
|
14
43
|
/**
|
|
15
44
|
* The type of the value abstract domain of a state abstract domain (i.e. the abstract domain a state abstract domain maps to).
|