@eagleoutice/flowr 2.10.4 → 2.10.5
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 -20
- package/abstract-interpretation/absint-visitor.d.ts +17 -21
- package/abstract-interpretation/absint-visitor.js +47 -48
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -3
- package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -1
- package/abstract-interpretation/data-frame/shape-inference.js +5 -4
- package/abstract-interpretation/domains/abstract-domain.d.ts +17 -16
- package/abstract-interpretation/domains/abstract-domain.js +25 -27
- package/abstract-interpretation/domains/bounded-set-domain.js +1 -1
- package/abstract-interpretation/domains/multi-value-state-domain.d.ts +32 -0
- package/abstract-interpretation/domains/multi-value-state-domain.js +60 -0
- package/abstract-interpretation/domains/partial-product-domain.d.ts +43 -0
- package/abstract-interpretation/domains/partial-product-domain.js +163 -0
- package/abstract-interpretation/domains/product-domain.d.ts +2 -29
- package/abstract-interpretation/domains/product-domain.js +6 -123
- package/abstract-interpretation/domains/set-range-domain.js +3 -3
- package/abstract-interpretation/domains/set-upper-bound-domain.js +1 -1
- package/abstract-interpretation/domains/singleton-domain.js +1 -1
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +13 -28
- package/abstract-interpretation/domains/state-abstract-domain.js +16 -38
- package/abstract-interpretation/domains/state-domain-like.d.ts +36 -0
- package/abstract-interpretation/domains/state-domain-like.js +3 -0
- package/cli/flowr.js +11 -1
- package/config.d.ts +7 -0
- package/config.js +22 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +4 -0
- package/control-flow/semantic-cfg-guided-visitor.js +20 -32
- package/dataflow/environments/default-builtin-config.d.ts +10 -0
- package/dataflow/environments/default-builtin-config.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +2 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +38 -21
- package/documentation/doc-readme.js +13 -2
- package/documentation/wiki-absint.d.ts +1 -2
- package/documentation/wiki-absint.js +34 -10
- package/documentation/wiki-analyzer.js +3 -4
- package/documentation/wiki-interface.js +21 -16
- package/linter/linter-rules.d.ts +2 -2
- package/linter/rules/problematic-inputs.d.ts +4 -3
- package/linter/rules/problematic-inputs.js +3 -4
- package/package.json +3 -3
- package/project/flowr-analyzer-builder.d.ts +6 -3
- package/project/flowr-analyzer-builder.js +12 -5
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.d.ts +4 -3
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +17 -4
- package/project/plugins/flowr-analyzer-plugin.d.ts +1 -1
- package/project/plugins/flowr-analyzer-plugin.js +1 -1
- package/queries/catalog/input-sources-query/input-source-functions.d.ts +6 -0
- package/queries/catalog/input-sources-query/input-source-functions.js +50 -0
- package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +1 -1
- package/queries/catalog/input-sources-query/input-sources-query-executor.js +19 -53
- package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +2 -1
- package/queries/catalog/input-sources-query/input-sources-query-format.js +26 -11
- package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +18 -41
- package/queries/catalog/input-sources-query/simple-input-classifier.js +165 -103
- package/r-bridge/lang-4.x/ast/model/model.d.ts +4 -4
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +3 -3
- package/util/record.d.ts +18 -3
- package/util/record.js +22 -1
- package/util/version.js +1 -1
- package/project/plugins/flowr-analyzer-plugin-defaults.d.ts +0 -5
- package/project/plugins/flowr-analyzer-plugin-defaults.js +0 -37
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AbstractDomain = exports.DEFAULT_INFERENCE_LIMIT = void 0;
|
|
4
|
-
exports.domainElementToString = domainElementToString;
|
|
5
|
-
exports.isAbstractDomain = isAbstractDomain;
|
|
6
4
|
const assert_1 = require("../../util/assert");
|
|
7
5
|
const lattice_1 = require("./lattice");
|
|
8
6
|
/**
|
|
@@ -62,31 +60,31 @@ class AbstractDomain {
|
|
|
62
60
|
(0, assert_1.guard)(values.length > 0 || defaultValue !== undefined, 'Abstract values to meet cannot be empty');
|
|
63
61
|
return values[0]?.meetAll(values.slice(1)) ?? defaultValue;
|
|
64
62
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return
|
|
63
|
+
/**
|
|
64
|
+
* Converts an element of an abstract domain into a string.
|
|
65
|
+
*/
|
|
66
|
+
static toString(value) {
|
|
67
|
+
if (value instanceof Map) {
|
|
68
|
+
return `{${value.entries().map(([key, value]) => `${AbstractDomain.toString(key)} -> ${AbstractDomain.toString(value)}`).toArray().join(', ')}}`;
|
|
69
|
+
}
|
|
70
|
+
else if (value instanceof Set) {
|
|
71
|
+
return `{${value.values().map(AbstractDomain.toString).toArray().join(', ')}}`;
|
|
72
|
+
}
|
|
73
|
+
else if (typeof value === 'object' && value !== null && value.toString !== Object.prototype.toString) {
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
75
|
+
return value.toString();
|
|
76
|
+
}
|
|
77
|
+
else if (Array.isArray(value)) {
|
|
78
|
+
return `[${value.map(AbstractDomain.toString).join(', ')}]`;
|
|
79
|
+
}
|
|
80
|
+
else if (value === lattice_1.Top) {
|
|
81
|
+
return lattice_1.TopSymbol;
|
|
82
|
+
}
|
|
83
|
+
else if (value === lattice_1.Bottom) {
|
|
84
|
+
return lattice_1.BottomSymbol;
|
|
85
|
+
}
|
|
86
|
+
return JSON.stringify(value);
|
|
89
87
|
}
|
|
90
|
-
return ['value', 'top', 'bottom', 'leq', 'join', 'meet', 'widen', 'narrow', 'concretize', 'abstract'].every(property => property in value);
|
|
91
88
|
}
|
|
89
|
+
exports.AbstractDomain = AbstractDomain;
|
|
92
90
|
//# sourceMappingURL=abstract-domain.js.map
|
|
@@ -127,7 +127,7 @@ class BoundedSetDomain extends abstract_domain_1.AbstractDomain {
|
|
|
127
127
|
if (this.value === lattice_1.Top) {
|
|
128
128
|
return lattice_1.TopSymbol;
|
|
129
129
|
}
|
|
130
|
-
const string = this.value.values().map(abstract_domain_1.
|
|
130
|
+
const string = this.value.values().map(abstract_domain_1.AbstractDomain.toString).toArray().join(', ');
|
|
131
131
|
return `{${string}}`;
|
|
132
132
|
}
|
|
133
133
|
isTop() {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
|
+
import { type AbstractProduct, PartialProductDomain } from './partial-product-domain';
|
|
3
|
+
import { type StateDomainLift, StateAbstractDomain } from './state-abstract-domain';
|
|
4
|
+
/**
|
|
5
|
+
* A reduction function for abstract values of a product domain.
|
|
6
|
+
*/
|
|
7
|
+
export type Reduction<Product extends AbstractProduct> = (value: Product) => Product;
|
|
8
|
+
/**
|
|
9
|
+
* A multi-value state abstract domain that maps AST node IDs to multiple abstract values from different abstract domains.
|
|
10
|
+
* @template Product - Type of the abstract product of the multi-value domain combining multiple abstract values
|
|
11
|
+
* @see {@link NodeId} for the node IDs of the AST nodes
|
|
12
|
+
*/
|
|
13
|
+
export declare class MultiValueStateDomain<Product extends AbstractProduct, Value extends StateDomainLift<MultiValueDomain<Product>> = StateDomainLift<MultiValueDomain<Product>>> extends StateAbstractDomain<MultiValueDomain<Product>, Value> {
|
|
14
|
+
constructor(value: Value, domain: Required<Product>, reductions?: readonly Reduction<Product>[]);
|
|
15
|
+
create(value: StateDomainLift<MultiValueDomain<Product>>): this;
|
|
16
|
+
getValue<Key extends keyof Product>(node: NodeId, property: Key): Product[Key] | undefined;
|
|
17
|
+
hasValue(node: NodeId, property: keyof Product): boolean;
|
|
18
|
+
setValue<Key extends keyof Product>(node: NodeId, property: Key, value: Product[Key]): void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A multi-value abstract domain as a (partial) product domain that combines multiple abstract domains.
|
|
22
|
+
* The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as having no sub abstract domain value.
|
|
23
|
+
* @template Product - Type of the abstract product of the multi-value domain combining multiple abstract values
|
|
24
|
+
* @see {@link MultiValueStateDomain} for a state abstract domain of a multi-value domain
|
|
25
|
+
*/
|
|
26
|
+
export declare class MultiValueDomain<Product extends AbstractProduct> extends PartialProductDomain<Product> {
|
|
27
|
+
readonly reductions: readonly Reduction<Product>[];
|
|
28
|
+
constructor(value: Product, domain: Required<Product>, reductions?: readonly Reduction<Product>[]);
|
|
29
|
+
create(value: Product): this;
|
|
30
|
+
static top<Product extends AbstractProduct>(domain: Required<Product>, reductions?: readonly Reduction<Product>[]): MultiValueDomain<Product>;
|
|
31
|
+
protected reduce(value: Product): Product;
|
|
32
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MultiValueDomain = exports.MultiValueStateDomain = void 0;
|
|
4
|
+
const lattice_1 = require("./lattice");
|
|
5
|
+
const partial_product_domain_1 = require("./partial-product-domain");
|
|
6
|
+
const state_abstract_domain_1 = require("./state-abstract-domain");
|
|
7
|
+
/**
|
|
8
|
+
* A multi-value state abstract domain that maps AST node IDs to multiple abstract values from different abstract domains.
|
|
9
|
+
* @template Product - Type of the abstract product of the multi-value domain combining multiple abstract values
|
|
10
|
+
* @see {@link NodeId} for the node IDs of the AST nodes
|
|
11
|
+
*/
|
|
12
|
+
class MultiValueStateDomain extends state_abstract_domain_1.StateAbstractDomain {
|
|
13
|
+
constructor(value, domain, reductions = []) {
|
|
14
|
+
super(value, new MultiValueDomain(domain, domain, reductions));
|
|
15
|
+
}
|
|
16
|
+
create(value) {
|
|
17
|
+
return new MultiValueStateDomain(value, this.domain.domain, this.domain.reductions);
|
|
18
|
+
}
|
|
19
|
+
getValue(node, property) {
|
|
20
|
+
if (this.value === lattice_1.Bottom) {
|
|
21
|
+
return this.domain.value[property]?.bottom();
|
|
22
|
+
}
|
|
23
|
+
return this.value.get(node)?.value[property];
|
|
24
|
+
}
|
|
25
|
+
hasValue(node, property) {
|
|
26
|
+
return this.value !== lattice_1.Bottom && this.value.get(node)?.value[property] !== undefined;
|
|
27
|
+
}
|
|
28
|
+
setValue(node, property, value) {
|
|
29
|
+
if (this.value !== lattice_1.Bottom) {
|
|
30
|
+
const oldValue = this.get(node);
|
|
31
|
+
const newValue = { ...oldValue?.value ?? {}, [property]: value };
|
|
32
|
+
this._value.set(node, new MultiValueDomain(newValue, this.domain.domain, this.domain.reductions));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.MultiValueStateDomain = MultiValueStateDomain;
|
|
37
|
+
/**
|
|
38
|
+
* A multi-value abstract domain as a (partial) product domain that combines multiple abstract domains.
|
|
39
|
+
* The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as having no sub abstract domain value.
|
|
40
|
+
* @template Product - Type of the abstract product of the multi-value domain combining multiple abstract values
|
|
41
|
+
* @see {@link MultiValueStateDomain} for a state abstract domain of a multi-value domain
|
|
42
|
+
*/
|
|
43
|
+
class MultiValueDomain extends partial_product_domain_1.PartialProductDomain {
|
|
44
|
+
reductions;
|
|
45
|
+
constructor(value, domain, reductions = []) {
|
|
46
|
+
super(value, domain);
|
|
47
|
+
this.reductions = reductions;
|
|
48
|
+
}
|
|
49
|
+
create(value) {
|
|
50
|
+
return new MultiValueDomain(value, this.domain, this.reductions);
|
|
51
|
+
}
|
|
52
|
+
static top(domain, reductions = []) {
|
|
53
|
+
return new MultiValueDomain({}, domain, reductions);
|
|
54
|
+
}
|
|
55
|
+
reduce(value) {
|
|
56
|
+
return this.reductions.reduce((current, reduction) => reduction(current), value);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.MultiValueDomain = MultiValueDomain;
|
|
60
|
+
//# sourceMappingURL=multi-value-state-domain.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type AnyAbstractDomain, 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<Domain extends AnyAbstractDomain = AnyAbstractDomain> = {
|
|
5
|
+
[key in string]?: Domain;
|
|
6
|
+
};
|
|
7
|
+
/** The type of the concrete product of an abstract product mapping each property to a concrete value in the respective concrete domain */
|
|
8
|
+
export type ConcreteProductOf<Product extends AbstractProduct> = {
|
|
9
|
+
[Key in keyof Product]: Product[Key] extends AbstractDomain<infer Concrete, unknown, unknown, unknown> ? Concrete : never;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A partial product abstract domain as named Cartesian product of (optional) sub abstract domains.
|
|
13
|
+
* The sub abstract domains are represented by a (partial) record mapping property names to abstract domains.
|
|
14
|
+
* The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as having no sub abstract domain value.
|
|
15
|
+
* @template Product - Type of the abstract product of the product domain mapping (optional) property names to abstract domains
|
|
16
|
+
*/
|
|
17
|
+
export declare abstract class PartialProductDomain<Product extends AbstractProduct> extends AbstractDomain<ConcreteProductOf<Product>, Product, Product, Product> {
|
|
18
|
+
readonly domain: Required<Product>;
|
|
19
|
+
constructor(value: Product, domain: Required<Product>);
|
|
20
|
+
abstract create(value: Product): this;
|
|
21
|
+
bottom(): this;
|
|
22
|
+
top(): this;
|
|
23
|
+
equals(other: this): boolean;
|
|
24
|
+
leq(other: this): boolean;
|
|
25
|
+
join(other: this): this;
|
|
26
|
+
meet(other: this): this;
|
|
27
|
+
widen(other: this): this;
|
|
28
|
+
narrow(other: this): this;
|
|
29
|
+
concretize(limit: number): ReadonlySet<ConcreteProductOf<Product>> | typeof Top;
|
|
30
|
+
abstract(concrete: ReadonlySet<ConcreteProductOf<Product>> | typeof Top): this;
|
|
31
|
+
toJson(): unknown;
|
|
32
|
+
toString(): string;
|
|
33
|
+
isTop(): boolean;
|
|
34
|
+
isTop(): this is this;
|
|
35
|
+
isBottom(): boolean;
|
|
36
|
+
isBottom(): this is this;
|
|
37
|
+
isValue(): boolean;
|
|
38
|
+
isValue(): this is this;
|
|
39
|
+
/**
|
|
40
|
+
* Optional reduction function for a reduced product domain.
|
|
41
|
+
*/
|
|
42
|
+
protected reduce(value: Product): Product;
|
|
43
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PartialProductDomain = void 0;
|
|
4
|
+
const abstract_domain_1 = require("./abstract-domain");
|
|
5
|
+
const lattice_1 = require("./lattice");
|
|
6
|
+
const record_1 = require("../../util/record");
|
|
7
|
+
/**
|
|
8
|
+
* A partial product abstract domain as named Cartesian product of (optional) sub abstract domains.
|
|
9
|
+
* The sub abstract domains are represented by a (partial) record mapping property names to abstract domains.
|
|
10
|
+
* The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as having no sub abstract domain value.
|
|
11
|
+
* @template Product - Type of the abstract product of the product domain mapping (optional) property names to abstract domains
|
|
12
|
+
*/
|
|
13
|
+
class PartialProductDomain extends abstract_domain_1.AbstractDomain {
|
|
14
|
+
domain;
|
|
15
|
+
constructor(value, domain) {
|
|
16
|
+
super(record_1.Record.mapProperties(value, entry => entry?.create(entry.value)));
|
|
17
|
+
this._value = this.reduce(this.value);
|
|
18
|
+
this.domain = domain;
|
|
19
|
+
}
|
|
20
|
+
bottom() {
|
|
21
|
+
const result = this.create(this.domain);
|
|
22
|
+
for (const key in result.value) {
|
|
23
|
+
result.value[key] = this.domain[key]?.bottom();
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
top() {
|
|
28
|
+
return this.create({});
|
|
29
|
+
}
|
|
30
|
+
equals(other) {
|
|
31
|
+
if (this.value === other.value) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
for (const key in this.value) {
|
|
35
|
+
if (this.value[key] == other.value[key]) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
else if (this.value[key] === undefined || other.value[key] === undefined || !this.value[key].equals(other.value[key])) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
leq(other) {
|
|
45
|
+
if (this.value === other.value) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
for (const key in this.value) {
|
|
49
|
+
if (this.value[key] === other.value[key] || other.value[key] === undefined) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
else if (this.value[key] === undefined || !this.value[key].leq(other.value[key])) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
join(other) {
|
|
59
|
+
const result = {};
|
|
60
|
+
for (const key in this.domain) {
|
|
61
|
+
if (this.value[key] !== undefined && other.value[key] !== undefined) {
|
|
62
|
+
result[key] = this.value[key].join(other.value[key]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return this.create(result);
|
|
66
|
+
}
|
|
67
|
+
meet(other) {
|
|
68
|
+
const result = {};
|
|
69
|
+
for (const key in this.domain) {
|
|
70
|
+
if (this.value[key] === undefined) {
|
|
71
|
+
result[key] = other.value[key];
|
|
72
|
+
}
|
|
73
|
+
else if (other.value[key] === undefined) {
|
|
74
|
+
result[key] = this.value[key];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
result[key] = this.value[key].meet(other.value[key]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return this.create(result);
|
|
81
|
+
}
|
|
82
|
+
widen(other) {
|
|
83
|
+
const result = {};
|
|
84
|
+
for (const key in this.domain) {
|
|
85
|
+
if (this.value[key] !== undefined && other.value[key] !== undefined) {
|
|
86
|
+
result[key] = this.value[key].widen(other.value[key]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return this.create(result);
|
|
90
|
+
}
|
|
91
|
+
narrow(other) {
|
|
92
|
+
const result = {};
|
|
93
|
+
for (const key in this.domain) {
|
|
94
|
+
if (this.value[key] === undefined) {
|
|
95
|
+
result[key] = other.value[key];
|
|
96
|
+
}
|
|
97
|
+
else if (other.value[key] === undefined) {
|
|
98
|
+
result[key] = this.value[key];
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
result[key] = this.value[key].narrow(other.value[key]);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return this.create(result);
|
|
105
|
+
}
|
|
106
|
+
concretize(limit) {
|
|
107
|
+
let result = new Set([{}]);
|
|
108
|
+
for (const key in this.value) {
|
|
109
|
+
if (this.value[key] === undefined) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const concrete = this.value[key].concretize(limit);
|
|
113
|
+
if (concrete === lattice_1.Top) {
|
|
114
|
+
return lattice_1.Top;
|
|
115
|
+
}
|
|
116
|
+
const newResult = new Set();
|
|
117
|
+
for (const value of concrete) {
|
|
118
|
+
for (const entry of result) {
|
|
119
|
+
if (newResult.size >= limit) {
|
|
120
|
+
return lattice_1.Top;
|
|
121
|
+
}
|
|
122
|
+
newResult.add({ ...entry, [key]: value });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
result = newResult;
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
abstract(concrete) {
|
|
130
|
+
if (concrete === lattice_1.Top) {
|
|
131
|
+
return this.top();
|
|
132
|
+
}
|
|
133
|
+
const result = {};
|
|
134
|
+
for (const key in this.domain) {
|
|
135
|
+
const concreteValues = new Set(concrete.values().map(value => value[key]));
|
|
136
|
+
result[key] = this.domain[key]?.abstract(concreteValues);
|
|
137
|
+
}
|
|
138
|
+
return this.create(result);
|
|
139
|
+
}
|
|
140
|
+
toJson() {
|
|
141
|
+
return record_1.Record.mapProperties(this.value, entry => entry?.toJson());
|
|
142
|
+
}
|
|
143
|
+
toString() {
|
|
144
|
+
return '(' + record_1.Record.entries(this.value).map(([key, value]) => `${key}: ${value.toString()}`).join(', ') + ')';
|
|
145
|
+
}
|
|
146
|
+
isTop() {
|
|
147
|
+
return record_1.Record.values(this.value).length === 0;
|
|
148
|
+
}
|
|
149
|
+
isBottom() {
|
|
150
|
+
return record_1.Record.values(this.value).every(value => value.isBottom());
|
|
151
|
+
}
|
|
152
|
+
isValue() {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Optional reduction function for a reduced product domain.
|
|
157
|
+
*/
|
|
158
|
+
reduce(value) {
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.PartialProductDomain = PartialProductDomain;
|
|
163
|
+
//# sourceMappingURL=partial-product-domain.js.map
|
|
@@ -1,41 +1,14 @@
|
|
|
1
|
-
import {
|
|
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, AnyAbstractDomain>;
|
|
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
|
-
};
|
|
1
|
+
import { type AbstractProduct, PartialProductDomain } from './partial-product-domain';
|
|
9
2
|
/**
|
|
10
3
|
* A product abstract domain as named Cartesian product of sub abstract domains.
|
|
11
4
|
* The sub abstract domains are represented by a record mapping property names to abstract domains.
|
|
12
5
|
* 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
6
|
* @template Product - Type of the abstract product of the product domain mapping property names to abstract domains
|
|
14
7
|
*/
|
|
15
|
-
export declare abstract class ProductDomain<Product extends AbstractProduct
|
|
8
|
+
export declare abstract class ProductDomain<Product extends Required<AbstractProduct>> extends PartialProductDomain<Product> {
|
|
16
9
|
constructor(value: Product);
|
|
17
10
|
abstract create(value: Product): this;
|
|
18
|
-
bottom(): this;
|
|
19
11
|
top(): this;
|
|
20
|
-
equals(other: this): boolean;
|
|
21
|
-
leq(other: this): boolean;
|
|
22
|
-
join(other: this): this;
|
|
23
|
-
meet(other: this): this;
|
|
24
|
-
widen(other: this): this;
|
|
25
|
-
narrow(other: this): this;
|
|
26
|
-
concretize(limit: number): ReadonlySet<ConcreteProduct<Product>> | typeof Top;
|
|
27
|
-
abstract(concrete: ReadonlySet<ConcreteProduct<Product>> | typeof Top): this;
|
|
28
|
-
toJson(): unknown;
|
|
29
|
-
toString(): string;
|
|
30
12
|
isTop(): boolean;
|
|
31
13
|
isTop(): this is this;
|
|
32
|
-
isBottom(): boolean;
|
|
33
|
-
isBottom(): this is this;
|
|
34
|
-
isValue(): boolean;
|
|
35
|
-
isValue(): this is this;
|
|
36
|
-
/**
|
|
37
|
-
* Optional reduction function for a reduced product domain.
|
|
38
|
-
*/
|
|
39
|
-
protected reduce(value: Product): Product;
|
|
40
|
-
private refine;
|
|
41
14
|
}
|
|
@@ -1,144 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ProductDomain = void 0;
|
|
4
|
-
const abstract_domain_1 = require("./abstract-domain");
|
|
5
|
-
const lattice_1 = require("./lattice");
|
|
6
4
|
const record_1 = require("../../util/record");
|
|
5
|
+
const partial_product_domain_1 = require("./partial-product-domain");
|
|
7
6
|
/**
|
|
8
7
|
* A product abstract domain as named Cartesian product of sub abstract domains.
|
|
9
8
|
* The sub abstract domains are represented by a record mapping property names to abstract domains.
|
|
10
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.
|
|
11
10
|
* @template Product - Type of the abstract product of the product domain mapping property names to abstract domains
|
|
12
11
|
*/
|
|
13
|
-
class ProductDomain extends
|
|
12
|
+
class ProductDomain extends partial_product_domain_1.PartialProductDomain {
|
|
14
13
|
constructor(value) {
|
|
15
|
-
super(
|
|
16
|
-
this._value = this.reduce(this.value);
|
|
17
|
-
}
|
|
18
|
-
bottom() {
|
|
19
|
-
const result = this.create(this.value);
|
|
20
|
-
for (const key in result.value) {
|
|
21
|
-
result._value[key] = result.value[key].bottom();
|
|
22
|
-
}
|
|
23
|
-
return result;
|
|
14
|
+
super(value, value);
|
|
24
15
|
}
|
|
25
16
|
top() {
|
|
26
|
-
const result = this.create(this.
|
|
27
|
-
for (const key in result.value) {
|
|
28
|
-
result._value[key] = result.value[key].top();
|
|
29
|
-
}
|
|
30
|
-
return result;
|
|
31
|
-
}
|
|
32
|
-
equals(other) {
|
|
33
|
-
if (this.value === other.value) {
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
for (const key in this.value) {
|
|
37
|
-
if (!this.value[key].equals(other.value[key])) {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
leq(other) {
|
|
44
|
-
if (this.value === other.value) {
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
for (const key in this.value) {
|
|
48
|
-
if (!this.value[key].leq(other.value[key])) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
join(other) {
|
|
55
|
-
const result = this.create(this.value);
|
|
56
|
-
for (const key in result.value) {
|
|
57
|
-
result._value[key] = result.value[key].join(other.value[key]);
|
|
58
|
-
}
|
|
59
|
-
return result.refine();
|
|
60
|
-
}
|
|
61
|
-
meet(other) {
|
|
62
|
-
const result = this.create(this.value);
|
|
63
|
-
for (const key in result.value) {
|
|
64
|
-
result._value[key] = result.value[key].meet(other.value[key]);
|
|
65
|
-
}
|
|
66
|
-
return result.refine();
|
|
67
|
-
}
|
|
68
|
-
widen(other) {
|
|
69
|
-
const result = this.create(this.value);
|
|
70
|
-
for (const key in result.value) {
|
|
71
|
-
result._value[key] = result.value[key].widen(other.value[key]);
|
|
72
|
-
}
|
|
73
|
-
return result.refine();
|
|
74
|
-
}
|
|
75
|
-
narrow(other) {
|
|
76
|
-
const result = this.create(this.value);
|
|
17
|
+
const result = this.create(this.domain);
|
|
77
18
|
for (const key in result.value) {
|
|
78
|
-
result.
|
|
79
|
-
}
|
|
80
|
-
return result.refine();
|
|
81
|
-
}
|
|
82
|
-
concretize(limit) {
|
|
83
|
-
let result = new Set([{}]);
|
|
84
|
-
for (const key in this.value) {
|
|
85
|
-
const concrete = this.value[key].concretize(limit);
|
|
86
|
-
if (concrete === lattice_1.Top) {
|
|
87
|
-
return lattice_1.Top;
|
|
88
|
-
}
|
|
89
|
-
const newResult = new Set();
|
|
90
|
-
for (const value of concrete) {
|
|
91
|
-
for (const entry of result) {
|
|
92
|
-
if (newResult.size >= limit) {
|
|
93
|
-
return lattice_1.Top;
|
|
94
|
-
}
|
|
95
|
-
newResult.add({ ...entry, [key]: value });
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
result = newResult;
|
|
19
|
+
result.value[key] = result.value[key]?.top();
|
|
99
20
|
}
|
|
100
21
|
return result;
|
|
101
22
|
}
|
|
102
|
-
abstract(concrete) {
|
|
103
|
-
if (concrete === lattice_1.Top) {
|
|
104
|
-
return this.top();
|
|
105
|
-
}
|
|
106
|
-
const result = this.create(this.value);
|
|
107
|
-
for (const key in result.value) {
|
|
108
|
-
const concreteValues = new Set(concrete.values().map(value => value[key]));
|
|
109
|
-
result._value[key] = result.value[key].abstract(concreteValues);
|
|
110
|
-
}
|
|
111
|
-
return result.refine();
|
|
112
|
-
}
|
|
113
|
-
toJson() {
|
|
114
|
-
return record_1.Record.mapProperties(this.value, entry => entry.toJson());
|
|
115
|
-
}
|
|
116
|
-
toString() {
|
|
117
|
-
return '(' + Object.entries(this.value).map(([key, value]) => `${key}: ${value.toString()}`).join(', ') + ')';
|
|
118
|
-
}
|
|
119
23
|
isTop() {
|
|
120
|
-
return
|
|
121
|
-
}
|
|
122
|
-
isBottom() {
|
|
123
|
-
return Object.values(this.value).every(value => value.isBottom());
|
|
124
|
-
}
|
|
125
|
-
isValue() {
|
|
126
|
-
return true;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Optional reduction function for a reduced product domain.
|
|
130
|
-
*/
|
|
131
|
-
reduce(value) {
|
|
132
|
-
return value;
|
|
133
|
-
}
|
|
134
|
-
refine() {
|
|
135
|
-
if (!this.isTop() || this.isBottom()) {
|
|
136
|
-
const reduced = this.reduce(this.value);
|
|
137
|
-
if (reduced !== this.value) {
|
|
138
|
-
return this.create(reduced);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return this;
|
|
24
|
+
return record_1.Record.values(this.value).every(value => value.isTop());
|
|
142
25
|
}
|
|
143
26
|
}
|
|
144
27
|
exports.ProductDomain = ProductDomain;
|
|
@@ -382,11 +382,11 @@ class SetRangeDomain extends abstract_domain_1.AbstractDomain {
|
|
|
382
382
|
return lattice_1.BottomSymbol;
|
|
383
383
|
}
|
|
384
384
|
else if (this.value.range === lattice_1.Top) {
|
|
385
|
-
const minString = this.value.min.values().map(abstract_domain_1.
|
|
385
|
+
const minString = this.value.min.values().map(abstract_domain_1.AbstractDomain.toString).toArray().join(', ');
|
|
386
386
|
return `[{${minString}}, ${lattice_1.TopSymbol}]`;
|
|
387
387
|
}
|
|
388
|
-
const minString = this.value.min.values().map(abstract_domain_1.
|
|
389
|
-
const rangeString = this.value.range.values().map(abstract_domain_1.
|
|
388
|
+
const minString = this.value.min.values().map(abstract_domain_1.AbstractDomain.toString).toArray().join(', ');
|
|
389
|
+
const rangeString = this.value.range.values().map(abstract_domain_1.AbstractDomain.toString).toArray().join(', ');
|
|
390
390
|
return `[{${minString}}, {${rangeString}}]`;
|
|
391
391
|
}
|
|
392
392
|
isTop() {
|
|
@@ -180,7 +180,7 @@ class SetUpperBoundDomain extends abstract_domain_1.AbstractDomain {
|
|
|
180
180
|
else if (this.value === lattice_1.Bottom) {
|
|
181
181
|
return lattice_1.BottomSymbol;
|
|
182
182
|
}
|
|
183
|
-
const string = this.value.values().map(abstract_domain_1.
|
|
183
|
+
const string = this.value.values().map(abstract_domain_1.AbstractDomain.toString).toArray().join(', ');
|
|
184
184
|
return `{${string}}`;
|
|
185
185
|
}
|
|
186
186
|
isTop() {
|
|
@@ -114,7 +114,7 @@ class SingletonDomain extends abstract_domain_1.AbstractDomain {
|
|
|
114
114
|
else if (this.value === lattice_1.Bottom) {
|
|
115
115
|
return lattice_1.BottomSymbol;
|
|
116
116
|
}
|
|
117
|
-
return
|
|
117
|
+
return abstract_domain_1.AbstractDomain.toString(this.value);
|
|
118
118
|
}
|
|
119
119
|
isTop() {
|
|
120
120
|
return this.value === lattice_1.Top;
|