@eagleoutice/flowr 2.4.5 → 2.4.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.
Files changed (25) hide show
  1. package/README.md +22 -22
  2. package/abstract-interpretation/data-frame/absint-visitor.js +2 -3
  3. package/abstract-interpretation/data-frame/dataframe-domain.d.ts +40 -0
  4. package/abstract-interpretation/data-frame/dataframe-domain.js +62 -0
  5. package/abstract-interpretation/data-frame/domain.js +1 -1
  6. package/abstract-interpretation/domains/abstract-domain.d.ts +56 -0
  7. package/abstract-interpretation/domains/abstract-domain.js +19 -0
  8. package/abstract-interpretation/domains/bounded-set-domain.d.ts +43 -0
  9. package/abstract-interpretation/domains/bounded-set-domain.js +121 -0
  10. package/abstract-interpretation/domains/interval-domain.d.ts +61 -0
  11. package/abstract-interpretation/domains/interval-domain.js +208 -0
  12. package/abstract-interpretation/domains/lattice.d.ts +62 -0
  13. package/abstract-interpretation/domains/lattice.js +12 -0
  14. package/abstract-interpretation/domains/positive-interval-domain.d.ts +32 -0
  15. package/abstract-interpretation/domains/positive-interval-domain.js +91 -0
  16. package/abstract-interpretation/domains/product-domain.d.ts +37 -0
  17. package/abstract-interpretation/domains/product-domain.js +133 -0
  18. package/abstract-interpretation/domains/set-bounded-set-domain.d.ts +43 -0
  19. package/abstract-interpretation/domains/set-bounded-set-domain.js +164 -0
  20. package/abstract-interpretation/domains/singleton-domain.d.ts +38 -0
  21. package/abstract-interpretation/domains/singleton-domain.js +115 -0
  22. package/abstract-interpretation/domains/state-abstract-domain.d.ts +32 -0
  23. package/abstract-interpretation/domains/state-abstract-domain.js +179 -0
  24. package/package.json +1 -1
  25. package/util/version.js +1 -1
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IntervalDomain = void 0;
4
+ const abstract_domain_1 = require("./abstract-domain");
5
+ const lattice_1 = require("./lattice");
6
+ /**
7
+ * The interval abstract domain as intervals with possibly infinite bounds representing possible numeric values.
8
+ * The Bottom element is defined as {@link Bottom} symbol and the Top element is defined as the interval [-∞, +∞].
9
+ * @template Value - Type of the constraint in the abstract domain (Top, Bottom, or an actual value)
10
+ */
11
+ class IntervalDomain {
12
+ _value;
13
+ constructor(value) {
14
+ if (Array.isArray(value)) {
15
+ if (value.some(isNaN) || value[0] > value[1] || value[0] === +Infinity || value[1] === -Infinity) {
16
+ this._value = lattice_1.Bottom;
17
+ }
18
+ else {
19
+ this._value = [value[0], value[1]];
20
+ }
21
+ }
22
+ else {
23
+ this._value = value;
24
+ }
25
+ }
26
+ get value() {
27
+ return this._value;
28
+ }
29
+ static top() {
30
+ return new IntervalDomain([-Infinity, +Infinity]);
31
+ }
32
+ static bottom() {
33
+ return new IntervalDomain(lattice_1.Bottom);
34
+ }
35
+ static abstract(concrete) {
36
+ if (concrete === lattice_1.Top) {
37
+ return IntervalDomain.top();
38
+ }
39
+ else if (concrete.size === 0 || concrete.values().some(isNaN)) {
40
+ return IntervalDomain.bottom();
41
+ }
42
+ return new IntervalDomain([Math.min(...concrete), Math.max(...concrete)]);
43
+ }
44
+ top() {
45
+ return IntervalDomain.top();
46
+ }
47
+ bottom() {
48
+ return IntervalDomain.bottom();
49
+ }
50
+ equals(other) {
51
+ return this.value === other.value || (this.isValue() && other.isValue() && this.value[0] === other.value[0] && this.value[1] === other.value[1]);
52
+ }
53
+ leq(other) {
54
+ return this.value === lattice_1.Bottom || (other.isValue() && other.value[0] <= this.value[0] && this.value[1] <= other.value[1]);
55
+ }
56
+ join(...values) {
57
+ const result = new IntervalDomain(this.value);
58
+ for (const other of values) {
59
+ if (result.value === lattice_1.Bottom) {
60
+ result._value = other.value;
61
+ }
62
+ else if (other.value === lattice_1.Bottom) {
63
+ result._value = result.value;
64
+ }
65
+ else {
66
+ result._value = [Math.min(result.value[0], other.value[0]), Math.max(result.value[1], other.value[1])];
67
+ }
68
+ }
69
+ return result;
70
+ }
71
+ meet(...values) {
72
+ const result = new IntervalDomain(this.value);
73
+ for (const other of values) {
74
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
75
+ result._value = lattice_1.Bottom;
76
+ }
77
+ else if (Math.max(this.value[0], other.value[0]) > Math.min(this.value[1], other.value[1])) {
78
+ result._value = lattice_1.Bottom;
79
+ }
80
+ else {
81
+ result._value = [Math.max(this.value[0], other.value[0]), Math.min(this.value[1], other.value[1])];
82
+ }
83
+ }
84
+ return result;
85
+ }
86
+ widen(other) {
87
+ if (this.value === lattice_1.Bottom) {
88
+ return new IntervalDomain(other.value);
89
+ }
90
+ else if (other.value === lattice_1.Bottom) {
91
+ return new IntervalDomain(this.value);
92
+ }
93
+ else {
94
+ return new IntervalDomain([
95
+ this.value[0] <= other.value[0] ? this.value[0] : -Infinity,
96
+ this.value[1] >= other.value[1] ? this.value[1] : +Infinity
97
+ ]);
98
+ }
99
+ }
100
+ narrow(other) {
101
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
102
+ return this.bottom();
103
+ }
104
+ return new IntervalDomain([
105
+ this.value[0] === -Infinity ? other.value[0] : this.value[0],
106
+ this.value[1] === +Infinity ? other.value[1] : this.value[1]
107
+ ]);
108
+ }
109
+ concretize(limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) {
110
+ if (this.value === lattice_1.Bottom) {
111
+ return new Set();
112
+ }
113
+ else if (!isFinite(this.value[0]) || !isFinite(this.value[1]) || this.value[1] - this.value[0] + 1 > limit) {
114
+ return lattice_1.Top;
115
+ }
116
+ const set = new Set();
117
+ for (let x = this.value[0]; x <= this.value[1]; x++) {
118
+ set.add(x);
119
+ }
120
+ return set;
121
+ }
122
+ abstract(concrete) {
123
+ return IntervalDomain.abstract(concrete);
124
+ }
125
+ /**
126
+ * Adds another abstract value to the current abstract value by adding the two lower and upper bounds, respectively.
127
+ */
128
+ add(other) {
129
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
130
+ return this.bottom();
131
+ }
132
+ else {
133
+ return new IntervalDomain([this.value[0] + other.value[0], this.value[1] + other.value[1]]);
134
+ }
135
+ }
136
+ /**
137
+ * Subtracts another abstract value from the current abstract value by subtracting the two lower and upper bounds from each other, respectively.
138
+ */
139
+ subtract(other) {
140
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
141
+ return this.bottom();
142
+ }
143
+ else {
144
+ return new IntervalDomain([this.value[0] - other.value[0], this.value[1] - other.value[1]]);
145
+ }
146
+ }
147
+ /**
148
+ * Creates the minimum between the current abstract value and another abstract value by creating the minimum of the two lower and upper bounds, respectively.
149
+ */
150
+ min(other) {
151
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
152
+ return this.bottom();
153
+ }
154
+ else {
155
+ return new IntervalDomain([Math.min(this.value[0], other.value[0]), Math.min(this.value[1], other.value[1])]);
156
+ }
157
+ }
158
+ /**
159
+ * Creates the maximum between the current abstract value and another abstract value by creating the maximum of the two lower and upper bounds, respectively.
160
+ */
161
+ max(other) {
162
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
163
+ return this.bottom();
164
+ }
165
+ else {
166
+ return new IntervalDomain([Math.max(this.value[0], other.value[0]), Math.max(this.value[1], other.value[1])]);
167
+ }
168
+ }
169
+ /**
170
+ * Extends the lower bound of the current abstract value down to -∞.
171
+ */
172
+ extendDown() {
173
+ if (this.value === lattice_1.Bottom) {
174
+ return this.bottom();
175
+ }
176
+ else {
177
+ return new IntervalDomain([-Infinity, this.value[1]]);
178
+ }
179
+ }
180
+ /**
181
+ * Extends the upper bound of the current abstract value up to +∞.
182
+ */
183
+ extendUp() {
184
+ if (this.value === lattice_1.Bottom) {
185
+ return this.bottom();
186
+ }
187
+ else {
188
+ return new IntervalDomain([this.value[0], +Infinity]);
189
+ }
190
+ }
191
+ toString() {
192
+ if (this.value === lattice_1.Bottom) {
193
+ return '⊥';
194
+ }
195
+ return `[${isFinite(this.value[0]) ? this.value[0] : '-∞'}, ${isFinite(this.value[1]) ? this.value[1] : '+∞'}]`;
196
+ }
197
+ isTop() {
198
+ return this.value !== lattice_1.Bottom && this.value[0] === -Infinity && this.value[1] === +Infinity;
199
+ }
200
+ isBottom() {
201
+ return this.value === lattice_1.Bottom;
202
+ }
203
+ isValue() {
204
+ return this.value !== lattice_1.Bottom;
205
+ }
206
+ }
207
+ exports.IntervalDomain = IntervalDomain;
208
+ //# sourceMappingURL=interval-domain.js.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The Top symbol to represent the Top element of complete lattices (e.g. of abstract domains).
3
+ */
4
+ export declare const Top: unique symbol;
5
+ /**
6
+ * The Bottom symbol to represent the Bottom element of complete lattices (e.g. of abstract domains).
7
+ */
8
+ export declare const Bottom: unique symbol;
9
+ /**
10
+ * A complete lattice with a partially ordered set, join operator (LUB), meet operator (GLB), top element, and bottom element (e.g. for abstract domains).
11
+ * @template Value - Type of a lattice element representing a value (may exclude `Top` and `Bot`)
12
+ * @template Top - Type of the Top element (greatest element) of the complete lattice (defaults to {@link Top})
13
+ * @template Bot - Type of the Bottom element (least element) of the complete lattice (defaults to {@link Bottom})
14
+ * @template Lift - Type of the lattice elements (defaults to `Value` or `Top` or `Bot`)
15
+ */
16
+ export interface Lattice<Value, Top = typeof Top, Bot = typeof Bottom, Lift extends Value | Top | Bot = Value | Top | Bot> {
17
+ /**
18
+ * The current abstract value of the lattice.
19
+ */
20
+ get value(): Lift;
21
+ /**
22
+ * Gets the Top element (greatest element) of the complete lattice (should additionally be provided as static function).
23
+ */
24
+ top(): Lattice<Value, Top, Bot, Top>;
25
+ /**
26
+ * Gets the Bottom element (least element) of the complete lattice (should additionally be provided as static function).
27
+ */
28
+ bottom(): Lattice<Value, Top, Bot, Bot>;
29
+ /**
30
+ * Checks whether the current abstract value equals to another abstract value.
31
+ */
32
+ equals(other: Lattice<Value, Top, Bot>): boolean;
33
+ /**
34
+ * Checks whether the current abstract value is less than or equal to another abstract value with respect to the partial order of the lattice.
35
+ */
36
+ leq(other: Lattice<Value, Top, Bot>): boolean;
37
+ /**
38
+ * Joins the current abstract value with other abstract values by creating the least upper bound (LUB) in the lattice.
39
+ */
40
+ join(...values: Lattice<Value, Top, Bot>[]): Lattice<Value, Top, Bot>;
41
+ /**
42
+ * Meets the current abstract value with other abstract values by creating the greatest lower bound (GLB) in the lattice.
43
+ */
44
+ meet(...values: Lattice<Value, Top, Bot>[]): Lattice<Value, Top, Bot>;
45
+ /**
46
+ * Converts the lattice into a human-readable string.
47
+ */
48
+ toString(): string;
49
+ /**
50
+ * Checks whether the current abstract value is the Top element of the complete lattice.
51
+ */
52
+ isTop(): this is Lattice<Value, Top, Bot, Top>;
53
+ /**
54
+ * Checks whether the current abstract value is the Bottom element of the complete lattice.
55
+ */
56
+ isBottom(): this is Lattice<Value, Top, Bot, Bot>;
57
+ /**
58
+ * Checks whether the current abstract value is an actual value of the complete lattice
59
+ * (this may include the Top or Bottom element if they are also values and no separate symbols, for example).
60
+ */
61
+ isValue(): this is Lattice<Value, Top, Bot, Value>;
62
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Bottom = exports.Top = void 0;
4
+ /**
5
+ * The Top symbol to represent the Top element of complete lattices (e.g. of abstract domains).
6
+ */
7
+ exports.Top = Symbol('top');
8
+ /**
9
+ * The Bottom symbol to represent the Bottom element of complete lattices (e.g. of abstract domains).
10
+ */
11
+ exports.Bottom = Symbol('bottom');
12
+ //# sourceMappingURL=lattice.js.map
@@ -0,0 +1,32 @@
1
+ import { IntervalDomain } from './interval-domain';
2
+ import { Bottom, Top } from './lattice';
3
+ /** The type of the actual values of the positive interval domain as tuple of the lower and upper bound */
4
+ export type PosIntervalValue = readonly [number, number];
5
+ /** The type of the Top element of the positive interval domain as interval [0, +∞] from 0 to +∞ */
6
+ export type PosIntervalTop = readonly [0, typeof Infinity];
7
+ /** The type of the Bottom element of the positive interval domain as {@link Bottom} symbol */
8
+ export type PosIntervalBottom = typeof Bottom;
9
+ /** The type of the abstract values of the positive interval domain that are Top, Bottom, or actual values */
10
+ export type PosIntervalLift = PosIntervalValue | PosIntervalTop | PosIntervalBottom;
11
+ /**
12
+ * The positive interval abstract domain as positive intervals with possibly zero lower bounds and infinite upper bounds representing possible numeric values.
13
+ * The Bottom element is defined as {@link Bottom} symbol and the Top element is defined as the interval [0, +∞].
14
+ * @template Value - Type of the constraint in the abstract domain (Top, Bottom, or an actual value)
15
+ */
16
+ export declare class PosIntervalDomain<Value extends PosIntervalLift = PosIntervalLift> extends IntervalDomain<Value> {
17
+ constructor(value: Value);
18
+ static top(): PosIntervalDomain<PosIntervalTop>;
19
+ static bottom(): PosIntervalDomain<PosIntervalBottom>;
20
+ static abstract(concrete: ReadonlySet<number> | typeof Top): PosIntervalDomain;
21
+ top(): PosIntervalDomain<PosIntervalTop>;
22
+ bottom(): PosIntervalDomain<PosIntervalBottom>;
23
+ widen(other: PosIntervalDomain): PosIntervalDomain;
24
+ narrow(other: PosIntervalDomain): PosIntervalDomain;
25
+ abstract(concrete: ReadonlySet<number> | typeof Top): PosIntervalDomain;
26
+ subtract(other: PosIntervalDomain): PosIntervalDomain;
27
+ /**
28
+ * Extends the lower bound of the current abstract value down to 0.
29
+ */
30
+ extendDown(): PosIntervalDomain;
31
+ isTop(): this is PosIntervalDomain<PosIntervalTop>;
32
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PosIntervalDomain = void 0;
4
+ const interval_domain_1 = require("./interval-domain");
5
+ const lattice_1 = require("./lattice");
6
+ /**
7
+ * The positive interval abstract domain as positive intervals with possibly zero lower bounds and infinite upper bounds representing possible numeric values.
8
+ * The Bottom element is defined as {@link Bottom} symbol and the Top element is defined as the interval [0, +∞].
9
+ * @template Value - Type of the constraint in the abstract domain (Top, Bottom, or an actual value)
10
+ */
11
+ class PosIntervalDomain extends interval_domain_1.IntervalDomain {
12
+ constructor(value) {
13
+ if (Array.isArray(value) && value[0] < 0) {
14
+ super(lattice_1.Bottom);
15
+ }
16
+ else {
17
+ super(value);
18
+ }
19
+ }
20
+ static top() {
21
+ return new PosIntervalDomain([0, +Infinity]);
22
+ }
23
+ static bottom() {
24
+ return new PosIntervalDomain(lattice_1.Bottom);
25
+ }
26
+ static abstract(concrete) {
27
+ if (concrete === lattice_1.Top) {
28
+ return PosIntervalDomain.top();
29
+ }
30
+ else if (concrete.size === 0 || concrete.values().some(value => isNaN(value) || value < 0)) {
31
+ return PosIntervalDomain.bottom();
32
+ }
33
+ return new PosIntervalDomain([Math.min(...concrete), Math.max(...concrete)]);
34
+ }
35
+ top() {
36
+ return PosIntervalDomain.top();
37
+ }
38
+ bottom() {
39
+ return PosIntervalDomain.bottom();
40
+ }
41
+ widen(other) {
42
+ if (this.value === lattice_1.Bottom) {
43
+ return new PosIntervalDomain(other.value);
44
+ }
45
+ else if (other.value === lattice_1.Bottom) {
46
+ return new PosIntervalDomain(this.value);
47
+ }
48
+ else {
49
+ return new PosIntervalDomain([
50
+ this.value[0] <= other.value[0] ? this.value[0] : 0,
51
+ this.value[1] >= other.value[1] ? this.value[1] : +Infinity
52
+ ]);
53
+ }
54
+ }
55
+ narrow(other) {
56
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
57
+ return PosIntervalDomain.bottom();
58
+ }
59
+ return new PosIntervalDomain([
60
+ this.value[0] === 0 ? other.value[0] : this.value[0],
61
+ this.value[1] === +Infinity ? other.value[1] : this.value[1]
62
+ ]);
63
+ }
64
+ abstract(concrete) {
65
+ return PosIntervalDomain.abstract(concrete);
66
+ }
67
+ subtract(other) {
68
+ if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) {
69
+ return this.bottom();
70
+ }
71
+ else {
72
+ return new PosIntervalDomain([Math.max(this.value[0] - other.value[0], 0), Math.max(this.value[1] - other.value[1], 0)]);
73
+ }
74
+ }
75
+ /**
76
+ * Extends the lower bound of the current abstract value down to 0.
77
+ */
78
+ extendDown() {
79
+ if (this.value === lattice_1.Bottom) {
80
+ return this.bottom();
81
+ }
82
+ else {
83
+ return new PosIntervalDomain([0, this.value[1]]);
84
+ }
85
+ }
86
+ isTop() {
87
+ return this.value !== lattice_1.Bottom && this.value[0] === 0 && this.value[1] !== +Infinity;
88
+ }
89
+ }
90
+ exports.PosIntervalDomain = PosIntervalDomain;
91
+ //# sourceMappingURL=positive-interval-domain.js.map
@@ -0,0 +1,37 @@
1
+ import { type AbstractDomain } from './abstract-domain';
2
+ import { Top } from './lattice';
3
+ /** The type of an abstract product of a product domain mapping named properties of the product to abstract domains */
4
+ export type AbstractProduct = Record<string, AbstractDomain<unknown, unknown, unknown, unknown>>;
5
+ /** The type of the concrete product of an abstract product mapping each property to a concrete value in the respective concrete domain */
6
+ export type ConcreteProduct<Product extends AbstractProduct> = {
7
+ [Key in keyof Product]: Product[Key] extends AbstractDomain<infer Concrete, unknown, unknown, unknown> ? Concrete : never;
8
+ };
9
+ /**
10
+ * A product abstract domain as named Cartesian product of sub abstract domains.
11
+ * The sub abstract domains are represented a record mapping property names to abstract domains.
12
+ * The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as mapping every sub abstract domain to Top.
13
+ * @template Product - Type of the abstract product of the product domain mapping property names to abstract domains
14
+ */
15
+ export declare abstract class ProductDomain<Product extends AbstractProduct> implements AbstractDomain<ConcreteProduct<Product>, Product, Product, Product> {
16
+ private _value;
17
+ constructor(value: Product);
18
+ /**
19
+ * Creates an abstract value of the product domain for a given abstract value.
20
+ */
21
+ abstract create(value: Product): ProductDomain<Product>;
22
+ get value(): Product;
23
+ bottom(): ProductDomain<Product>;
24
+ top(): ProductDomain<Product>;
25
+ equals(other: ProductDomain<Product>): boolean;
26
+ leq(other: ProductDomain<Product>): boolean;
27
+ join(...values: ProductDomain<Product>[]): ProductDomain<Product>;
28
+ meet(...values: ProductDomain<Product>[]): ProductDomain<Product>;
29
+ widen(other: ProductDomain<Product>): ProductDomain<Product>;
30
+ narrow(other: ProductDomain<Product>): ProductDomain<Product>;
31
+ concretize(limit?: number): ReadonlySet<ConcreteProduct<Product>> | typeof Top;
32
+ abstract(concrete: ReadonlySet<ConcreteProduct<Product>> | typeof Top): ProductDomain<Product>;
33
+ toString(): string;
34
+ isTop(): this is ProductDomain<Product>;
35
+ isBottom(): this is ProductDomain<Product>;
36
+ isValue(): this is ProductDomain<Product>;
37
+ }
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProductDomain = void 0;
4
+ const abstract_domain_1 = require("./abstract-domain");
5
+ const lattice_1 = require("./lattice");
6
+ /**
7
+ * A product abstract domain as named Cartesian product of sub abstract domains.
8
+ * The sub abstract domains are represented a record mapping property names to abstract domains.
9
+ * The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as mapping every sub abstract domain to Top.
10
+ * @template Product - Type of the abstract product of the product domain mapping property names to abstract domains
11
+ */
12
+ class ProductDomain {
13
+ _value;
14
+ constructor(value) {
15
+ this._value = value;
16
+ }
17
+ get value() {
18
+ return this._value;
19
+ }
20
+ bottom() {
21
+ const result = this.create(this.value);
22
+ for (const key in result.value) {
23
+ result._value[key] = result.value[key].bottom();
24
+ }
25
+ return result;
26
+ }
27
+ top() {
28
+ const result = this.create(this.value);
29
+ for (const key in result.value) {
30
+ result._value[key] = result.value[key].top();
31
+ }
32
+ return result;
33
+ }
34
+ equals(other) {
35
+ if (this.value === other.value) {
36
+ return true;
37
+ }
38
+ for (const key in this.value) {
39
+ if (!this.value[key].equals(other.value[key])) {
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 key in this.value) {
50
+ if (!this.value[key].leq(other.value[key])) {
51
+ return false;
52
+ }
53
+ }
54
+ return true;
55
+ }
56
+ join(...values) {
57
+ const result = this.create(this.value);
58
+ for (const value of values) {
59
+ for (const key in result.value) {
60
+ result._value[key] = result.value[key].join(value.value[key]);
61
+ }
62
+ }
63
+ return result;
64
+ }
65
+ meet(...values) {
66
+ const result = this.create(this.value);
67
+ for (const value of values) {
68
+ for (const key in result.value) {
69
+ result._value[key] = result.value[key].meet(value.value[key]);
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ widen(other) {
75
+ const result = this.create(this.value);
76
+ for (const key in result.value) {
77
+ result._value[key] = result.value[key].widen(other.value[key]);
78
+ }
79
+ return result;
80
+ }
81
+ narrow(other) {
82
+ const result = this.create(this.value);
83
+ for (const key in result.value) {
84
+ result._value[key] = result.value[key].narrow(other.value[key]);
85
+ }
86
+ return result;
87
+ }
88
+ concretize(limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) {
89
+ let result = new Set([{}]);
90
+ for (const key in this.value) {
91
+ const concrete = this.value[key].concretize(limit);
92
+ if (concrete === lattice_1.Top) {
93
+ return lattice_1.Top;
94
+ }
95
+ const newResult = new Set();
96
+ for (const value of concrete) {
97
+ for (const entry of result) {
98
+ if (newResult.size >= limit) {
99
+ return lattice_1.Top;
100
+ }
101
+ newResult.add({ ...entry, [key]: value });
102
+ }
103
+ }
104
+ result = newResult;
105
+ }
106
+ return result;
107
+ }
108
+ abstract(concrete) {
109
+ if (concrete === lattice_1.Top) {
110
+ return this.top();
111
+ }
112
+ const result = this.create(this.value);
113
+ for (const key in result.value) {
114
+ const concreteValues = new Set(concrete.values().map(value => value[key]));
115
+ result._value[key] = result.value[key].abstract(concreteValues);
116
+ }
117
+ return result;
118
+ }
119
+ toString() {
120
+ return '(' + Object.entries(this.value).map(([key, value]) => `${key}: ${value.toString()}`).join(', ') + ')';
121
+ }
122
+ isTop() {
123
+ return Object.values(this.value).every(value => value.isTop());
124
+ }
125
+ isBottom() {
126
+ return Object.values(this.value).every(value => value.isBottom());
127
+ }
128
+ isValue() {
129
+ return true;
130
+ }
131
+ }
132
+ exports.ProductDomain = ProductDomain;
133
+ //# sourceMappingURL=product-domain.js.map
@@ -0,0 +1,43 @@
1
+ import { type AbstractDomain } from './abstract-domain';
2
+ import { Bottom, Top } from './lattice';
3
+ /** The type of the actual values of the set bounded set domain as set */
4
+ export type SetBoundedSetValue<T> = ReadonlySet<T>;
5
+ /** The type of the Top element of the set bounded set domain as {@link Top} symbol */
6
+ export type SetBoundedSetTop = typeof Top;
7
+ /** The type of the Bottom element of the set bounded set domain as {@link Bottom} */
8
+ export type SetBoundedSetBottom = typeof Bottom;
9
+ /** The type of the abstract values of the set bounded set domain that are Top, Bottom, or actual values */
10
+ export type SetBoundedSetLift<T> = SetBoundedSetValue<T> | SetBoundedSetTop | SetBoundedSetBottom;
11
+ /**
12
+ * 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.
13
+ * The Bottom element is defined as the{@link Bottom} and the Top element is defined as {@link Top} symbol.
14
+ * @template T - Type of the values 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 SetBoundedSetDomain<T, Value extends SetBoundedSetLift<T> = SetBoundedSetLift<T>> implements AbstractDomain<ReadonlySet<T>, SetBoundedSetValue<T>, SetBoundedSetTop, SetBoundedSetBottom, Value> {
18
+ private readonly limit;
19
+ private _value;
20
+ constructor(value: Value, limit?: number);
21
+ get value(): Value;
22
+ static top<T>(limit?: number): SetBoundedSetDomain<T, SetBoundedSetTop>;
23
+ static bottom<T>(limit?: number): SetBoundedSetDomain<T, SetBoundedSetBottom>;
24
+ static abstract<T>(concrete: ReadonlySet<ReadonlySet<T>> | typeof Top, limit?: number): SetBoundedSetDomain<T>;
25
+ top(): SetBoundedSetDomain<T, SetBoundedSetTop>;
26
+ bottom(): SetBoundedSetDomain<T, SetBoundedSetBottom>;
27
+ equals(other: SetBoundedSetDomain<T>): boolean;
28
+ leq(other: SetBoundedSetDomain<T>): boolean;
29
+ join(...values: SetBoundedSetDomain<T>[]): SetBoundedSetDomain<T>;
30
+ meet(...values: SetBoundedSetDomain<T>[]): SetBoundedSetDomain<T>;
31
+ /**
32
+ * Subtracts another abstract value from the current abstract value by removing all elements of the other abstract value from the current abstract value.
33
+ */
34
+ subtract(other: SetBoundedSetDomain<T>): SetBoundedSetDomain<T>;
35
+ widen(other: SetBoundedSetDomain<T>): SetBoundedSetDomain<T>;
36
+ narrow(other: SetBoundedSetDomain<T>): SetBoundedSetDomain<T>;
37
+ concretize(limit?: number): ReadonlySet<ReadonlySet<T>> | typeof Top;
38
+ abstract(concrete: ReadonlySet<ReadonlySet<T>> | typeof Top): SetBoundedSetDomain<T>;
39
+ toString(): string;
40
+ isTop(): this is SetBoundedSetDomain<T, SetBoundedSetTop>;
41
+ isBottom(): this is SetBoundedSetDomain<T, SetBoundedSetBottom>;
42
+ isValue(): this is SetBoundedSetDomain<T, SetBoundedSetValue<T>>;
43
+ }