@eagleoutice/flowr 2.0.20 → 2.0.22
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/dataflow/environments/built-in.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +36 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
- package/package.json +1 -1
- package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/processing/decorate.js +40 -30
- package/slicing/static/static-slicer.d.ts +1 -1
- package/slicing/static/static-slicer.js +6 -6
- package/util/version.js +1 -1
|
@@ -109,9 +109,10 @@ registerBuiltInConstant(true, 'T', true);
|
|
|
109
109
|
registerBuiltInConstant(true, 'FALSE', false);
|
|
110
110
|
registerBuiltInConstant(true, 'F', false);
|
|
111
111
|
registerSimpleFunctions('~', '+', '-', '*', '/', '^', '!', '?', '**', '==', '!=', '>', '<', '>=', '<=', '%%', '%/%', '%*%', '%in%', ':', 'list', 'c', 'rep', 'seq', 'seq_len', 'seq_along', 'seq.int', 'gsub', 'which', 'class', 'dimnames', 'min', 'max', 'intersect', 'subset', 'match', 'sqrt', 'abs', 'round', 'floor', 'ceiling', 'signif', 'trunc', 'log', 'log10', 'log2', 'sum', 'mean', 'unique', 'paste', 'paste0', 'read.csv', 'stop', 'is.null', 'plot', 'numeric', 'as.character', 'as.integer', 'as.logical', 'as.numeric', 'as.matrix', 'do.call', 'rbind', 'nrow', 'ncol', 'tryCatch', 'expression', 'factor', 'missing', 'as.data.frame', 'data.frame', 'na.omit', 'rownames', 'names', 'order', 'length', 'any', 'dim', 'matrix', 'cbind', 'nchar', 't');
|
|
112
|
-
registerBuiltInFunctions(false, ['
|
|
112
|
+
registerBuiltInFunctions(false, ['mapply', 'Mapply'], built_in_apply_1.processApply, { indexOfFunction: 0, nameOfFunctionArgument: 'FUN' });
|
|
113
|
+
registerBuiltInFunctions(false, ['lapply', 'sapply', 'vapply'], built_in_apply_1.processApply, { indexOfFunction: 1, nameOfFunctionArgument: 'FUN' });
|
|
113
114
|
/* functool wrappers */
|
|
114
|
-
registerBuiltInFunctions(false, ['Lapply', 'Sapply', 'Vapply'
|
|
115
|
+
registerBuiltInFunctions(false, ['Lapply', 'Sapply', 'Vapply'], built_in_apply_1.processApply, { indexOfFunction: 1, nameOfFunctionArgument: 'FUN' });
|
|
115
116
|
registerBuiltInFunctions(false, ['apply', 'tapply', 'Tapply'], built_in_apply_1.processApply, { indexOfFunction: 2, nameOfFunctionArgument: 'FUN' });
|
|
116
117
|
registerBuiltInFunctions(false, ['print'], defaultBuiltInProcessor, { returnsNthArgument: 0, forceArgs: 'all' });
|
|
117
118
|
registerBuiltInFunctions(true, ['('], defaultBuiltInProcessor, { returnsNthArgument: 0 });
|
|
@@ -143,7 +144,7 @@ registerBuiltInFunctions(true, ['for'], built_in_for_loop_1.processForLoop, {});
|
|
|
143
144
|
registerBuiltInFunctions(true, ['repeat'], built_in_repeat_loop_1.processRepeatLoop, {});
|
|
144
145
|
registerBuiltInFunctions(true, ['while'], built_in_while_loop_1.processWhileLoop, {});
|
|
145
146
|
registerBuiltInFunctions(false, ['options'], defaultBuiltInProcessor, { hasUnknownSideEffects: true, forceArgs: 'all' });
|
|
146
|
-
registerBuiltInFunctions(false, ['on.exit', 'sys.on.exit'], defaultBuiltInProcessor, { hasUnknownSideEffects: true });
|
|
147
|
+
registerBuiltInFunctions(false, ['on.exit', 'sys.on.exit', 'par'], defaultBuiltInProcessor, { hasUnknownSideEffects: true });
|
|
147
148
|
/* library and require is handled above */
|
|
148
149
|
registerBuiltInFunctions(false, ['requireNamespace', 'loadNamespace', 'attachNamespace', 'asNamespace'], defaultBuiltInProcessor, { hasUnknownSideEffects: true });
|
|
149
150
|
/* downloader and installer functions (R, devtools, BiocManager) */
|
|
@@ -25,6 +25,18 @@ function toReplacementSymbol(target, prefix, superAssignment) {
|
|
|
25
25
|
function getEffectiveOrder(config, args) {
|
|
26
26
|
return config.swapSourceAndTarget ? [args[1], args[0]] : args;
|
|
27
27
|
}
|
|
28
|
+
function findRootAccess(node) {
|
|
29
|
+
let current = node;
|
|
30
|
+
while (current.type === "RAccess" /* RType.Access */) {
|
|
31
|
+
current = current.accessed;
|
|
32
|
+
}
|
|
33
|
+
if (current.type === "RSymbol" /* RType.Symbol */) {
|
|
34
|
+
return current;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
28
40
|
/**
|
|
29
41
|
* Processes an assignment, i.e., `<target> <- <source>`.
|
|
30
42
|
* Handling it as a function call \`<-\` `(<target>, <source>)`.
|
|
@@ -64,6 +76,29 @@ args, rootId, data, config) {
|
|
|
64
76
|
const replacement = toReplacementSymbol(target, target.operator, config.superAssignment ?? false);
|
|
65
77
|
return (0, process_named_call_1.processAsNamedCall)(replacement, data, replacement.content, [(0, make_argument_1.toUnnamedArgument)(target.accessed, data.completeAst.idMap), ...target.access, source]);
|
|
66
78
|
}
|
|
79
|
+
else if (type === "RAccess" /* RType.Access */) {
|
|
80
|
+
const rootArg = findRootAccess(target);
|
|
81
|
+
if (rootArg) {
|
|
82
|
+
const res = (0, known_call_handling_1.processKnownFunctionCall)({
|
|
83
|
+
name,
|
|
84
|
+
args: [rootArg, source],
|
|
85
|
+
rootId,
|
|
86
|
+
data,
|
|
87
|
+
reverseOrder: !config.swapSourceAndTarget,
|
|
88
|
+
forceArgs: config.forceArgs
|
|
89
|
+
});
|
|
90
|
+
return processAssignmentToSymbol({
|
|
91
|
+
...config,
|
|
92
|
+
nameOfAssignmentFunction: name.content,
|
|
93
|
+
source,
|
|
94
|
+
target: rootArg,
|
|
95
|
+
args: getEffectiveOrder(config, res.processedArguments),
|
|
96
|
+
rootId,
|
|
97
|
+
data,
|
|
98
|
+
information: res.information,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
67
102
|
else if (type === "RString" /* RType.String */) {
|
|
68
103
|
return processAssignmentToString(target, args, name, rootId, data, config, source);
|
|
69
104
|
}
|
|
@@ -79,7 +114,7 @@ function extractSourceAndTarget(args, name) {
|
|
|
79
114
|
return { source, target };
|
|
80
115
|
}
|
|
81
116
|
function produceWrittenNodes(rootId, target, isFunctionDef, data, makeMaybe) {
|
|
82
|
-
return target.in.map(ref => ({
|
|
117
|
+
return [...target.in, ...target.unknownReferences].map(ref => ({
|
|
83
118
|
...ref,
|
|
84
119
|
kind: isFunctionDef ? 'function' : 'variable',
|
|
85
120
|
definedAt: rootId,
|
|
@@ -63,7 +63,7 @@ function processForLoop(name, args, rootId, data) {
|
|
|
63
63
|
return {
|
|
64
64
|
unknownReferences: [],
|
|
65
65
|
// we only want those not bound by a local variable
|
|
66
|
-
in: [{ nodeId: rootId, name: name.content, controlDependencies: originalDependency }, ...variable.in, ...[...nameIdShares.values()].flat()],
|
|
66
|
+
in: [{ nodeId: rootId, name: name.content, controlDependencies: originalDependency }, ...variable.in, ...vector.in, ...vector.unknownReferences, ...[...nameIdShares.values()].flat()],
|
|
67
67
|
out: outgoing,
|
|
68
68
|
graph: nextGraph,
|
|
69
69
|
entryPoint: name.info.id,
|
package/package.json
CHANGED
|
@@ -44,11 +44,11 @@ export declare function deterministicLocationIdGenerator<OtherInfo>(start?: numb
|
|
|
44
44
|
export interface ParentContextInfo extends MergeableRecord {
|
|
45
45
|
role: RoleInParent;
|
|
46
46
|
/**
|
|
47
|
-
* The
|
|
47
|
+
* The nesting of the node in the AST
|
|
48
48
|
*
|
|
49
|
-
* The root node has a
|
|
49
|
+
* The root node has a nesting of 0, nested function calls, loops etc. will increase the nesting
|
|
50
50
|
*/
|
|
51
|
-
|
|
51
|
+
nesting: number;
|
|
52
52
|
/**
|
|
53
53
|
* 0-based index of the child in the parent (code semantics, e.g., for an if-then-else, the condition will be 0, the then-case will be 1, ...)
|
|
54
54
|
*
|
|
@@ -60,6 +60,9 @@ const defaultParentContext = {
|
|
|
60
60
|
role: "root" /* RoleInParent.Root */,
|
|
61
61
|
index: 0
|
|
62
62
|
};
|
|
63
|
+
const nestForElement = new Set([
|
|
64
|
+
"RFunctionDefinition" /* RType.FunctionDefinition */, "RForLoop" /* RType.ForLoop */, "RWhileLoop" /* RType.WhileLoop */, "RRepeatLoop" /* RType.RepeatLoop */, "RIfThenElse" /* RType.IfThenElse */,
|
|
65
|
+
]);
|
|
63
66
|
/**
|
|
64
67
|
* Covert the given AST into a doubly linked tree while assigning ids (so it stays serializable).
|
|
65
68
|
*
|
|
@@ -77,9 +80,16 @@ function decorateAst(ast, getId = deterministicCountingIdGenerator(0)) {
|
|
|
77
80
|
const foldLeaf = createFoldForLeaf(info);
|
|
78
81
|
const foldBinaryOp = createFoldForBinaryOp(info);
|
|
79
82
|
const unaryOp = createFoldForUnaryOp(info);
|
|
80
|
-
/* we pass down the depth */
|
|
81
|
-
const decoratedAst = (0, stateful_fold_1.foldAstStateful)(ast,
|
|
82
|
-
down: (
|
|
83
|
+
/* we pass down the nesting depth */
|
|
84
|
+
const decoratedAst = (0, stateful_fold_1.foldAstStateful)(ast, 0, {
|
|
85
|
+
down: (n, nesting) => {
|
|
86
|
+
if (nestForElement.has(n.type)) {
|
|
87
|
+
return nesting + 1;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
return nesting;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
83
93
|
foldNumber: foldLeaf,
|
|
84
94
|
foldString: foldLeaf,
|
|
85
95
|
foldLogical: foldLeaf,
|
|
@@ -117,7 +127,7 @@ function decorateAst(ast, getId = deterministicCountingIdGenerator(0)) {
|
|
|
117
127
|
}
|
|
118
128
|
exports.decorateAst = decorateAst;
|
|
119
129
|
function createFoldForLeaf(info) {
|
|
120
|
-
return (data,
|
|
130
|
+
return (data, nesting) => {
|
|
121
131
|
const id = info.getId(data);
|
|
122
132
|
const decorated = {
|
|
123
133
|
...data,
|
|
@@ -126,7 +136,7 @@ function createFoldForLeaf(info) {
|
|
|
126
136
|
id,
|
|
127
137
|
parent: undefined,
|
|
128
138
|
...defaultParentContext,
|
|
129
|
-
|
|
139
|
+
nesting
|
|
130
140
|
}
|
|
131
141
|
};
|
|
132
142
|
info.idMap.set(id, decorated);
|
|
@@ -134,9 +144,9 @@ function createFoldForLeaf(info) {
|
|
|
134
144
|
};
|
|
135
145
|
}
|
|
136
146
|
function createFoldForBinaryOp(info) {
|
|
137
|
-
return (data, lhs, rhs,
|
|
147
|
+
return (data, lhs, rhs, nesting) => {
|
|
138
148
|
const id = info.getId(data);
|
|
139
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
149
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, lhs, rhs };
|
|
140
150
|
info.idMap.set(id, decorated);
|
|
141
151
|
const lhsInfo = lhs.info;
|
|
142
152
|
lhsInfo.parent = id;
|
|
@@ -155,9 +165,9 @@ function createFoldForBinaryOp(info) {
|
|
|
155
165
|
};
|
|
156
166
|
}
|
|
157
167
|
function createFoldForUnaryOp(info) {
|
|
158
|
-
return (data, operand,
|
|
168
|
+
return (data, operand, nesting) => {
|
|
159
169
|
const id = info.getId(data);
|
|
160
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
170
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, operand };
|
|
161
171
|
info.idMap.set(id, decorated);
|
|
162
172
|
const opInfo = operand.info;
|
|
163
173
|
opInfo.parent = id;
|
|
@@ -166,9 +176,9 @@ function createFoldForUnaryOp(info) {
|
|
|
166
176
|
};
|
|
167
177
|
}
|
|
168
178
|
function createFoldForAccess(info) {
|
|
169
|
-
return (data, accessed, access,
|
|
179
|
+
return (data, accessed, access, nesting) => {
|
|
170
180
|
const id = info.getId(data);
|
|
171
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
181
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, accessed, access };
|
|
172
182
|
info.idMap.set(id, decorated);
|
|
173
183
|
const accessedInfo = accessed.info;
|
|
174
184
|
accessedInfo.parent = id;
|
|
@@ -189,9 +199,9 @@ function createFoldForAccess(info) {
|
|
|
189
199
|
};
|
|
190
200
|
}
|
|
191
201
|
function createFoldForForLoop(info) {
|
|
192
|
-
return (data, variable, vector, body,
|
|
202
|
+
return (data, variable, vector, body, nesting) => {
|
|
193
203
|
const id = info.getId(data);
|
|
194
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
204
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, variable, vector, body };
|
|
195
205
|
info.idMap.set(id, decorated);
|
|
196
206
|
const varInfo = variable.info;
|
|
197
207
|
varInfo.parent = id;
|
|
@@ -208,9 +218,9 @@ function createFoldForForLoop(info) {
|
|
|
208
218
|
};
|
|
209
219
|
}
|
|
210
220
|
function createFoldForRepeatLoop(info) {
|
|
211
|
-
return (data, body,
|
|
221
|
+
return (data, body, nesting) => {
|
|
212
222
|
const id = info.getId(data);
|
|
213
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
223
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, body };
|
|
214
224
|
info.idMap.set(id, decorated);
|
|
215
225
|
const bodyInfo = body.info;
|
|
216
226
|
bodyInfo.parent = id;
|
|
@@ -219,9 +229,9 @@ function createFoldForRepeatLoop(info) {
|
|
|
219
229
|
};
|
|
220
230
|
}
|
|
221
231
|
function createFoldForWhileLoop(info) {
|
|
222
|
-
return (data, condition, body,
|
|
232
|
+
return (data, condition, body, nesting) => {
|
|
223
233
|
const id = info.getId(data);
|
|
224
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
234
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, condition, body };
|
|
225
235
|
info.idMap.set(id, decorated);
|
|
226
236
|
const condInfo = condition.info;
|
|
227
237
|
condInfo.parent = id;
|
|
@@ -234,9 +244,9 @@ function createFoldForWhileLoop(info) {
|
|
|
234
244
|
};
|
|
235
245
|
}
|
|
236
246
|
function createFoldForIfThenElse(info) {
|
|
237
|
-
return (data, condition, then, otherwise,
|
|
247
|
+
return (data, condition, then, otherwise, nesting) => {
|
|
238
248
|
const id = info.getId(data);
|
|
239
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
249
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, condition, then, otherwise };
|
|
240
250
|
info.idMap.set(id, decorated);
|
|
241
251
|
const condInfo = condition.info;
|
|
242
252
|
condInfo.parent = id;
|
|
@@ -255,9 +265,9 @@ function createFoldForIfThenElse(info) {
|
|
|
255
265
|
};
|
|
256
266
|
}
|
|
257
267
|
function createFoldForExprList(info) {
|
|
258
|
-
return (data, grouping, children,
|
|
268
|
+
return (data, grouping, children, nesting) => {
|
|
259
269
|
const id = info.getId(data);
|
|
260
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
270
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, grouping, children };
|
|
261
271
|
info.idMap.set(id, decorated);
|
|
262
272
|
let i = 0;
|
|
263
273
|
for (const child of children) {
|
|
@@ -270,14 +280,14 @@ function createFoldForExprList(info) {
|
|
|
270
280
|
};
|
|
271
281
|
}
|
|
272
282
|
function createFoldForFunctionCall(info) {
|
|
273
|
-
return (data, functionName, args,
|
|
283
|
+
return (data, functionName, args, nesting) => {
|
|
274
284
|
const id = info.getId(data);
|
|
275
285
|
let decorated;
|
|
276
286
|
if (data.named) {
|
|
277
|
-
decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
287
|
+
decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, functionName, arguments: args };
|
|
278
288
|
}
|
|
279
289
|
else {
|
|
280
|
-
decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
290
|
+
decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, calledFunction: functionName, arguments: args };
|
|
281
291
|
}
|
|
282
292
|
info.idMap.set(id, decorated);
|
|
283
293
|
const funcInfo = functionName.info;
|
|
@@ -297,9 +307,9 @@ function createFoldForFunctionCall(info) {
|
|
|
297
307
|
};
|
|
298
308
|
}
|
|
299
309
|
function createFoldForFunctionDefinition(info) {
|
|
300
|
-
return (data, params, body,
|
|
310
|
+
return (data, params, body, nesting) => {
|
|
301
311
|
const id = info.getId(data);
|
|
302
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
312
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, parameters: params, body };
|
|
303
313
|
info.idMap.set(id, decorated);
|
|
304
314
|
let idx = 0;
|
|
305
315
|
for (const param of params) {
|
|
@@ -316,9 +326,9 @@ function createFoldForFunctionDefinition(info) {
|
|
|
316
326
|
};
|
|
317
327
|
}
|
|
318
328
|
function createFoldForFunctionParameter(info) {
|
|
319
|
-
return (data, name, defaultValue,
|
|
329
|
+
return (data, name, defaultValue, nesting) => {
|
|
320
330
|
const id = info.getId(data);
|
|
321
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
331
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, name, defaultValue };
|
|
322
332
|
info.idMap.set(id, decorated);
|
|
323
333
|
const nameInfo = name.info;
|
|
324
334
|
nameInfo.parent = id;
|
|
@@ -333,9 +343,9 @@ function createFoldForFunctionParameter(info) {
|
|
|
333
343
|
};
|
|
334
344
|
}
|
|
335
345
|
function createFoldForFunctionArgument(info) {
|
|
336
|
-
return (data, name, value,
|
|
346
|
+
return (data, name, value, nesting) => {
|
|
337
347
|
const id = info.getId(data);
|
|
338
|
-
const decorated = { ...data, info: { ...data.info, id, parent: undefined,
|
|
348
|
+
const decorated = { ...data, info: { ...data.info, id, parent: undefined, nesting }, name, value };
|
|
339
349
|
info.idMap.set(id, decorated);
|
|
340
350
|
let idx = 0;
|
|
341
351
|
if (name) {
|
|
@@ -9,7 +9,7 @@ export declare const slicerLogger: import("tslog").Logger<import("tslog").ILogOb
|
|
|
9
9
|
* The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
|
|
10
10
|
*
|
|
11
11
|
* @param graph - The dataflow graph to conduct the slicing on.
|
|
12
|
-
* @param ast - The normalized AST of the code (used to get static
|
|
12
|
+
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
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,7 +16,7 @@ exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
|
|
|
16
16
|
* The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
|
|
17
17
|
*
|
|
18
18
|
* @param graph - The dataflow graph to conduct the slicing on.
|
|
19
|
-
* @param ast - The normalized AST of the code (used to get static
|
|
19
|
+
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
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
|
*/
|
|
@@ -25,7 +25,7 @@ function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
|
25
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
|
-
let
|
|
28
|
+
let minNesting = Number.MAX_SAFE_INTEGER;
|
|
29
29
|
const sliceSeedIds = new Set();
|
|
30
30
|
// every node ships the call environment which registers the calling environment
|
|
31
31
|
{
|
|
@@ -33,8 +33,8 @@ function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
|
33
33
|
const basePrint = (0, fingerprint_1.envFingerprint)(emptyEnv);
|
|
34
34
|
for (const { id: startId } of decodedCriteria) {
|
|
35
35
|
queue.add(startId, emptyEnv, basePrint, false);
|
|
36
|
-
// retrieve the minimum
|
|
37
|
-
|
|
36
|
+
// retrieve the minimum nesting of all nodes to only add control dependencies if they are "part" of the current execution
|
|
37
|
+
minNesting = Math.min(minNesting, idMap.get(startId)?.info.nesting ?? minNesting);
|
|
38
38
|
sliceSeedIds.add(startId);
|
|
39
39
|
}
|
|
40
40
|
/* additionally,
|
|
@@ -54,11 +54,11 @@ function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
|
54
54
|
continue;
|
|
55
55
|
}
|
|
56
56
|
const [currentVertex, currentEdges] = currentInfo;
|
|
57
|
-
// we only add control dependencies iff 1) we are in different function call or 2) they have, at least, the same
|
|
57
|
+
// we only add control dependencies iff 1) we are in different function call or 2) they have, at least, the same nesting as the slicing seed
|
|
58
58
|
if (currentVertex.controlDependencies && currentVertex.controlDependencies.length > 0) {
|
|
59
59
|
const topLevel = graph.isRoot(id) || sliceSeedIds.has(id);
|
|
60
60
|
for (const cd of currentVertex.controlDependencies.filter(({ id }) => !queue.hasId(id))) {
|
|
61
|
-
if (!topLevel || (idMap.get(cd.id)?.info.
|
|
61
|
+
if (!topLevel || (idMap.get(cd.id)?.info.nesting ?? 0) >= minNesting) {
|
|
62
62
|
queue.add(cd.id, baseEnvironment, baseEnvFingerprint, false);
|
|
63
63
|
}
|
|
64
64
|
}
|
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.22';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|