@eagleoutice/flowr 2.4.6 → 2.4.8
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 +37 -33
- package/abstract-interpretation/data-frame/absint-visitor.js +3 -2
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +40 -0
- package/abstract-interpretation/data-frame/dataframe-domain.js +62 -0
- package/abstract-interpretation/data-frame/domain.js +1 -1
- package/abstract-interpretation/domains/abstract-domain.d.ts +56 -0
- package/abstract-interpretation/domains/abstract-domain.js +19 -0
- package/abstract-interpretation/domains/bounded-set-domain.d.ts +43 -0
- package/abstract-interpretation/domains/bounded-set-domain.js +121 -0
- package/abstract-interpretation/domains/interval-domain.d.ts +61 -0
- package/abstract-interpretation/domains/interval-domain.js +208 -0
- package/abstract-interpretation/domains/lattice.d.ts +62 -0
- package/abstract-interpretation/domains/lattice.js +12 -0
- package/abstract-interpretation/domains/positive-interval-domain.d.ts +32 -0
- package/abstract-interpretation/domains/positive-interval-domain.js +91 -0
- package/abstract-interpretation/domains/product-domain.d.ts +37 -0
- package/abstract-interpretation/domains/product-domain.js +133 -0
- package/abstract-interpretation/domains/set-bounded-set-domain.d.ts +43 -0
- package/abstract-interpretation/domains/set-bounded-set-domain.js +164 -0
- package/abstract-interpretation/domains/singleton-domain.d.ts +38 -0
- package/abstract-interpretation/domains/singleton-domain.js +115 -0
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +32 -0
- package/abstract-interpretation/domains/state-abstract-domain.js +179 -0
- package/benchmark/slicer.js +1 -1
- package/benchmark/summarizer/first-phase/process.js +1 -1
- package/cli/repl/commands/repl-query.js +11 -2
- package/cli/repl/core.d.ts +2 -2
- package/cli/repl/core.js +26 -7
- package/cli/repl/server/connection.js +3 -1
- package/cli/repl/server/messages/message-slice.d.ts +3 -0
- package/cli/repl/server/messages/message-slice.js +2 -0
- package/control-flow/extract-cfg.d.ts +3 -3
- package/control-flow/extract-cfg.js +4 -4
- package/control-flow/useless-loop.js +30 -21
- package/dataflow/environments/built-in.d.ts +1 -1
- package/dataflow/environments/default-builtin-config.d.ts +9 -0
- package/dataflow/environments/default-builtin-config.js +21 -21
- package/dataflow/environments/environment.js +18 -9
- package/dataflow/environments/overwrite.js +2 -2
- package/dataflow/extractor.js +1 -1
- package/dataflow/graph/diff-dataflow-graph.js +4 -4
- package/dataflow/graph/graph.d.ts +3 -3
- package/dataflow/graph/graph.js +4 -1
- package/dataflow/graph/quads.js +4 -4
- package/dataflow/info.js +1 -1
- package/dataflow/internal/linker.d.ts +2 -0
- package/dataflow/internal/linker.js +18 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +68 -21
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +4 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -18
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +4 -5
- package/dataflow/internal/process/functions/call/common.js +4 -3
- package/documentation/doc-util/doc-query.js +6 -2
- package/documentation/doc-util/doc-types.d.ts +7 -2
- package/documentation/doc-util/doc-types.js +20 -4
- package/documentation/print-core-wiki.js +5 -1
- package/documentation/print-dataflow-graph-wiki.js +21 -12
- package/documentation/print-faq-wiki.js +5 -0
- package/documentation/print-interface-wiki.js +2 -0
- package/documentation/print-linter-wiki.js +2 -3
- package/documentation/print-query-wiki.js +22 -7
- package/linter/linter-executor.js +25 -17
- package/linter/linter-format.d.ts +10 -1
- package/linter/linter-format.js +8 -0
- package/linter/linter-rules.d.ts +1 -0
- package/linter/rules/absolute-path.js +8 -8
- package/linter/rules/dataframe-access-validation.js +1 -1
- package/linter/rules/file-path-validity.js +8 -11
- package/linter/rules/naming-convention.d.ts +5 -1
- package/linter/rules/naming-convention.js +24 -8
- package/linter/rules/seeded-randomness.js +2 -2
- package/linter/rules/unused-definition.js +1 -1
- package/package.json +17 -15
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +5 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +14 -12
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +6 -5
- package/queries/catalog/call-context-query/call-context-query-format.js +1 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
- package/queries/catalog/config-query/config-query-executor.js +7 -1
- package/queries/catalog/config-query/config-query-format.d.ts +7 -0
- package/queries/catalog/config-query/config-query-format.js +72 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +50 -75
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +50 -26
- package/queries/catalog/dependencies-query/dependencies-query-format.js +75 -20
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +2 -2
- package/queries/catalog/dependencies-query/function-info/visualize-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/visualize-functions.js +13 -0
- package/queries/catalog/happens-before-query/happens-before-query-executor.js +1 -1
- package/queries/catalog/linter-query/linter-query-format.js +4 -0
- package/queries/query-print.d.ts +2 -2
- package/queries/query-print.js +3 -2
- package/queries/query.d.ts +28 -21
- package/search/flowr-search-builder.d.ts +1 -1
- package/search/flowr-search-builder.js +1 -1
- package/search/flowr-search-filters.d.ts +20 -10
- package/search/flowr-search-filters.js +19 -3
- package/search/search-executor/search-enrichers.d.ts +1 -1
- package/search/search-executor/search-enrichers.js +3 -2
- package/search/search-executor/search-generators.js +1 -1
- package/search/search-executor/search-transformer.js +1 -1
- package/util/objects.d.ts +11 -0
- package/util/objects.js +26 -0
- package/util/version.js +1 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SetBoundedSetDomain = void 0;
|
|
4
|
+
const set_1 = require("../../util/collections/set");
|
|
5
|
+
const abstract_domain_1 = require("./abstract-domain");
|
|
6
|
+
const lattice_1 = require("./lattice");
|
|
7
|
+
/**
|
|
8
|
+
* The set bounded set abstract domain as sets capturing possible values of the concrete set bounded by a `limit` for the maximum number of inferred values.
|
|
9
|
+
* The Bottom element is defined as the{@link Bottom} and the Top element is defined as {@link Top} symbol.
|
|
10
|
+
* @template T - Type of the values in the abstract domain
|
|
11
|
+
* @template Value - Type of the constraint in the abstract domain (Top, Bottom, or an actual value)
|
|
12
|
+
*/
|
|
13
|
+
class SetBoundedSetDomain {
|
|
14
|
+
limit;
|
|
15
|
+
_value;
|
|
16
|
+
constructor(value, limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) {
|
|
17
|
+
if (value !== lattice_1.Top && value !== lattice_1.Bottom) {
|
|
18
|
+
this._value = (value.size > limit ? lattice_1.Top : new Set(value));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this._value = value;
|
|
22
|
+
}
|
|
23
|
+
this.limit = limit;
|
|
24
|
+
}
|
|
25
|
+
get value() {
|
|
26
|
+
return this._value;
|
|
27
|
+
}
|
|
28
|
+
static top(limit) {
|
|
29
|
+
return new SetBoundedSetDomain(lattice_1.Top, limit);
|
|
30
|
+
}
|
|
31
|
+
static bottom(limit) {
|
|
32
|
+
return new SetBoundedSetDomain(lattice_1.Bottom, limit);
|
|
33
|
+
}
|
|
34
|
+
static abstract(concrete, limit) {
|
|
35
|
+
if (concrete === lattice_1.Top) {
|
|
36
|
+
return SetBoundedSetDomain.top(limit);
|
|
37
|
+
}
|
|
38
|
+
else if (concrete.size === 0) {
|
|
39
|
+
return SetBoundedSetDomain.bottom(limit);
|
|
40
|
+
}
|
|
41
|
+
return new SetBoundedSetDomain(concrete.values().reduce((result, set) => result.union(set)), limit);
|
|
42
|
+
}
|
|
43
|
+
top() {
|
|
44
|
+
return SetBoundedSetDomain.top(this.limit);
|
|
45
|
+
}
|
|
46
|
+
bottom() {
|
|
47
|
+
return SetBoundedSetDomain.bottom(this.limit);
|
|
48
|
+
}
|
|
49
|
+
equals(other) {
|
|
50
|
+
return this.value === other.value || (this.isValue() && other.isValue() && (0, set_1.setEquals)(this.value, other.value));
|
|
51
|
+
}
|
|
52
|
+
leq(other) {
|
|
53
|
+
return this.value === lattice_1.Bottom || other.value === lattice_1.Top || (this.isValue() && other.isValue() && this.value.isSubsetOf(other.value));
|
|
54
|
+
}
|
|
55
|
+
join(...values) {
|
|
56
|
+
const result = new SetBoundedSetDomain(this.value, this.limit);
|
|
57
|
+
for (const other of values) {
|
|
58
|
+
if (result.value === lattice_1.Top || other.value === lattice_1.Top) {
|
|
59
|
+
result._value = lattice_1.Top;
|
|
60
|
+
}
|
|
61
|
+
else if (result.value === lattice_1.Bottom) {
|
|
62
|
+
result._value = other.value;
|
|
63
|
+
}
|
|
64
|
+
else if (other.value === lattice_1.Bottom) {
|
|
65
|
+
result._value = result.value;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const join = result.value.union(other.value);
|
|
69
|
+
result._value = join.size > this.limit ? lattice_1.Top : join;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
meet(...values) {
|
|
75
|
+
const result = new SetBoundedSetDomain(this.value, this.limit);
|
|
76
|
+
for (const other of values) {
|
|
77
|
+
if (result.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
|
|
78
|
+
result._value = lattice_1.Bottom;
|
|
79
|
+
}
|
|
80
|
+
else if (result.value === lattice_1.Top) {
|
|
81
|
+
result._value = other.value;
|
|
82
|
+
}
|
|
83
|
+
else if (other.value === lattice_1.Top) {
|
|
84
|
+
result._value = result.value;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
result._value = result.value.intersection(other.value);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Subtracts another abstract value from the current abstract value by removing all elements of the other abstract value from the current abstract value.
|
|
94
|
+
*/
|
|
95
|
+
subtract(other) {
|
|
96
|
+
if (this.value === lattice_1.Top) {
|
|
97
|
+
return this.top();
|
|
98
|
+
}
|
|
99
|
+
else if (this.value === lattice_1.Bottom) {
|
|
100
|
+
return this.bottom();
|
|
101
|
+
}
|
|
102
|
+
else if (other.value === lattice_1.Top || other.value === lattice_1.Bottom) {
|
|
103
|
+
return new SetBoundedSetDomain(this.value, this.limit);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return new SetBoundedSetDomain(this.value.difference(other.value), this.limit);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
widen(other) {
|
|
110
|
+
if (this.value === lattice_1.Bottom) {
|
|
111
|
+
return new SetBoundedSetDomain(other.value, this.limit);
|
|
112
|
+
}
|
|
113
|
+
else if (other.value === lattice_1.Bottom) {
|
|
114
|
+
return new SetBoundedSetDomain(this.value, this.limit);
|
|
115
|
+
}
|
|
116
|
+
return other.leq(this) ? new SetBoundedSetDomain(this.value, this.limit) : this.top();
|
|
117
|
+
}
|
|
118
|
+
narrow(other) {
|
|
119
|
+
if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
|
|
120
|
+
return this.bottom();
|
|
121
|
+
}
|
|
122
|
+
return this.isTop() ? other : this;
|
|
123
|
+
}
|
|
124
|
+
concretize(limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) {
|
|
125
|
+
if (this.value === lattice_1.Bottom) {
|
|
126
|
+
return new Set();
|
|
127
|
+
}
|
|
128
|
+
else if (this.value === lattice_1.Top || 2 ** (this.value.size) > limit) {
|
|
129
|
+
return lattice_1.Top;
|
|
130
|
+
}
|
|
131
|
+
const subsets = [new Set()];
|
|
132
|
+
for (const element of this.value.values()) {
|
|
133
|
+
const newSubsets = subsets.map(subset => new Set([...subset, element]));
|
|
134
|
+
for (const subset of newSubsets) {
|
|
135
|
+
subsets.push(subset);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return new Set(subsets);
|
|
139
|
+
}
|
|
140
|
+
abstract(concrete) {
|
|
141
|
+
return SetBoundedSetDomain.abstract(concrete, this.limit);
|
|
142
|
+
}
|
|
143
|
+
toString() {
|
|
144
|
+
if (this.value === lattice_1.Top) {
|
|
145
|
+
return '⊤';
|
|
146
|
+
}
|
|
147
|
+
else if (this.value === lattice_1.Bottom) {
|
|
148
|
+
return '⊥';
|
|
149
|
+
}
|
|
150
|
+
const string = this.value.values().map(abstract_domain_1.domainElementToString).toArray().join(', ');
|
|
151
|
+
return `{${string}}`;
|
|
152
|
+
}
|
|
153
|
+
isTop() {
|
|
154
|
+
return this.value === lattice_1.Top;
|
|
155
|
+
}
|
|
156
|
+
isBottom() {
|
|
157
|
+
return this.value == lattice_1.Bottom;
|
|
158
|
+
}
|
|
159
|
+
isValue() {
|
|
160
|
+
return this.value !== lattice_1.Top && this.value !== lattice_1.Bottom;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.SetBoundedSetDomain = SetBoundedSetDomain;
|
|
164
|
+
//# sourceMappingURL=set-bounded-set-domain.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type AbstractDomain } from './abstract-domain';
|
|
2
|
+
import { Bottom, Top } from './lattice';
|
|
3
|
+
/** The type of the actual values of the singleton domain as single value */
|
|
4
|
+
export type SingletonValue<T> = T;
|
|
5
|
+
/** The type of the Top element of the singleton domain as {@link Top} symbol */
|
|
6
|
+
export type SingletonTop = typeof Top;
|
|
7
|
+
/** The type of the Bottom element of the singleton domain as {@link Bottom} symbol */
|
|
8
|
+
export type SingletonBottom = typeof Bottom;
|
|
9
|
+
/** The type of the abstract values of the singleton domain that are Top, Bottom, or actual values */
|
|
10
|
+
export type SingletonLift<T> = SingletonValue<T> | SingletonTop | SingletonBottom;
|
|
11
|
+
/**
|
|
12
|
+
* The singleton abstract domain as single possible value.
|
|
13
|
+
* The Bottom element is defined as {@link Bottom} symbol and the Top element is defined as {@link Top} symbol.
|
|
14
|
+
* @template T - Type of the value in the abstract domain
|
|
15
|
+
* @template Value - Type of the constraint in the abstract domain (Top, Bottom, or an actual value)
|
|
16
|
+
*/
|
|
17
|
+
export declare class SingletonDomain<T, Value extends SingletonLift<T> = SingletonLift<T>> implements AbstractDomain<T, SingletonValue<T>, SingletonTop, SingletonBottom, Value> {
|
|
18
|
+
private _value;
|
|
19
|
+
constructor(value: Value);
|
|
20
|
+
get value(): Value;
|
|
21
|
+
static top<T>(): SingletonDomain<T, SingletonTop>;
|
|
22
|
+
static bottom<T>(): SingletonDomain<T, SingletonBottom>;
|
|
23
|
+
static abstract<T>(concrete: ReadonlySet<T> | typeof Top): SingletonDomain<T>;
|
|
24
|
+
top(): SingletonDomain<T, SingletonTop>;
|
|
25
|
+
bottom(): SingletonDomain<T, SingletonBottom>;
|
|
26
|
+
equals(other: SingletonDomain<T>): boolean;
|
|
27
|
+
leq(other: SingletonDomain<T>): boolean;
|
|
28
|
+
join(...values: SingletonDomain<T>[]): SingletonDomain<T>;
|
|
29
|
+
meet(...values: SingletonDomain<T>[]): SingletonDomain<T>;
|
|
30
|
+
widen(other: SingletonDomain<T>): SingletonDomain<T>;
|
|
31
|
+
narrow(other: SingletonDomain<T>): SingletonDomain<T>;
|
|
32
|
+
concretize(): ReadonlySet<T> | typeof Top;
|
|
33
|
+
abstract(concrete: ReadonlySet<T> | typeof Top): SingletonDomain<T>;
|
|
34
|
+
toString(): string;
|
|
35
|
+
isTop(): this is SingletonDomain<T, SingletonTop>;
|
|
36
|
+
isBottom(): this is SingletonDomain<T, SingletonBottom>;
|
|
37
|
+
isValue(): this is SingletonDomain<T, SingletonValue<T>>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SingletonDomain = void 0;
|
|
4
|
+
const abstract_domain_1 = require("./abstract-domain");
|
|
5
|
+
const lattice_1 = require("./lattice");
|
|
6
|
+
/**
|
|
7
|
+
* The singleton abstract domain as single possible value.
|
|
8
|
+
* The Bottom element is defined as {@link Bottom} symbol and the Top element is defined as {@link Top} symbol.
|
|
9
|
+
* @template T - Type of the value in the abstract domain
|
|
10
|
+
* @template Value - Type of the constraint in the abstract domain (Top, Bottom, or an actual value)
|
|
11
|
+
*/
|
|
12
|
+
class SingletonDomain {
|
|
13
|
+
_value;
|
|
14
|
+
constructor(value) {
|
|
15
|
+
this._value = value;
|
|
16
|
+
}
|
|
17
|
+
get value() {
|
|
18
|
+
return this._value;
|
|
19
|
+
}
|
|
20
|
+
static top() {
|
|
21
|
+
return new SingletonDomain(lattice_1.Top);
|
|
22
|
+
}
|
|
23
|
+
static bottom() {
|
|
24
|
+
return new SingletonDomain(lattice_1.Bottom);
|
|
25
|
+
}
|
|
26
|
+
static abstract(concrete) {
|
|
27
|
+
if (concrete === lattice_1.Top || concrete.size > 1) {
|
|
28
|
+
return SingletonDomain.top();
|
|
29
|
+
}
|
|
30
|
+
else if (concrete.size === 0) {
|
|
31
|
+
return SingletonDomain.bottom();
|
|
32
|
+
}
|
|
33
|
+
return new SingletonDomain([...concrete][0]);
|
|
34
|
+
}
|
|
35
|
+
top() {
|
|
36
|
+
return SingletonDomain.top();
|
|
37
|
+
}
|
|
38
|
+
bottom() {
|
|
39
|
+
return SingletonDomain.bottom();
|
|
40
|
+
}
|
|
41
|
+
equals(other) {
|
|
42
|
+
return this.value === other.value;
|
|
43
|
+
}
|
|
44
|
+
leq(other) {
|
|
45
|
+
return this.value === lattice_1.Bottom || other.value === lattice_1.Top || (this.isValue() && other.isValue() && this.value <= other.value);
|
|
46
|
+
}
|
|
47
|
+
join(...values) {
|
|
48
|
+
const result = new SingletonDomain(this.value);
|
|
49
|
+
for (const other of values) {
|
|
50
|
+
if (result.value === lattice_1.Bottom) {
|
|
51
|
+
result._value = other.value;
|
|
52
|
+
}
|
|
53
|
+
else if (other.value === lattice_1.Bottom) {
|
|
54
|
+
result._value = result.value;
|
|
55
|
+
}
|
|
56
|
+
else if (result.value !== other.value) {
|
|
57
|
+
result._value = lattice_1.Top;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
meet(...values) {
|
|
63
|
+
const result = new SingletonDomain(this.value);
|
|
64
|
+
for (const other of values) {
|
|
65
|
+
if (result.value === lattice_1.Top) {
|
|
66
|
+
result._value = other.value;
|
|
67
|
+
}
|
|
68
|
+
else if (other.value === lattice_1.Top) {
|
|
69
|
+
result._value = result.value;
|
|
70
|
+
}
|
|
71
|
+
else if (result.value !== other.value) {
|
|
72
|
+
result._value = lattice_1.Bottom;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
widen(other) {
|
|
78
|
+
return this.join(other); // Using join for widening as the lattice is finite
|
|
79
|
+
}
|
|
80
|
+
narrow(other) {
|
|
81
|
+
return this.meet(other); // Using meet for narrowing as the lattice is finite
|
|
82
|
+
}
|
|
83
|
+
concretize() {
|
|
84
|
+
if (this.value === lattice_1.Top) {
|
|
85
|
+
return lattice_1.Top;
|
|
86
|
+
}
|
|
87
|
+
else if (this.value === lattice_1.Bottom) {
|
|
88
|
+
return new Set();
|
|
89
|
+
}
|
|
90
|
+
return new Set([this.value]);
|
|
91
|
+
}
|
|
92
|
+
abstract(concrete) {
|
|
93
|
+
return SingletonDomain.abstract(concrete);
|
|
94
|
+
}
|
|
95
|
+
toString() {
|
|
96
|
+
if (this.value === lattice_1.Top) {
|
|
97
|
+
return '⊤';
|
|
98
|
+
}
|
|
99
|
+
else if (this.value === lattice_1.Bottom) {
|
|
100
|
+
return '⊥';
|
|
101
|
+
}
|
|
102
|
+
return (0, abstract_domain_1.domainElementToString)(this.value);
|
|
103
|
+
}
|
|
104
|
+
isTop() {
|
|
105
|
+
return this.value === lattice_1.Top;
|
|
106
|
+
}
|
|
107
|
+
isBottom() {
|
|
108
|
+
return this.value === lattice_1.Bottom;
|
|
109
|
+
}
|
|
110
|
+
isValue() {
|
|
111
|
+
return this.value !== lattice_1.Top && this.value !== lattice_1.Bottom;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.SingletonDomain = SingletonDomain;
|
|
115
|
+
//# sourceMappingURL=singleton-domain.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
|
+
import type { AbstractDomain, ConcreteDomain } from './abstract-domain';
|
|
3
|
+
import { Top } from './lattice';
|
|
4
|
+
/** The type of the abstract state for a abstract domain mapping AST node IDs to abstract values of an abstract domain */
|
|
5
|
+
export type AbstractState<Domain extends AbstractDomain<unknown, unknown, unknown, unknown>> = Map<NodeId, Domain>;
|
|
6
|
+
/** The type of the concrete state for the concrete domain of an abstract domain mapping AST node IDs to a concrete value in the concrete domain */
|
|
7
|
+
export type ConcreteState<Domain extends AbstractDomain<unknown, unknown, unknown, unknown>> = ReadonlyMap<NodeId, ConcreteDomain<Domain>>;
|
|
8
|
+
/**
|
|
9
|
+
* A state abstract domain as mapping of AST node IDs of a program to abstract values of an abstract domain.
|
|
10
|
+
* The Bottom element is defined as empty mapping and the Top element is defined as mapping every existing mapped AST node ID to Top.
|
|
11
|
+
* @template Domain - Type of the abstract domain to map the AST node IDs to
|
|
12
|
+
* @see {@link NodeId} for the node IDs of the AST nodes
|
|
13
|
+
*/
|
|
14
|
+
export declare class StateAbstractDomain<Domain extends AbstractDomain<unknown, unknown, unknown, unknown>> implements AbstractDomain<ConcreteState<Domain>, AbstractState<Domain>, AbstractState<Domain>, AbstractState<Domain>> {
|
|
15
|
+
private _value;
|
|
16
|
+
constructor(value: AbstractState<Domain>);
|
|
17
|
+
get value(): AbstractState<Domain>;
|
|
18
|
+
bottom(): StateAbstractDomain<Domain>;
|
|
19
|
+
top(): StateAbstractDomain<Domain>;
|
|
20
|
+
equals(other: StateAbstractDomain<Domain>): boolean;
|
|
21
|
+
leq(other: StateAbstractDomain<Domain>): boolean;
|
|
22
|
+
join(...values: StateAbstractDomain<Domain>[]): StateAbstractDomain<Domain>;
|
|
23
|
+
meet(...values: StateAbstractDomain<Domain>[]): StateAbstractDomain<Domain>;
|
|
24
|
+
widen(other: StateAbstractDomain<Domain>): StateAbstractDomain<Domain>;
|
|
25
|
+
narrow(other: StateAbstractDomain<Domain>): StateAbstractDomain<Domain>;
|
|
26
|
+
concretize(limit?: number): ReadonlySet<ConcreteState<Domain>> | typeof Top;
|
|
27
|
+
abstract(concrete: ReadonlySet<ConcreteState<Domain>> | typeof Top): StateAbstractDomain<Domain>;
|
|
28
|
+
toString(): string;
|
|
29
|
+
isTop(): this is StateAbstractDomain<Domain>;
|
|
30
|
+
isBottom(): this is StateAbstractDomain<Domain>;
|
|
31
|
+
isValue(): this is StateAbstractDomain<Domain>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StateAbstractDomain = void 0;
|
|
4
|
+
const abstract_domain_1 = require("./abstract-domain");
|
|
5
|
+
const lattice_1 = require("./lattice");
|
|
6
|
+
/**
|
|
7
|
+
* A state abstract domain as mapping of AST node IDs of a program to abstract values of an abstract domain.
|
|
8
|
+
* The Bottom element is defined as empty mapping and the Top element is defined as mapping every existing mapped AST node ID to Top.
|
|
9
|
+
* @template Domain - Type of the abstract domain to map the AST node IDs to
|
|
10
|
+
* @see {@link NodeId} for the node IDs of the AST nodes
|
|
11
|
+
*/
|
|
12
|
+
class StateAbstractDomain {
|
|
13
|
+
_value;
|
|
14
|
+
constructor(value) {
|
|
15
|
+
this._value = new Map(value);
|
|
16
|
+
}
|
|
17
|
+
get value() {
|
|
18
|
+
return this._value;
|
|
19
|
+
}
|
|
20
|
+
bottom() {
|
|
21
|
+
return new StateAbstractDomain(new Map());
|
|
22
|
+
}
|
|
23
|
+
top() {
|
|
24
|
+
const result = new StateAbstractDomain(this.value);
|
|
25
|
+
for (const [key, value] of result.value) {
|
|
26
|
+
result._value.set(key, value.top());
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
equals(other) {
|
|
31
|
+
if (this.value === other.value) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
else if (this.value.size !== other.value.size) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
for (const [nodeId, value] of this.value) {
|
|
38
|
+
const otherValue = other.value.get(nodeId);
|
|
39
|
+
if (otherValue === undefined || !value.equals(otherValue)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
leq(other) {
|
|
46
|
+
if (this.value === other.value) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
for (const [nodeId, value] of this.value) {
|
|
50
|
+
const otherValue = other.value.get(nodeId);
|
|
51
|
+
if (otherValue === undefined || !value.leq(otherValue)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
join(...values) {
|
|
58
|
+
const result = new StateAbstractDomain(this.value);
|
|
59
|
+
for (const other of values) {
|
|
60
|
+
for (const [nodeId, value] of other.value) {
|
|
61
|
+
const currValue = result.value.get(nodeId);
|
|
62
|
+
if (currValue === undefined) {
|
|
63
|
+
result.value.set(nodeId, value);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
result.value.set(nodeId, currValue.join(value));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
meet(...values) {
|
|
73
|
+
const result = new StateAbstractDomain(this.value);
|
|
74
|
+
for (const other of values) {
|
|
75
|
+
for (const [nodeId] of result.value) {
|
|
76
|
+
if (!other.value.has(nodeId)) {
|
|
77
|
+
result.value.delete(nodeId);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (const [nodeId, value] of other.value) {
|
|
81
|
+
const currValue = result.value.get(nodeId);
|
|
82
|
+
if (currValue !== undefined) {
|
|
83
|
+
result.value.set(nodeId, currValue.meet(value));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
widen(other) {
|
|
90
|
+
const result = new StateAbstractDomain(this.value);
|
|
91
|
+
for (const [nodeId, value] of other.value) {
|
|
92
|
+
const currValue = result.value.get(nodeId);
|
|
93
|
+
if (currValue === undefined) {
|
|
94
|
+
result.value.set(nodeId, value);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
result.value.set(nodeId, currValue.widen(value));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
narrow(other) {
|
|
103
|
+
const result = new StateAbstractDomain(this.value);
|
|
104
|
+
for (const [nodeId] of this.value) {
|
|
105
|
+
if (!other.value.has(nodeId)) {
|
|
106
|
+
result.value.delete(nodeId);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const [nodeId, value] of other.value) {
|
|
110
|
+
const currValue = result.value.get(nodeId);
|
|
111
|
+
if (currValue !== undefined) {
|
|
112
|
+
result.value.set(nodeId, currValue.narrow(value));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
concretize(limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) {
|
|
118
|
+
if (this.value.values().some(value => value.isBottom())) {
|
|
119
|
+
return new Set();
|
|
120
|
+
}
|
|
121
|
+
let states = new Set([new Map()]);
|
|
122
|
+
for (const [nodeId, value] of this.value) {
|
|
123
|
+
const concreteValues = value.concretize(limit);
|
|
124
|
+
if (concreteValues === lattice_1.Top) {
|
|
125
|
+
return lattice_1.Top;
|
|
126
|
+
}
|
|
127
|
+
const newStates = new Set();
|
|
128
|
+
for (const state of states) {
|
|
129
|
+
for (const concrete of concreteValues) {
|
|
130
|
+
if (newStates.size > limit) {
|
|
131
|
+
return lattice_1.Top;
|
|
132
|
+
}
|
|
133
|
+
const map = new Map(state);
|
|
134
|
+
map.set(nodeId, concrete);
|
|
135
|
+
newStates.add(map);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
states = newStates;
|
|
139
|
+
}
|
|
140
|
+
return states;
|
|
141
|
+
}
|
|
142
|
+
abstract(concrete) {
|
|
143
|
+
const entry = [...this.value.values()][0];
|
|
144
|
+
if (concrete === lattice_1.Top || entry === undefined) {
|
|
145
|
+
return new StateAbstractDomain(new Map());
|
|
146
|
+
}
|
|
147
|
+
const mappings = new Map();
|
|
148
|
+
for (const state of concrete) {
|
|
149
|
+
for (const [nodeId, value] of state) {
|
|
150
|
+
const mapping = mappings.get(nodeId);
|
|
151
|
+
if (mapping === undefined) {
|
|
152
|
+
mappings.set(nodeId, new Set([value]));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
mapping.add(value);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const result = new Map();
|
|
160
|
+
for (const [nodeId, values] of mappings) {
|
|
161
|
+
result.set(nodeId, entry.abstract(values));
|
|
162
|
+
}
|
|
163
|
+
return new StateAbstractDomain(result);
|
|
164
|
+
}
|
|
165
|
+
toString() {
|
|
166
|
+
return '(' + this.value.entries().toArray().map(([key, value]) => `${key} -> ${value.toString()}`).join(', ') + ')';
|
|
167
|
+
}
|
|
168
|
+
isTop() {
|
|
169
|
+
return this.value.values().every(value => value.isTop());
|
|
170
|
+
}
|
|
171
|
+
isBottom() {
|
|
172
|
+
return this.value.size === 0;
|
|
173
|
+
}
|
|
174
|
+
isValue() {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.StateAbstractDomain = StateAbstractDomain;
|
|
179
|
+
//# sourceMappingURL=state-abstract-domain.js.map
|
package/benchmark/slicer.js
CHANGED
|
@@ -108,7 +108,7 @@ class BenchmarkSlicer {
|
|
|
108
108
|
(0, assert_1.guard)(this.normalizedAst !== undefined, 'normalizedAst should be defined after initialization');
|
|
109
109
|
(0, assert_1.guard)(this.dataflow !== undefined, 'dataflow should be defined after initialization');
|
|
110
110
|
// collect dataflow graph size
|
|
111
|
-
const vertices =
|
|
111
|
+
const vertices = this.dataflow.graph.vertices(true);
|
|
112
112
|
let numberOfEdges = 0;
|
|
113
113
|
let numberOfCalls = 0;
|
|
114
114
|
let numberOfDefinitions = 0;
|
|
@@ -256,7 +256,7 @@ async function summarizeSlicerStats(stats, report = () => {
|
|
|
256
256
|
};
|
|
257
257
|
}
|
|
258
258
|
function summarizeDfShapeStats({ perNodeStats, ...stats }) {
|
|
259
|
-
const nodeStats =
|
|
259
|
+
const nodeStats = perNodeStats.values().toArray();
|
|
260
260
|
const isTop = (value) => value === 'top';
|
|
261
261
|
const isInfinite = (value) => value === 'infinite';
|
|
262
262
|
const isBottom = (value) => value === 'bottom';
|
|
@@ -37,7 +37,15 @@ async function processQueryArgs(line, parser, output, config) {
|
|
|
37
37
|
}
|
|
38
38
|
let parsedQuery = [];
|
|
39
39
|
if (query.startsWith('@')) {
|
|
40
|
-
|
|
40
|
+
const queryName = query.slice(1);
|
|
41
|
+
const queryObj = query_1.SupportedQueries[queryName];
|
|
42
|
+
if (queryObj?.fromLine) {
|
|
43
|
+
const q = queryObj.fromLine(args, config);
|
|
44
|
+
parsedQuery = q ? (Array.isArray(q) ? q : [q]) : [];
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
parsedQuery = [{ type: query.slice(1) }];
|
|
48
|
+
}
|
|
41
49
|
const validationResult = (0, query_1.QueriesSchema)().validate(parsedQuery);
|
|
42
50
|
if (validationResult.error) {
|
|
43
51
|
output.stderr(`Invalid query: ${validationResult.error.message}`);
|
|
@@ -59,6 +67,7 @@ async function processQueryArgs(line, parser, output, config) {
|
|
|
59
67
|
}
|
|
60
68
|
const processed = await getDataflow(config, parser, args.join(' '));
|
|
61
69
|
return {
|
|
70
|
+
parsedQuery,
|
|
62
71
|
query: await Promise.resolve((0, query_1.executeQueries)({ dataflow: processed.dataflow, ast: processed.normalize, config }, parsedQuery)),
|
|
63
72
|
processed
|
|
64
73
|
};
|
|
@@ -73,7 +82,7 @@ exports.queryCommand = {
|
|
|
73
82
|
const results = await processQueryArgs(remainingLine, parser, output, config);
|
|
74
83
|
const totalEnd = Date.now();
|
|
75
84
|
if (results) {
|
|
76
|
-
output.stdout((0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.ansiFormatter, totalEnd - totalStart, results.query, results.processed));
|
|
85
|
+
output.stdout((0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.ansiFormatter, totalEnd - totalStart, results.query, results.processed, results.parsedQuery));
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
88
|
};
|
package/cli/repl/core.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ import type { FlowrConfigOptions } from '../../config';
|
|
|
6
6
|
/**
|
|
7
7
|
* Used by the repl to provide automatic completions for a given (partial) input line
|
|
8
8
|
*/
|
|
9
|
-
export declare function replCompleter(line: string): [string[], string];
|
|
10
|
-
export declare function makeDefaultReplReadline(): readline.ReadLineOptions;
|
|
9
|
+
export declare function replCompleter(line: string, config: FlowrConfigOptions): [string[], string];
|
|
10
|
+
export declare function makeDefaultReplReadline(config: FlowrConfigOptions): readline.ReadLineOptions;
|
|
11
11
|
/**
|
|
12
12
|
* This function interprets the given `expr` as a REPL command (see {@link repl} for more on the semantics).
|
|
13
13
|
*
|
package/cli/repl/core.js
CHANGED
|
@@ -60,6 +60,7 @@ const repl_main_1 = require("./commands/repl-main");
|
|
|
60
60
|
const shell_1 = require("../../r-bridge/shell");
|
|
61
61
|
const log_1 = require("../../util/log");
|
|
62
62
|
const config_1 = require("../../config");
|
|
63
|
+
const query_1 = require("../../queries/query");
|
|
63
64
|
let _replCompleterKeywords = undefined;
|
|
64
65
|
function replCompleterKeywords() {
|
|
65
66
|
if (_replCompleterKeywords === undefined) {
|
|
@@ -71,7 +72,7 @@ const defaultHistoryFile = path_1.default.join(os_1.default.tmpdir(), '.flowrhis
|
|
|
71
72
|
/**
|
|
72
73
|
* Used by the repl to provide automatic completions for a given (partial) input line
|
|
73
74
|
*/
|
|
74
|
-
function replCompleter(line) {
|
|
75
|
+
function replCompleter(line, config) {
|
|
75
76
|
const splitLine = (0, args_1.splitAtEscapeSensitive)(line);
|
|
76
77
|
// did we just type a space (and are starting a new arg right now)?
|
|
77
78
|
const startingNewArg = line.endsWith(' ');
|
|
@@ -81,17 +82,19 @@ function replCompleter(line) {
|
|
|
81
82
|
if (commandNameColon) {
|
|
82
83
|
const completions = [];
|
|
83
84
|
const commandName = commandNameColon.slice(1);
|
|
84
|
-
|
|
85
|
+
const cmd = (0, repl_commands_1.getCommand)(commandName);
|
|
86
|
+
if (cmd?.script === true) {
|
|
85
87
|
// autocomplete script arguments
|
|
86
88
|
const options = scripts_info_1.scripts[commandName].options;
|
|
87
89
|
completions.push(...(0, scripts_info_1.getValidOptionsForCompletion)(options, splitLine).map(o => `${o} `));
|
|
88
90
|
}
|
|
91
|
+
else if (commandName.startsWith('query')) {
|
|
92
|
+
completions.push(...replQueryCompleter(splitLine, config));
|
|
93
|
+
}
|
|
89
94
|
else {
|
|
90
95
|
// autocomplete command arguments (specifically, autocomplete the file:// protocol)
|
|
91
96
|
completions.push(retriever_1.fileProtocol);
|
|
92
97
|
}
|
|
93
|
-
// add an empty option so that it doesn't autocomplete the only defined option immediately
|
|
94
|
-
completions.push(' ');
|
|
95
98
|
const currentArg = startingNewArg ? '' : splitLine[splitLine.length - 1];
|
|
96
99
|
return [completions.filter(a => a.startsWith(currentArg)), currentArg];
|
|
97
100
|
}
|
|
@@ -99,7 +102,23 @@ function replCompleter(line) {
|
|
|
99
102
|
// if no command is already typed, just return all commands that match
|
|
100
103
|
return [replCompleterKeywords().filter(k => k.startsWith(line)).map(k => `${k} `), line];
|
|
101
104
|
}
|
|
102
|
-
function
|
|
105
|
+
function replQueryCompleter(splitLine, config) {
|
|
106
|
+
const nonEmpty = splitLine.slice(1).map(s => s.trim()).filter(s => s.length > 0);
|
|
107
|
+
const queryShorts = Object.keys(query_1.SupportedQueries).map(q => `@${q}`).concat(['help']);
|
|
108
|
+
let candidates = [];
|
|
109
|
+
if (nonEmpty.length == 0 || (nonEmpty.length == 1 && queryShorts.some(q => q.startsWith(nonEmpty[0]) && nonEmpty[0] !== q))) {
|
|
110
|
+
candidates = candidates.concat(queryShorts.map(q => `${q} `));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const q = nonEmpty[0].slice(1);
|
|
114
|
+
const queryElement = query_1.SupportedQueries[q];
|
|
115
|
+
if (queryElement?.completer) {
|
|
116
|
+
candidates = candidates.concat(queryElement.completer(nonEmpty.slice(1), config));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return candidates;
|
|
120
|
+
}
|
|
121
|
+
function makeDefaultReplReadline(config) {
|
|
103
122
|
return {
|
|
104
123
|
input: process.stdin,
|
|
105
124
|
output: process.stdout,
|
|
@@ -107,7 +126,7 @@ function makeDefaultReplReadline() {
|
|
|
107
126
|
terminal: true,
|
|
108
127
|
history: loadReplHistory(defaultHistoryFile),
|
|
109
128
|
removeHistoryDuplicates: true,
|
|
110
|
-
completer: replCompleter
|
|
129
|
+
completer: (c) => replCompleter(c, config)
|
|
111
130
|
};
|
|
112
131
|
}
|
|
113
132
|
async function replProcessStatement(output, statement, parser, allowRSessionAccess, config) {
|
|
@@ -162,7 +181,7 @@ async function replProcessAnswer(config, output, expr, parser, allowRSessionAcce
|
|
|
162
181
|
* For the execution, this function makes use of {@link replProcessAnswer}.
|
|
163
182
|
*
|
|
164
183
|
*/
|
|
165
|
-
async function repl(config, { parser = new shell_1.RShell((0, config_1.getEngineConfig)(config, 'r-shell'), { revive: 2 /* RShellReviveOptions.Always */ }), rl = readline.createInterface(makeDefaultReplReadline()), output = repl_main_1.standardReplOutput, historyFile = defaultHistoryFile, allowRSessionAccess = false }) {
|
|
184
|
+
async function repl(config, { parser = new shell_1.RShell((0, config_1.getEngineConfig)(config, 'r-shell'), { revive: 2 /* RShellReviveOptions.Always */ }), rl = readline.createInterface(makeDefaultReplReadline(config)), output = repl_main_1.standardReplOutput, historyFile = defaultHistoryFile, allowRSessionAccess = false }) {
|
|
166
185
|
if (historyFile) {
|
|
167
186
|
rl.on('history', h => fs_1.default.writeFileSync(historyFile, h.join('\n'), { encoding: 'utf-8' }));
|
|
168
187
|
}
|