@eagleoutice/flowr 2.0.16 → 2.0.17
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 +1 -1
- package/cli/repl/commands/commands.js +3 -1
- package/cli/repl/commands/lineage.d.ts +15 -0
- package/cli/repl/commands/lineage.js +66 -0
- package/cli/repl/server/connection.d.ts +1 -0
- package/cli/repl/server/connection.js +34 -0
- package/cli/repl/server/messages/lineage.d.ts +16 -0
- package/cli/repl/server/messages/lineage.js +17 -0
- package/cli/repl/server/messages/messages.d.ts +2 -1
- package/dataflow/environments/built-in.js +18 -8
- package/dataflow/environments/environment.js +4 -3
- package/dataflow/environments/resolve-by-name.d.ts +1 -1
- package/dataflow/environments/resolve-by-name.js +4 -4
- package/dataflow/graph/diff.js +1 -0
- package/dataflow/graph/graph.d.ts +18 -19
- package/dataflow/graph/graph.js +41 -24
- package/dataflow/graph/vertex.d.ts +6 -1
- package/dataflow/graph/vertex.js +21 -0
- package/dataflow/info.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +10 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-library.js +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.d.ts +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +18 -7
- package/dataflow/internal/process/functions/call/built-in/{built-in-logical-bin-op.d.ts → built-in-special-bin-op.d.ts} +2 -1
- package/dataflow/internal/process/functions/call/built-in/{built-in-logical-bin-op.js → built-in-special-bin-op.js} +3 -3
- package/dataflow/internal/process/functions/call/common.d.ts +6 -2
- package/dataflow/internal/process/functions/call/common.js +36 -1
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +3 -2
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -2
- package/dataflow/internal/process/functions/call/named-call-handling.js +3 -1
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +1 -0
- package/dataflow/internal/process/functions/process-argument.js +0 -28
- package/package.json +3 -2
- package/r-bridge/data/data.d.ts +5 -0
- package/r-bridge/data/data.js +6 -0
- package/slicing/criterion/parse.d.ts +3 -4
- package/slicing/criterion/parse.js +3 -3
- package/slicing/static/static-slicer.d.ts +1 -1
- package/slicing/static/static-slicer.js +10 -4
- package/statistics/statistics.js +1 -1
- package/util/json.d.ts +1 -1
- package/util/json.js +3 -3
- package/util/logic.d.ts +5 -1
- package/util/version.js +1 -1
- package/abstract-interpretation/domain.d.ts +0 -57
- package/abstract-interpretation/domain.js +0 -176
- package/abstract-interpretation/handler/binop/binop.d.ts +0 -15
- package/abstract-interpretation/handler/binop/binop.js +0 -42
- package/abstract-interpretation/handler/binop/operators.d.ts +0 -2
- package/abstract-interpretation/handler/binop/operators.js +0 -28
- package/abstract-interpretation/handler/handler.d.ts +0 -6
- package/abstract-interpretation/handler/handler.js +0 -3
- package/abstract-interpretation/processor.d.ts +0 -11
- package/abstract-interpretation/processor.js +0 -84
|
@@ -13,4 +13,4 @@ export declare const slicerLogger: import("tslog").Logger<import("tslog").ILogOb
|
|
|
13
13
|
* @param criteria - The criteras to slice on.
|
|
14
14
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
15
15
|
*/
|
|
16
|
-
export declare function staticSlicing(graph: DataflowGraph,
|
|
16
|
+
export declare function staticSlicing(graph: DataflowGraph, { idMap }: NormalizedAst, criteria: SlicingCriteria, threshold?: number): Readonly<SliceResult>;
|
|
@@ -20,9 +20,9 @@ exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
|
|
|
20
20
|
* @param criteria - The criteras to slice on.
|
|
21
21
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
22
22
|
*/
|
|
23
|
-
function staticSlicing(graph,
|
|
23
|
+
function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
24
24
|
(0, assert_1.guard)(criteria.length > 0, 'must have at least one seed id to calculate slice');
|
|
25
|
-
const decodedCriteria = (0, parse_1.convertAllSlicingCriteriaToIds)(criteria,
|
|
25
|
+
const decodedCriteria = (0, parse_1.convertAllSlicingCriteriaToIds)(criteria, idMap);
|
|
26
26
|
(0, log_1.expensiveTrace)(exports.slicerLogger, () => `calculating slice for ${decodedCriteria.length} seed criteria: ${decodedCriteria.map(s => JSON.stringify(s)).join(', ')}`);
|
|
27
27
|
const queue = new visiting_queue_1.VisitingQueue(threshold);
|
|
28
28
|
let minDepth = Number.MAX_SAFE_INTEGER;
|
|
@@ -34,9 +34,15 @@ function staticSlicing(graph, ast, criteria, threshold = 75) {
|
|
|
34
34
|
for (const { id: startId } of decodedCriteria) {
|
|
35
35
|
queue.add(startId, emptyEnv, basePrint, false);
|
|
36
36
|
// retrieve the minimum depth of all nodes to only add control dependencies if they are "part" of the current execution
|
|
37
|
-
minDepth = Math.min(minDepth,
|
|
37
|
+
minDepth = Math.min(minDepth, idMap.get(startId)?.info.depth ?? minDepth);
|
|
38
38
|
sliceSeedIds.add(startId);
|
|
39
39
|
}
|
|
40
|
+
/* additionally,
|
|
41
|
+
* include all the implicit side effects that we have to consider as we are unable to narrow them down
|
|
42
|
+
*/
|
|
43
|
+
for (const id of graph.unknownSideEffects) {
|
|
44
|
+
queue.add(id, emptyEnv, basePrint, true);
|
|
45
|
+
}
|
|
40
46
|
}
|
|
41
47
|
while (queue.nonEmpty()) {
|
|
42
48
|
const current = queue.next();
|
|
@@ -52,7 +58,7 @@ function staticSlicing(graph, ast, criteria, threshold = 75) {
|
|
|
52
58
|
if (currentVertex.controlDependencies && currentVertex.controlDependencies.length > 0) {
|
|
53
59
|
const topLevel = graph.isRoot(id) || sliceSeedIds.has(id);
|
|
54
60
|
for (const cd of currentVertex.controlDependencies.filter(({ id }) => !queue.hasId(id))) {
|
|
55
|
-
if (!topLevel || (
|
|
61
|
+
if (!topLevel || (idMap.get(cd.id)?.info.depth ?? 0) <= minDepth) {
|
|
56
62
|
queue.add(cd.id, baseEnvironment, baseEnvFingerprint, false);
|
|
57
63
|
}
|
|
58
64
|
}
|
package/statistics/statistics.js
CHANGED
|
@@ -64,7 +64,7 @@ function initializeFeatureStatistics() {
|
|
|
64
64
|
const result = {};
|
|
65
65
|
for (const key of feature_1.allFeatureNames) {
|
|
66
66
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
67
|
-
result[key] = JSON.parse(JSON.stringify(feature_1.ALL_FEATURES[key].initialValue, json_1.jsonReplacer), json_1.
|
|
67
|
+
result[key] = JSON.parse(JSON.stringify(feature_1.ALL_FEATURES[key].initialValue, json_1.jsonReplacer), json_1.jsonBigIntRetriever);
|
|
68
68
|
}
|
|
69
69
|
return result;
|
|
70
70
|
}
|
package/util/json.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare function jsonReplacer(key: any, value: any): any;
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function jsonBigIntRetriever(key: string, value: unknown): unknown;
|
package/util/json.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.jsonBigIntRetriever = exports.jsonReplacer = void 0;
|
|
4
4
|
// to get the types within JSON.stringify
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
function jsonReplacer(key, value) {
|
|
@@ -16,7 +16,7 @@ function jsonReplacer(key, value) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
exports.jsonReplacer = jsonReplacer;
|
|
19
|
-
function
|
|
19
|
+
function jsonBigIntRetriever(key, value) {
|
|
20
20
|
if (typeof value === 'string' && value.endsWith('n')) {
|
|
21
21
|
return BigInt(value.slice(0, -1));
|
|
22
22
|
}
|
|
@@ -24,5 +24,5 @@ function jsonRetriever(key, value) {
|
|
|
24
24
|
return value;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
exports.
|
|
27
|
+
exports.jsonBigIntRetriever = jsonBigIntRetriever;
|
|
28
28
|
//# sourceMappingURL=json.js.map
|
package/util/logic.d.ts
CHANGED
package/util/version.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.flowrVersion = void 0;
|
|
4
4
|
const semver_1 = require("semver");
|
|
5
5
|
// this is automatically replaced with the current version by release-it
|
|
6
|
-
const version = '2.0.
|
|
6
|
+
const version = '2.0.17';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
interface IntervalBound {
|
|
2
|
-
readonly value: number;
|
|
3
|
-
readonly inclusive: boolean;
|
|
4
|
-
}
|
|
5
|
-
export declare class Interval {
|
|
6
|
-
readonly min: IntervalBound;
|
|
7
|
-
readonly max: IntervalBound;
|
|
8
|
-
/**
|
|
9
|
-
* Build a new interval from the given bounds.
|
|
10
|
-
* If the interval represents a scalar, the min and max bounds should be equal, as well as their inclusivity.
|
|
11
|
-
* @param min - The minimum bound of the interval.
|
|
12
|
-
* @param max - The maximum bound of the interval.
|
|
13
|
-
*/
|
|
14
|
-
constructor(min: IntervalBound, max: IntervalBound);
|
|
15
|
-
toString(): string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* A domain represents a set of intervals describing a range of possible values a variable may hold.
|
|
19
|
-
* In the future we may want to extend this to support more complex types.
|
|
20
|
-
*/
|
|
21
|
-
export declare class Domain {
|
|
22
|
-
/** set of intervals to hold */
|
|
23
|
-
private readonly _intervals;
|
|
24
|
-
private constructor();
|
|
25
|
-
static bottom(): Domain;
|
|
26
|
-
static fromIntervals(intervals: readonly Interval[] | ReadonlySet<Interval>): Domain;
|
|
27
|
-
static fromScalar(n: number): Domain;
|
|
28
|
-
get intervals(): Set<Interval>;
|
|
29
|
-
private set intervals(value);
|
|
30
|
-
addInterval(interval: Interval): void;
|
|
31
|
-
toString(): string;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Returns true if the given intervals overlap, checking for inclusivity.
|
|
35
|
-
*/
|
|
36
|
-
export declare function doIntervalsOverlap(interval1: Interval, interval2: Interval): boolean;
|
|
37
|
-
/**
|
|
38
|
-
* Unifies the given domains by creating a new domain that contains all values from all given domains.
|
|
39
|
-
*/
|
|
40
|
-
export declare function unifyDomains(domains: readonly Domain[]): Domain;
|
|
41
|
-
/**
|
|
42
|
-
* Unify all intervals which overlap with each other to one.
|
|
43
|
-
*/
|
|
44
|
-
export declare function unifyOverlappingIntervals(intervals: readonly Interval[]): Interval[];
|
|
45
|
-
/**
|
|
46
|
-
* Returns domain1 + domain2, mapping the inclusivity.
|
|
47
|
-
*
|
|
48
|
-
* @see subtractDomains
|
|
49
|
-
*/
|
|
50
|
-
export declare function addDomains(domain1: Domain, domain2: Domain): Domain;
|
|
51
|
-
/**
|
|
52
|
-
* Returns domain1 - domain2, mapping the inclusivity.
|
|
53
|
-
*
|
|
54
|
-
* @see addDomains
|
|
55
|
-
*/
|
|
56
|
-
export declare function subtractDomains(domain1: Domain, domain2: Domain): Domain;
|
|
57
|
-
export {};
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.subtractDomains = exports.addDomains = exports.unifyOverlappingIntervals = exports.unifyDomains = exports.doIntervalsOverlap = exports.Domain = exports.Interval = void 0;
|
|
4
|
-
const assert_1 = require("../util/assert");
|
|
5
|
-
class Interval {
|
|
6
|
-
min;
|
|
7
|
-
max;
|
|
8
|
-
/**
|
|
9
|
-
* Build a new interval from the given bounds.
|
|
10
|
-
* If the interval represents a scalar, the min and max bounds should be equal, as well as their inclusivity.
|
|
11
|
-
* @param min - The minimum bound of the interval.
|
|
12
|
-
* @param max - The maximum bound of the interval.
|
|
13
|
-
*/
|
|
14
|
-
constructor(min, max) {
|
|
15
|
-
this.min = min;
|
|
16
|
-
this.max = max;
|
|
17
|
-
(0, assert_1.guard)(min.value <= max.value, () => `The interval ${this.toString()} has a minimum that is greater than its maximum`);
|
|
18
|
-
(0, assert_1.guard)(min.value !== max.value || (min.inclusive === max.inclusive), `The bound ${min.value} cannot be in- and exclusive at the same time`);
|
|
19
|
-
}
|
|
20
|
-
toString() {
|
|
21
|
-
return `${this.min.inclusive ? '[' : '('}${this.min.value}, ${this.max.value}${this.max.inclusive ? ']' : ')'}`;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.Interval = Interval;
|
|
25
|
-
/**
|
|
26
|
-
* A domain represents a set of intervals describing a range of possible values a variable may hold.
|
|
27
|
-
* In the future we may want to extend this to support more complex types.
|
|
28
|
-
*/
|
|
29
|
-
class Domain {
|
|
30
|
-
/** set of intervals to hold */
|
|
31
|
-
_intervals;
|
|
32
|
-
constructor(intervals = []) {
|
|
33
|
-
this._intervals = new Set(unifyOverlappingIntervals(intervals));
|
|
34
|
-
}
|
|
35
|
-
static bottom() {
|
|
36
|
-
return new Domain();
|
|
37
|
-
}
|
|
38
|
-
static fromIntervals(intervals) {
|
|
39
|
-
return new Domain(Array.from(intervals));
|
|
40
|
-
}
|
|
41
|
-
static fromScalar(n) {
|
|
42
|
-
return new Domain([new Interval({ value: n, inclusive: true }, { value: n, inclusive: true })]);
|
|
43
|
-
}
|
|
44
|
-
get intervals() {
|
|
45
|
-
return this._intervals;
|
|
46
|
-
}
|
|
47
|
-
set intervals(intervals) {
|
|
48
|
-
this._intervals.clear();
|
|
49
|
-
for (const interval of intervals) {
|
|
50
|
-
this._intervals.add(interval);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
addInterval(interval) {
|
|
54
|
-
this.intervals = unifyOverlappingIntervals([...this.intervals, interval]);
|
|
55
|
-
}
|
|
56
|
-
toString() {
|
|
57
|
-
return `{${Array.from(this.intervals).join(', ')}}`;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
exports.Domain = Domain;
|
|
61
|
-
function compareIntervals(compareType, interval1, interval2) {
|
|
62
|
-
const diff = interval1.value - interval2.value;
|
|
63
|
-
if (diff !== 0 || compareType === 2 /* CompareType.IgnoreInclusivity */) {
|
|
64
|
-
return diff;
|
|
65
|
-
}
|
|
66
|
-
switch (compareType) {
|
|
67
|
-
case 0 /* CompareType.Min */:
|
|
68
|
-
return Number(!interval1.inclusive) - Number(!interval2.inclusive);
|
|
69
|
-
case 1 /* CompareType.Max */:
|
|
70
|
-
return Number(interval1.inclusive) - Number(interval2.inclusive);
|
|
71
|
-
default:
|
|
72
|
-
(0, assert_1.assertUnreachable)(compareType);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function compareIntervalsByTheirMinimum(interval1, interval2) {
|
|
76
|
-
return compareIntervals(0 /* CompareType.Min */, interval1.min, interval2.min);
|
|
77
|
-
}
|
|
78
|
-
function compareIntervalsByTheirMaximum(interval1, interval2) {
|
|
79
|
-
return compareIntervals(1 /* CompareType.Max */, interval1.max, interval2.max);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Returns true if the given intervals overlap, checking for inclusivity.
|
|
83
|
-
*/
|
|
84
|
-
function doIntervalsOverlap(interval1, interval2) {
|
|
85
|
-
const diff1 = compareIntervals(2 /* CompareType.IgnoreInclusivity */, interval1.max, interval2.min);
|
|
86
|
-
const diff2 = compareIntervals(2 /* CompareType.IgnoreInclusivity */, interval2.max, interval1.min);
|
|
87
|
-
// If one interval ends before the other starts, they don't overlap
|
|
88
|
-
if (diff1 < 0 || diff2 < 0) {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
// If their end and start are equal, they only overlap if both are inclusive
|
|
92
|
-
if (diff1 === 0) {
|
|
93
|
-
return interval1.max.inclusive && interval2.min.inclusive;
|
|
94
|
-
}
|
|
95
|
-
if (diff2 === 0) {
|
|
96
|
-
return interval2.max.inclusive && interval1.min.inclusive;
|
|
97
|
-
}
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
exports.doIntervalsOverlap = doIntervalsOverlap;
|
|
101
|
-
/**
|
|
102
|
-
* Unifies the given domains by creating a new domain that contains all values from all given domains.
|
|
103
|
-
*/
|
|
104
|
-
function unifyDomains(domains) {
|
|
105
|
-
const unifiedIntervals = unifyOverlappingIntervals(domains.flatMap(domain => Array.from(domain.intervals)));
|
|
106
|
-
return Domain.fromIntervals(unifiedIntervals);
|
|
107
|
-
}
|
|
108
|
-
exports.unifyDomains = unifyDomains;
|
|
109
|
-
/**
|
|
110
|
-
* Unify all intervals which overlap with each other to one.
|
|
111
|
-
*/
|
|
112
|
-
function unifyOverlappingIntervals(intervals) {
|
|
113
|
-
if (intervals.length === 0) {
|
|
114
|
-
return [];
|
|
115
|
-
}
|
|
116
|
-
const sortedIntervals = [...intervals].sort(compareIntervalsByTheirMinimum);
|
|
117
|
-
const unifiedIntervals = [];
|
|
118
|
-
let currentInterval = sortedIntervals[0];
|
|
119
|
-
for (const nextInterval of sortedIntervals) {
|
|
120
|
-
if (doIntervalsOverlap(currentInterval, nextInterval)) {
|
|
121
|
-
const intervalWithEarlierStart = compareIntervalsByTheirMinimum(currentInterval, nextInterval) < 0 ? currentInterval : nextInterval;
|
|
122
|
-
const intervalWithLaterEnd = compareIntervalsByTheirMaximum(currentInterval, nextInterval) > 0 ? currentInterval : nextInterval;
|
|
123
|
-
currentInterval = new Interval(intervalWithEarlierStart.min, intervalWithLaterEnd.max);
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
unifiedIntervals.push(currentInterval);
|
|
127
|
-
currentInterval = nextInterval;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
unifiedIntervals.push(currentInterval);
|
|
131
|
-
return unifiedIntervals;
|
|
132
|
-
}
|
|
133
|
-
exports.unifyOverlappingIntervals = unifyOverlappingIntervals;
|
|
134
|
-
/**
|
|
135
|
-
* Returns domain1 + domain2, mapping the inclusivity.
|
|
136
|
-
*
|
|
137
|
-
* @see subtractDomains
|
|
138
|
-
*/
|
|
139
|
-
function addDomains(domain1, domain2) {
|
|
140
|
-
const intervals = new Set();
|
|
141
|
-
for (const interval1 of domain1.intervals) {
|
|
142
|
-
for (const interval2 of domain2.intervals) {
|
|
143
|
-
intervals.add(new Interval({
|
|
144
|
-
value: interval1.min.value + interval2.min.value,
|
|
145
|
-
inclusive: interval1.min.inclusive && interval2.min.inclusive
|
|
146
|
-
}, {
|
|
147
|
-
value: interval1.max.value + interval2.max.value,
|
|
148
|
-
inclusive: interval1.max.inclusive && interval2.max.inclusive
|
|
149
|
-
}));
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return Domain.fromIntervals(intervals);
|
|
153
|
-
}
|
|
154
|
-
exports.addDomains = addDomains;
|
|
155
|
-
/**
|
|
156
|
-
* Returns domain1 - domain2, mapping the inclusivity.
|
|
157
|
-
*
|
|
158
|
-
* @see addDomains
|
|
159
|
-
*/
|
|
160
|
-
function subtractDomains(domain1, domain2) {
|
|
161
|
-
const intervals = new Set();
|
|
162
|
-
for (const interval1 of domain1.intervals) {
|
|
163
|
-
for (const interval2 of domain2.intervals) {
|
|
164
|
-
intervals.add(new Interval({
|
|
165
|
-
value: interval1.min.value - interval2.max.value,
|
|
166
|
-
inclusive: interval1.min.inclusive && interval2.max.inclusive
|
|
167
|
-
}, {
|
|
168
|
-
value: interval1.max.value - interval2.min.value,
|
|
169
|
-
inclusive: interval1.max.inclusive && interval2.min.inclusive
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return Domain.fromIntervals(intervals);
|
|
174
|
-
}
|
|
175
|
-
exports.subtractDomains = subtractDomains;
|
|
176
|
-
//# sourceMappingURL=domain.js.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { Handler } from '../handler';
|
|
2
|
-
import type { AINode } from '../../processor';
|
|
3
|
-
import type { ParentInformation } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
|
-
import type { RBinaryOp } from '../../../r-bridge/lang-4.x/ast/model/nodes/r-binary-op';
|
|
5
|
-
export type BinaryOpProcessor = (lhs: AINode, rhs: AINode, node: RBinaryOp<ParentInformation>) => AINode;
|
|
6
|
-
export declare class BinOp implements Handler<AINode> {
|
|
7
|
-
readonly node: RBinaryOp<ParentInformation>;
|
|
8
|
-
lhs: AINode | undefined;
|
|
9
|
-
rhs: AINode | undefined;
|
|
10
|
-
constructor(node: RBinaryOp<ParentInformation>);
|
|
11
|
-
getName(): string;
|
|
12
|
-
enter(): void;
|
|
13
|
-
exit(): AINode;
|
|
14
|
-
next(node: AINode): void;
|
|
15
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BinOp = void 0;
|
|
4
|
-
const processor_1 = require("../../processor");
|
|
5
|
-
const assert_1 = require("../../../util/assert");
|
|
6
|
-
const operators_1 = require("./operators");
|
|
7
|
-
class BinOp {
|
|
8
|
-
node;
|
|
9
|
-
lhs;
|
|
10
|
-
rhs;
|
|
11
|
-
constructor(node) {
|
|
12
|
-
this.node = node;
|
|
13
|
-
}
|
|
14
|
-
getName() {
|
|
15
|
-
return `Bin Op (${this.node.operator})`;
|
|
16
|
-
}
|
|
17
|
-
enter() {
|
|
18
|
-
processor_1.aiLogger.trace(`Entered ${this.getName()}`);
|
|
19
|
-
}
|
|
20
|
-
exit() {
|
|
21
|
-
processor_1.aiLogger.trace(`Exited ${this.getName()}`);
|
|
22
|
-
(0, assert_1.guard)(this.lhs !== undefined, `No LHS found for assignment ${this.node.info.id}`);
|
|
23
|
-
(0, assert_1.guard)(this.rhs !== undefined, `No RHS found for assignment ${this.node.info.id}`);
|
|
24
|
-
const processor = operators_1.operators[this.node.operator];
|
|
25
|
-
(0, assert_1.guard)(processor !== undefined, `No processor found for binary operator ${this.node.operator}`);
|
|
26
|
-
return processor(this.lhs, this.rhs, this.node);
|
|
27
|
-
}
|
|
28
|
-
next(node) {
|
|
29
|
-
processor_1.aiLogger.trace(`${this.getName()} received`);
|
|
30
|
-
if (this.lhs === undefined) {
|
|
31
|
-
this.lhs = node;
|
|
32
|
-
}
|
|
33
|
-
else if (this.rhs === undefined) {
|
|
34
|
-
this.rhs = node;
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
(0, assert_1.guard)(false, `BinOp ${this.node.info.id} already has both LHS and RHS`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
exports.BinOp = BinOp;
|
|
42
|
-
//# sourceMappingURL=binop.js.map
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.operators = void 0;
|
|
4
|
-
const domain_1 = require("../../domain");
|
|
5
|
-
exports.operators = {
|
|
6
|
-
'<-': (lhs, rhs, node) => {
|
|
7
|
-
return {
|
|
8
|
-
id: lhs.id,
|
|
9
|
-
domain: rhs.domain,
|
|
10
|
-
astNode: node.lhs,
|
|
11
|
-
};
|
|
12
|
-
},
|
|
13
|
-
'+': (lhs, rhs, node) => {
|
|
14
|
-
return {
|
|
15
|
-
id: lhs.id,
|
|
16
|
-
domain: (0, domain_1.addDomains)(lhs.domain, rhs.domain),
|
|
17
|
-
astNode: node,
|
|
18
|
-
};
|
|
19
|
-
},
|
|
20
|
-
'-': (lhs, rhs, node) => {
|
|
21
|
-
return {
|
|
22
|
-
id: lhs.id,
|
|
23
|
-
domain: (0, domain_1.subtractDomains)(lhs.domain, rhs.domain),
|
|
24
|
-
astNode: node,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
//# sourceMappingURL=operators.js.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { DataflowInformation } from '../dataflow/info';
|
|
2
|
-
import { Domain } from './domain';
|
|
3
|
-
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
4
|
-
import type { NormalizedAst, ParentInformation, RNodeWithParent } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
|
-
export declare const aiLogger: import("tslog").Logger<import("tslog").ILogObj>;
|
|
6
|
-
export interface AINode {
|
|
7
|
-
readonly id: NodeId;
|
|
8
|
-
readonly domain: Domain;
|
|
9
|
-
readonly astNode: RNodeWithParent<ParentInformation>;
|
|
10
|
-
}
|
|
11
|
-
export declare function runAbstractInterpretation(ast: NormalizedAst, dfg: DataflowInformation): DataflowInformation;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runAbstractInterpretation = exports.aiLogger = void 0;
|
|
4
|
-
const cfg_1 = require("../util/cfg/cfg");
|
|
5
|
-
const visitor_1 = require("../util/cfg/visitor");
|
|
6
|
-
const assert_1 = require("../util/assert");
|
|
7
|
-
const binop_1 = require("./handler/binop/binop");
|
|
8
|
-
const domain_1 = require("./domain");
|
|
9
|
-
const log_1 = require("../util/log");
|
|
10
|
-
const edge_1 = require("../dataflow/graph/edge");
|
|
11
|
-
exports.aiLogger = log_1.log.getSubLogger({ name: 'abstract-interpretation' });
|
|
12
|
-
class Stack {
|
|
13
|
-
backingStore = [];
|
|
14
|
-
size() {
|
|
15
|
-
return this.backingStore.length;
|
|
16
|
-
}
|
|
17
|
-
peek() {
|
|
18
|
-
return this.backingStore[this.size() - 1];
|
|
19
|
-
}
|
|
20
|
-
pop() {
|
|
21
|
-
return this.backingStore.pop();
|
|
22
|
-
}
|
|
23
|
-
push(item) {
|
|
24
|
-
this.backingStore.push(item);
|
|
25
|
-
return item;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function getDomainOfDfgChild(node, dfg, nodeMap) {
|
|
29
|
-
const dfgNode = dfg.graph.get(node);
|
|
30
|
-
(0, assert_1.guard)(dfgNode !== undefined, `No DFG-Node found with ID ${node}`);
|
|
31
|
-
const [_, children] = dfgNode;
|
|
32
|
-
const ids = Array.from(children.entries())
|
|
33
|
-
.filter(([_, edge]) => (0, edge_1.edgeIncludesType)(edge.types, 1 /* EdgeType.Reads */))
|
|
34
|
-
.map(([id, _]) => id);
|
|
35
|
-
const domains = [];
|
|
36
|
-
for (const id of ids) {
|
|
37
|
-
const domain = nodeMap.get(id)?.domain;
|
|
38
|
-
(0, assert_1.guard)(domain !== undefined, `No domain found for ID ${id}`);
|
|
39
|
-
domains.push(domain);
|
|
40
|
-
}
|
|
41
|
-
return (0, domain_1.unifyDomains)(domains);
|
|
42
|
-
}
|
|
43
|
-
function runAbstractInterpretation(ast, dfg) {
|
|
44
|
-
const cfg = (0, cfg_1.extractCFG)(ast);
|
|
45
|
-
const operationStack = new Stack();
|
|
46
|
-
const nodeMap = new Map();
|
|
47
|
-
(0, visitor_1.visitCfg)(cfg, (node, _) => {
|
|
48
|
-
const astNode = ast.idMap.get(node.id);
|
|
49
|
-
if (astNode?.type === "RBinaryOp" /* RType.BinaryOp */) {
|
|
50
|
-
operationStack.push(new binop_1.BinOp(astNode)).enter();
|
|
51
|
-
}
|
|
52
|
-
else if (astNode?.type === "RSymbol" /* RType.Symbol */) {
|
|
53
|
-
operationStack.peek()?.next({
|
|
54
|
-
id: astNode.info.id,
|
|
55
|
-
domain: getDomainOfDfgChild(node.id, dfg, nodeMap),
|
|
56
|
-
astNode: astNode,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
else if (astNode?.type === "RNumber" /* RType.Number */) {
|
|
60
|
-
const num = astNode.content.num;
|
|
61
|
-
operationStack.peek()?.next({
|
|
62
|
-
id: astNode.info.id,
|
|
63
|
-
domain: domain_1.Domain.fromScalar(num),
|
|
64
|
-
astNode: astNode,
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
else if (node.type === "end-marker" /* CfgVertexType.EndMarker */) {
|
|
68
|
-
const operation = operationStack.pop();
|
|
69
|
-
if (operation === undefined) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const operationResult = operation.exit();
|
|
73
|
-
(0, assert_1.guard)(!nodeMap.has(operationResult.id), `Domain for ID ${operationResult.id} already exists`);
|
|
74
|
-
nodeMap.set(operationResult.id, operationResult);
|
|
75
|
-
operationStack.peek()?.next(operationResult);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
exports.aiLogger.warn(`Unknown node type ${node.type}`);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
return dfg;
|
|
82
|
-
}
|
|
83
|
-
exports.runAbstractInterpretation = runAbstractInterpretation;
|
|
84
|
-
//# sourceMappingURL=processor.js.map
|