@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.
- package/README.md +22 -22
- package/abstract-interpretation/data-frame/absint-visitor.js +2 -3
- 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/package.json +1 -1
- 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/package.json
CHANGED
package/util/version.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.flowrVersion = flowrVersion;
|
|
4
4
|
const semver_1 = require("semver");
|
|
5
5
|
// this is automatically replaced with the current version by release-it
|
|
6
|
-
const version = '2.4.
|
|
6
|
+
const version = '2.4.7';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|