@eagleoutice/flowr 2.10.3 → 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.
Files changed (94) hide show
  1. package/README.md +43 -26
  2. package/abstract-interpretation/absint-visitor.d.ts +17 -21
  3. package/abstract-interpretation/absint-visitor.js +47 -48
  4. package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -3
  5. package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -1
  6. package/abstract-interpretation/data-frame/shape-inference.js +5 -4
  7. package/abstract-interpretation/domains/abstract-domain.d.ts +17 -16
  8. package/abstract-interpretation/domains/abstract-domain.js +25 -27
  9. package/abstract-interpretation/domains/bounded-set-domain.js +1 -1
  10. package/abstract-interpretation/domains/multi-value-state-domain.d.ts +32 -0
  11. package/abstract-interpretation/domains/multi-value-state-domain.js +60 -0
  12. package/abstract-interpretation/domains/partial-product-domain.d.ts +43 -0
  13. package/abstract-interpretation/domains/partial-product-domain.js +163 -0
  14. package/abstract-interpretation/domains/product-domain.d.ts +2 -29
  15. package/abstract-interpretation/domains/product-domain.js +6 -123
  16. package/abstract-interpretation/domains/set-range-domain.js +3 -3
  17. package/abstract-interpretation/domains/set-upper-bound-domain.js +1 -1
  18. package/abstract-interpretation/domains/singleton-domain.js +1 -1
  19. package/abstract-interpretation/domains/state-abstract-domain.d.ts +13 -28
  20. package/abstract-interpretation/domains/state-abstract-domain.js +16 -38
  21. package/abstract-interpretation/domains/state-domain-like.d.ts +36 -0
  22. package/abstract-interpretation/domains/state-domain-like.js +3 -0
  23. package/cli/flowr.js +11 -1
  24. package/config.d.ts +7 -0
  25. package/config.js +22 -3
  26. package/control-flow/semantic-cfg-guided-visitor.d.ts +4 -0
  27. package/control-flow/semantic-cfg-guided-visitor.js +20 -32
  28. package/dataflow/environments/default-builtin-config.d.ts +10 -0
  29. package/dataflow/environments/default-builtin-config.js +2 -1
  30. package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +2 -0
  31. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +38 -21
  32. package/documentation/doc-readme.js +13 -2
  33. package/documentation/wiki-absint.d.ts +1 -2
  34. package/documentation/wiki-absint.js +34 -10
  35. package/documentation/wiki-analyzer.js +3 -4
  36. package/documentation/wiki-interface.js +21 -16
  37. package/documentation/wiki-linter.js +1 -1
  38. package/linter/linter-rules.d.ts +12 -12
  39. package/linter/linter-rules.js +2 -2
  40. package/linter/rules/network-functions.d.ts +1 -1
  41. package/linter/rules/network-functions.js +8 -2
  42. package/linter/rules/problematic-inputs.d.ts +43 -0
  43. package/linter/rules/problematic-inputs.js +110 -0
  44. package/linter/rules/seeded-randomness.d.ts +1 -1
  45. package/linter/rules/seeded-randomness.js +8 -1
  46. package/package.json +4 -4
  47. package/project/flowr-analyzer-builder.d.ts +6 -3
  48. package/project/flowr-analyzer-builder.js +12 -5
  49. package/project/plugins/file-plugins/files/flowr-rmarkdown-file.d.ts +4 -3
  50. package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +17 -4
  51. package/project/plugins/flowr-analyzer-plugin.d.ts +1 -1
  52. package/project/plugins/flowr-analyzer-plugin.js +1 -1
  53. package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
  54. package/queries/catalog/call-context-query/call-context-query-format.d.ts +1 -1
  55. package/queries/catalog/call-context-query/call-context-query-format.js +1 -2
  56. package/queries/catalog/dependencies-query/function-info/read-functions.js +6 -0
  57. package/queries/catalog/dependencies-query/function-info/write-functions.js +7 -0
  58. package/queries/catalog/input-sources-query/input-source-functions.d.ts +6 -0
  59. package/queries/catalog/input-sources-query/input-source-functions.js +50 -0
  60. package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +1 -1
  61. package/queries/catalog/input-sources-query/input-sources-query-executor.js +19 -31
  62. package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +2 -1
  63. package/queries/catalog/input-sources-query/input-sources-query-format.js +26 -8
  64. package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +33 -28
  65. package/queries/catalog/input-sources-query/simple-input-classifier.js +192 -99
  66. package/r-bridge/lang-4.x/ast/model/model.d.ts +4 -4
  67. package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +3 -3
  68. package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +3 -3
  69. package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +3 -3
  70. package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +3 -3
  71. package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +3 -3
  72. package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +3 -3
  73. package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +3 -3
  74. package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
  75. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +3 -3
  76. package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +3 -3
  77. package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +3 -3
  78. package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +3 -3
  79. package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +3 -3
  80. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -3
  81. package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +3 -3
  82. package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +3 -3
  83. package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +3 -3
  84. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -3
  85. package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +3 -3
  86. package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +3 -3
  87. package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +3 -3
  88. package/util/record.d.ts +18 -3
  89. package/util/record.js +22 -1
  90. package/util/version.js +1 -1
  91. package/linter/rules/problematic-eval.d.ts +0 -44
  92. package/linter/rules/problematic-eval.js +0 -83
  93. package/project/plugins/flowr-analyzer-plugin-defaults.d.ts +0 -5
  94. 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
- exports.AbstractDomain = AbstractDomain;
67
- /**
68
- * Converts an element of an abstract domain into a string.
69
- */
70
- function domainElementToString(value) {
71
- if (typeof value === 'object' && value !== null && value.toString !== Object.prototype.toString) {
72
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
73
- return value.toString();
74
- }
75
- else if (value === lattice_1.Top) {
76
- return lattice_1.TopSymbol;
77
- }
78
- else if (value === lattice_1.Bottom) {
79
- return lattice_1.BottomSymbol;
80
- }
81
- return JSON.stringify(value);
82
- }
83
- /**
84
- * Checks whether a value is an abstract domain.
85
- */
86
- function isAbstractDomain(value) {
87
- if (typeof value !== 'object' || value === null) {
88
- return false;
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.domainElementToString).toArray().join(', ');
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 { AbstractDomain, type AnyAbstractDomain } 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, 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> extends AbstractDomain<ConcreteProduct<Product>, Product, Product, Product> {
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 abstract_domain_1.AbstractDomain {
12
+ class ProductDomain extends partial_product_domain_1.PartialProductDomain {
14
13
  constructor(value) {
15
- super(record_1.Record.mapProperties(value, entry => entry.create(entry.value)));
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.value);
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._value[key] = result.value[key].narrow(other.value[key]);
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 Object.values(this.value).every(value => value.isTop());
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.domainElementToString).toArray().join(', ');
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.domainElementToString).toArray().join(', ');
389
- const rangeString = this.value.range.values().map(abstract_domain_1.domainElementToString).toArray().join(', ');
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.domainElementToString).toArray().join(', ');
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 (0, abstract_domain_1.domainElementToString)(this.value);
117
+ return abstract_domain_1.AbstractDomain.toString(this.value);
118
118
  }
119
119
  isTop() {
120
120
  return this.value === lattice_1.Top;