@eagleoutice/flowr 2.0.6 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/benchmark/slicer.d.ts +1 -1
- package/benchmark/slicer.js +5 -1
- package/cli/benchmark-app.js +2 -1
- package/cli/benchmark-helper-app.js +10 -2
- package/cli/common/options.js +2 -2
- package/dataflow/environments/built-in.d.ts +2 -1
- package/dataflow/environments/built-in.js +50 -41
- package/dataflow/environments/diff.js +5 -0
- package/dataflow/environments/environment.d.ts +1 -1
- package/dataflow/environments/environment.js +10 -3
- package/dataflow/graph/edge.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +1 -1
- package/package.json +1 -1
- package/slicing/static/fingerprint.js +2 -1
- package/slicing/static/slice-call.js +8 -13
- package/slicing/static/static-slicer.js +2 -2
- package/slicing/static/visiting-queue.d.ts +1 -0
- package/slicing/static/visiting-queue.js +3 -0
- package/util/mermaid/dfg.js +3 -3
- package/util/version.js +1 -1
package/benchmark/slicer.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ export declare class BenchmarkSlicer {
|
|
|
89
89
|
* @see collectAllSlicingCriteria
|
|
90
90
|
* @see SlicingCriteriaFilter
|
|
91
91
|
*/
|
|
92
|
-
sliceForAll(filter: SlicingCriteriaFilter, report?: (current: number, total: number, allCriteria: SlicingCriteria[]) => void): Promise<number>;
|
|
92
|
+
sliceForAll(filter: SlicingCriteriaFilter, report?: (current: number, total: number, allCriteria: SlicingCriteria[]) => void, sampleRandom?: number): Promise<number>;
|
|
93
93
|
/**
|
|
94
94
|
* Retrieves the final stats and closes the shell session.
|
|
95
95
|
* Can be called multiple times to retrieve the stored stats, but will only close the session once (the first time).
|
package/benchmark/slicer.js
CHANGED
|
@@ -215,10 +215,14 @@ class BenchmarkSlicer {
|
|
|
215
215
|
* @see collectAllSlicingCriteria
|
|
216
216
|
* @see SlicingCriteriaFilter
|
|
217
217
|
*/
|
|
218
|
-
async sliceForAll(filter, report = () => { }) {
|
|
218
|
+
async sliceForAll(filter, report = () => { }, sampleRandom = -1) {
|
|
219
219
|
this.guardActive();
|
|
220
220
|
let count = 0;
|
|
221
221
|
const allCriteria = [...(0, collect_all_1.collectAllSlicingCriteria)(this.normalizedAst.ast, filter)];
|
|
222
|
+
if (sampleRandom > 0) {
|
|
223
|
+
allCriteria.sort(() => Math.random() - 0.5);
|
|
224
|
+
allCriteria.length = Math.min(allCriteria.length, sampleRandom);
|
|
225
|
+
}
|
|
222
226
|
for (const slicingCriteria of allCriteria) {
|
|
223
227
|
report(count, allCriteria.length, allCriteria);
|
|
224
228
|
await this.slice(...slicingCriteria);
|
package/cli/benchmark-app.js
CHANGED
|
@@ -21,7 +21,8 @@ if (options.input.length === 0) {
|
|
|
21
21
|
console.error('No input files given. Nothing to do. See \'--help\' if this is an error.');
|
|
22
22
|
process.exit(0);
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
const numberRegex = /^\d+$/;
|
|
25
|
+
(0, assert_1.guard)(options.slice === 'all' || options.slice === 'no' || numberRegex.test(options.slice), 'slice must be either all, no, or a number');
|
|
25
26
|
(0, assert_1.guard)(options.runs === undefined || options.runs > 0, 'runs must be greater than zero');
|
|
26
27
|
function removeIfExists(summarizedRaw) {
|
|
27
28
|
if (fs_1.default.existsSync(summarizedRaw)) {
|
|
@@ -20,7 +20,8 @@ const options = (0, script_1.processCommandLineArgs)('benchmark-helper', [], {
|
|
|
20
20
|
if (options.verbose) {
|
|
21
21
|
log_1.log.error('running with *verbose* setting - do not use for final benchmark', options);
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
const numberRegex = /^\d+$/;
|
|
24
|
+
(0, assert_1.guard)(options.slice === 'all' || options.slice === 'no' || numberRegex.test(options.slice), 'slice must be either all, no, or a number');
|
|
24
25
|
async function benchmark() {
|
|
25
26
|
// we do not use the limit argument to be able to pick the limit randomly
|
|
26
27
|
(0, assert_1.guard)(options.input !== undefined, 'No input file given');
|
|
@@ -42,9 +43,16 @@ async function benchmark() {
|
|
|
42
43
|
console.log(`${prefix} Completed Slicing`);
|
|
43
44
|
(0, assert_1.guard)(count > 0, `No possible slices found for ${options.input}, skipping in count`);
|
|
44
45
|
}
|
|
45
|
-
else {
|
|
46
|
+
else if (options.slice === 'no') {
|
|
46
47
|
console.log(`${prefix} Skipping Slicing due to --slice=${options.slice}`);
|
|
47
48
|
}
|
|
49
|
+
else {
|
|
50
|
+
const limit = parseInt(options.slice);
|
|
51
|
+
console.log(`${prefix} Slicing up to ${limit} possible slices`);
|
|
52
|
+
const count = await slicer.sliceForAll(all_variables_1.DefaultAllVariablesFilter, (i, total, arr) => console.log(`${prefix} Slicing ${i + 1}/${total} [${JSON.stringify(arr[i])}]`), limit);
|
|
53
|
+
console.log(`${prefix} Completed Slicing`);
|
|
54
|
+
(0, assert_1.guard)(count > 0, `No possible slices found for ${options.input}, skipping in count`);
|
|
55
|
+
}
|
|
48
56
|
const { stats } = slicer.finish();
|
|
49
57
|
const output = {
|
|
50
58
|
filename: options.input,
|
package/cli/common/options.js
CHANGED
|
@@ -18,7 +18,7 @@ exports.benchmarkOptions = [
|
|
|
18
18
|
{ name: 'runs', alias: 'r', type: Number, description: 'The amount of benchmark runs that should be done, out of which an average will be calculated' },
|
|
19
19
|
{ name: 'input', alias: 'i', type: String, description: 'Pass a folder or file as src to read from', multiple: true, defaultOption: true, defaultValue: [], typeLabel: '{underline files/folders}' },
|
|
20
20
|
{ name: 'parallel', alias: 'p', type: String, description: 'Number of parallel executors (defaults to {italic max(cpu.count-1, 1)})', defaultValue: Math.max(os_1.default.cpus().length - 1, 1), typeLabel: '{underline number}' },
|
|
21
|
-
{ name: 'slice', alias: 's', type: String, description: 'Automatically slice for *all* variables (default) or *no* slicing and only parsing/dataflow construction', defaultValue: 'all', typeLabel: '{underline all/no}' },
|
|
21
|
+
{ name: 'slice', alias: 's', type: String, description: 'Automatically slice for *all* variables (default) or *no* slicing and only parsing/dataflow construction. Numbers will indicate: sample X random slices from all.', defaultValue: 'all', typeLabel: '{underline all/no}' },
|
|
22
22
|
{ name: 'output', alias: 'o', type: String, description: `Directory to write all the measurements to in a per-file-basis (defaults to {italic benchmark-${StartTimeString}})`, defaultValue: `benchmark-${StartTimeString}`, typeLabel: '{underline file}' }
|
|
23
23
|
];
|
|
24
24
|
exports.benchmarkHelperOptions = [
|
|
@@ -27,7 +27,7 @@ exports.benchmarkHelperOptions = [
|
|
|
27
27
|
{ name: 'input', alias: 'i', type: String, description: 'Pass a single file as src to read from', multiple: false, defaultOption: true, typeLabel: '{underline file}' },
|
|
28
28
|
{ name: 'file-id', alias: 'd', type: Number, description: 'A numeric file id that can be used to match an input and run-num to a file' },
|
|
29
29
|
{ name: 'run-num', alias: 'r', type: Number, description: 'The n-th time that the file with the given file-id is being benchmarked' },
|
|
30
|
-
{ name: 'slice', alias: 's', type: String, description: 'Automatically slice for *all* variables (default) or *no* slicing and only parsing/dataflow construction', defaultValue: 'all', typeLabel: '{underline all/no}' },
|
|
30
|
+
{ name: 'slice', alias: 's', type: String, description: 'Automatically slice for *all* variables (default) or *no* slicing and only parsing/dataflow construction. Numbers will indicate: sample X random slices from all.', defaultValue: 'all', typeLabel: '{underline all/no}' },
|
|
31
31
|
{ name: 'output', alias: 'o', type: String, description: 'File to write the measurements to (appends a single line in JSON format)', typeLabel: '{underline file}' },
|
|
32
32
|
];
|
|
33
33
|
exports.exportQuadsOptions = [
|
|
@@ -18,8 +18,9 @@ export interface BuiltInIdentifierConstant<T = unknown> extends IdentifierRefere
|
|
|
18
18
|
definedAt: typeof BuiltIn;
|
|
19
19
|
value: T;
|
|
20
20
|
}
|
|
21
|
-
export declare function registerBuiltInFunctions<Config, Proc extends BuiltInIdentifierProcessorWithConfig<Config>>(names: readonly Identifier[], processor: Proc, config: Config): void;
|
|
21
|
+
export declare function registerBuiltInFunctions<Config, Proc extends BuiltInIdentifierProcessorWithConfig<Config>>(both: boolean, names: readonly Identifier[], processor: Proc, config: Config): void;
|
|
22
22
|
export declare function registerReplacementFunctions(standardConfig: {
|
|
23
23
|
makeMaybe?: boolean;
|
|
24
24
|
}, assignments: readonly ('<-' | '<<-')[], ...prefixes: readonly Identifier[]): void;
|
|
25
25
|
export declare const BuiltInMemory: Map<Identifier, IdentifierDefinition[]>;
|
|
26
|
+
export declare const EmptyBuiltInMemory: Map<Identifier, IdentifierDefinition[]>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BuiltInMemory = exports.registerReplacementFunctions = exports.registerBuiltInFunctions = exports.BuiltIn = void 0;
|
|
3
|
+
exports.EmptyBuiltInMemory = exports.BuiltInMemory = exports.registerReplacementFunctions = exports.registerBuiltInFunctions = exports.BuiltIn = void 0;
|
|
4
4
|
const known_call_handling_1 = require("../internal/process/functions/call/known-call-handling");
|
|
5
5
|
const built_in_source_1 = require("../internal/process/functions/call/built-in/built-in-source");
|
|
6
6
|
const built_in_access_1 = require("../internal/process/functions/call/built-in/built-in-access");
|
|
@@ -39,17 +39,21 @@ function defaultBuiltInProcessor(name, args, rootId, data, config) {
|
|
|
39
39
|
}
|
|
40
40
|
return res;
|
|
41
41
|
}
|
|
42
|
-
function registerBuiltInFunctions(names, processor, config) {
|
|
42
|
+
function registerBuiltInFunctions(both, names, processor, config) {
|
|
43
43
|
for (const name of names) {
|
|
44
44
|
(0, assert_1.guard)(!exports.BuiltInMemory.has(name), `Built-in ${name} already defined`);
|
|
45
|
-
|
|
45
|
+
const d = [{
|
|
46
46
|
kind: 'built-in-function',
|
|
47
47
|
definedAt: exports.BuiltIn,
|
|
48
48
|
controlDependencies: undefined,
|
|
49
49
|
processor: (name, args, rootId, data) => processor(name, args, rootId, data, config),
|
|
50
50
|
name,
|
|
51
51
|
nodeId: exports.BuiltIn
|
|
52
|
-
}]
|
|
52
|
+
}];
|
|
53
|
+
exports.BuiltInMemory.set(name, d);
|
|
54
|
+
if (both) {
|
|
55
|
+
exports.EmptyBuiltInMemory.set(name, d);
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
58
|
}
|
|
55
59
|
exports.registerBuiltInFunctions = registerBuiltInFunctions;
|
|
@@ -72,53 +76,58 @@ function registerReplacementFunctions(standardConfig, assignments, ...prefixes)
|
|
|
72
76
|
}
|
|
73
77
|
exports.registerReplacementFunctions = registerReplacementFunctions;
|
|
74
78
|
function registerSimpleFunctions(...names) {
|
|
75
|
-
registerBuiltInFunctions(names, defaultBuiltInProcessor, { readAllArguments: true });
|
|
79
|
+
registerBuiltInFunctions(false, names, defaultBuiltInProcessor, { readAllArguments: true });
|
|
76
80
|
}
|
|
77
|
-
function registerBuiltInConstant(name, value) {
|
|
81
|
+
function registerBuiltInConstant(both, name, value) {
|
|
78
82
|
(0, assert_1.guard)(!exports.BuiltInMemory.has(name), `Built-in ${name} already defined`);
|
|
79
|
-
|
|
83
|
+
const d = [{
|
|
80
84
|
kind: 'built-in-value',
|
|
81
85
|
definedAt: exports.BuiltIn,
|
|
82
86
|
controlDependencies: undefined,
|
|
83
87
|
value,
|
|
84
88
|
name,
|
|
85
89
|
nodeId: exports.BuiltIn
|
|
86
|
-
}]
|
|
90
|
+
}];
|
|
91
|
+
exports.BuiltInMemory.set(name, d);
|
|
92
|
+
if (both) {
|
|
93
|
+
exports.EmptyBuiltInMemory.set(name, d);
|
|
94
|
+
}
|
|
87
95
|
}
|
|
88
96
|
exports.BuiltInMemory = new Map();
|
|
89
|
-
|
|
90
|
-
registerBuiltInConstant('
|
|
91
|
-
registerBuiltInConstant('
|
|
92
|
-
registerBuiltInConstant('
|
|
93
|
-
registerBuiltInConstant('
|
|
94
|
-
registerBuiltInConstant('
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
registerBuiltInFunctions(['print', '('], defaultBuiltInProcessor, { returnsNthArgument: 0 });
|
|
98
|
-
registerBuiltInFunctions(['
|
|
99
|
-
registerBuiltInFunctions(['
|
|
100
|
-
registerBuiltInFunctions(['
|
|
101
|
-
registerBuiltInFunctions(['
|
|
102
|
-
registerBuiltInFunctions(['
|
|
103
|
-
registerBuiltInFunctions(
|
|
104
|
-
registerBuiltInFunctions(['
|
|
105
|
-
registerBuiltInFunctions(['
|
|
106
|
-
registerBuiltInFunctions(['
|
|
107
|
-
registerBuiltInFunctions(['
|
|
108
|
-
registerBuiltInFunctions(
|
|
109
|
-
registerBuiltInFunctions(['
|
|
110
|
-
registerBuiltInFunctions(['
|
|
111
|
-
registerBuiltInFunctions(['
|
|
112
|
-
registerBuiltInFunctions(['
|
|
113
|
-
registerBuiltInFunctions(['
|
|
114
|
-
registerBuiltInFunctions(
|
|
115
|
-
registerBuiltInFunctions(['
|
|
116
|
-
registerBuiltInFunctions(['
|
|
117
|
-
registerBuiltInFunctions(['
|
|
118
|
-
registerBuiltInFunctions(
|
|
119
|
-
registerBuiltInFunctions(['
|
|
120
|
-
registerBuiltInFunctions(['
|
|
121
|
-
registerBuiltInFunctions(['
|
|
97
|
+
exports.EmptyBuiltInMemory = new Map();
|
|
98
|
+
registerBuiltInConstant(true, 'NULL', null);
|
|
99
|
+
registerBuiltInConstant(true, 'NA', null);
|
|
100
|
+
registerBuiltInConstant(true, 'TRUE', true);
|
|
101
|
+
registerBuiltInConstant(true, 'T', true);
|
|
102
|
+
registerBuiltInConstant(true, 'FALSE', false);
|
|
103
|
+
registerBuiltInConstant(true, 'F', false);
|
|
104
|
+
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', 'apply', 'lapply', 'sapply', 'tapply', 'mapply', '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');
|
|
105
|
+
registerBuiltInFunctions(true, ['print', '('], defaultBuiltInProcessor, { returnsNthArgument: 0 });
|
|
106
|
+
registerBuiltInFunctions(false, ['cat', 'switch'], defaultBuiltInProcessor, {}); /* returns null */
|
|
107
|
+
registerBuiltInFunctions(true, ['return'], defaultBuiltInProcessor, { returnsNthArgument: 0, cfg: 1 /* ExitPointType.Return */ });
|
|
108
|
+
registerBuiltInFunctions(true, ['break'], defaultBuiltInProcessor, { cfg: 2 /* ExitPointType.Break */ });
|
|
109
|
+
registerBuiltInFunctions(true, ['next'], defaultBuiltInProcessor, { cfg: 3 /* ExitPointType.Next */ });
|
|
110
|
+
registerBuiltInFunctions(true, ['{'], built_in_expression_list_1.processExpressionList, {});
|
|
111
|
+
registerBuiltInFunctions(true, ['source'], built_in_source_1.processSourceCall, {});
|
|
112
|
+
registerBuiltInFunctions(true, ['[', '[['], built_in_access_1.processAccess, { treatIndicesAsString: false });
|
|
113
|
+
registerBuiltInFunctions(true, ['$', '@'], built_in_access_1.processAccess, { treatIndicesAsString: true });
|
|
114
|
+
registerBuiltInFunctions(true, ['if', 'ifelse'], built_in_if_then_else_1.processIfThenElse, {});
|
|
115
|
+
registerBuiltInFunctions(true, ['get'], built_in_get_1.processGet, {});
|
|
116
|
+
registerBuiltInFunctions(false, ['library'], built_in_library_1.processLibrary, {});
|
|
117
|
+
registerBuiltInFunctions(true, ['<-', '='], built_in_assignment_1.processAssignment, { canBeReplacement: true });
|
|
118
|
+
registerBuiltInFunctions(true, [':=', 'assign'], built_in_assignment_1.processAssignment, {});
|
|
119
|
+
registerBuiltInFunctions(true, ['delayedAssign'], built_in_assignment_1.processAssignment, { quoteSource: true });
|
|
120
|
+
registerBuiltInFunctions(true, ['<<-'], built_in_assignment_1.processAssignment, { superAssignment: true, canBeReplacement: true });
|
|
121
|
+
registerBuiltInFunctions(true, ['->'], built_in_assignment_1.processAssignment, { swapSourceAndTarget: true, canBeReplacement: true });
|
|
122
|
+
registerBuiltInFunctions(true, ['->>'], built_in_assignment_1.processAssignment, { superAssignment: true, swapSourceAndTarget: true, canBeReplacement: true });
|
|
123
|
+
registerBuiltInFunctions(true, ['&&', '&'], built_in_logical_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: true });
|
|
124
|
+
registerBuiltInFunctions(true, ['||', '|'], built_in_logical_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: false });
|
|
125
|
+
registerBuiltInFunctions(true, ['|>', '%>%'], built_in_pipe_1.processPipe, {});
|
|
126
|
+
registerBuiltInFunctions(true, ['function', '\\'], built_in_function_definition_1.processFunctionDefinition, {});
|
|
127
|
+
registerBuiltInFunctions(true, ['quote', 'substitute', 'bquote'], built_in_quote_1.processQuote, { quoteArgumentsWithIndex: 0 });
|
|
128
|
+
registerBuiltInFunctions(true, ['for'], built_in_for_loop_1.processForLoop, {});
|
|
129
|
+
registerBuiltInFunctions(true, ['repeat'], built_in_repeat_loop_1.processRepeatLoop, {});
|
|
130
|
+
registerBuiltInFunctions(true, ['while'], built_in_while_loop_1.processWhileLoop, {});
|
|
122
131
|
/* they are all mapped to `<-` but we separate super assignments */
|
|
123
132
|
registerReplacementFunctions({ makeMaybe: true }, ['<-', '<<-'], '[', '[[', '$', '@', 'names', 'dimnames', 'attributes', 'attr', 'class', 'levels', 'rownames', 'colnames');
|
|
124
133
|
//# sourceMappingURL=built-in.js.map
|
|
@@ -4,6 +4,7 @@ exports.diffEnvironmentInformation = exports.diffEnvironment = exports.diffIdent
|
|
|
4
4
|
const diff_1 = require("../../util/diff");
|
|
5
5
|
const json_1 = require("../../util/json");
|
|
6
6
|
const info_1 = require("../info");
|
|
7
|
+
const built_in_1 = require("./built-in");
|
|
7
8
|
function diffIdentifierReferences(a, b, info) {
|
|
8
9
|
if (a === undefined || b === undefined) {
|
|
9
10
|
if (a !== b) {
|
|
@@ -56,6 +57,10 @@ function diffEnvironment(a, b, info, depth) {
|
|
|
56
57
|
}
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
60
|
+
if ((a.memory === built_in_1.BuiltInMemory || a.memory === built_in_1.EmptyBuiltInMemory) &&
|
|
61
|
+
(b.memory === built_in_1.BuiltInMemory || b.memory === built_in_1.EmptyBuiltInMemory)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
59
64
|
if (a.memory.size !== b.memory.size) {
|
|
60
65
|
info.report.addComment(`${info.position}[at level: ${depth}] Different number of definitions in environment. ${info.leftname}: ${a.memory.size} vs. ${info.rightname}: ${b.memory.size}`);
|
|
61
66
|
(0, diff_1.setDifference)(new Set([...a.memory.keys()]), new Set([...b.memory.keys()]), {
|
|
@@ -40,4 +40,4 @@ export interface REnvironmentInformation {
|
|
|
40
40
|
readonly level: number;
|
|
41
41
|
}
|
|
42
42
|
export declare const BuiltInEnvironment: Environment;
|
|
43
|
-
export declare function initializeCleanEnvironments(): REnvironmentInformation;
|
|
43
|
+
export declare function initializeCleanEnvironments(fullBuiltIns?: boolean): REnvironmentInformation;
|
|
@@ -49,10 +49,17 @@ class Environment {
|
|
|
49
49
|
exports.Environment = Environment;
|
|
50
50
|
/* the built-in environment is the root of all environments */
|
|
51
51
|
exports.BuiltInEnvironment = new Environment(undefined);
|
|
52
|
-
exports.BuiltInEnvironment.memory =
|
|
53
|
-
|
|
52
|
+
exports.BuiltInEnvironment.memory = undefined;
|
|
53
|
+
const EmptyBuiltInEnvironment = {
|
|
54
|
+
id: exports.BuiltInEnvironment.id,
|
|
55
|
+
memory: undefined,
|
|
56
|
+
parent: undefined
|
|
57
|
+
};
|
|
58
|
+
function initializeCleanEnvironments(fullBuiltIns = true) {
|
|
59
|
+
exports.BuiltInEnvironment.memory ??= built_in_1.BuiltInMemory;
|
|
60
|
+
EmptyBuiltInEnvironment.memory ??= built_in_1.EmptyBuiltInMemory;
|
|
54
61
|
return {
|
|
55
|
-
current: new Environment(exports.BuiltInEnvironment),
|
|
62
|
+
current: new Environment(fullBuiltIns ? exports.BuiltInEnvironment : EmptyBuiltInEnvironment),
|
|
56
63
|
level: 0
|
|
57
64
|
};
|
|
58
65
|
}
|
package/dataflow/graph/edge.js
CHANGED
|
@@ -62,8 +62,9 @@ function edgeDoesNotIncludeType(type, types) {
|
|
|
62
62
|
return (types & type) === 0;
|
|
63
63
|
}
|
|
64
64
|
exports.edgeDoesNotIncludeType = edgeDoesNotIncludeType;
|
|
65
|
+
const alwaysTraverseEdgeTypes = 1 /* EdgeType.Reads */ | 2 /* EdgeType.DefinedBy */ | 64 /* EdgeType.Argument */ | 4 /* EdgeType.Calls */ | 16 /* EdgeType.DefinesOnCall */;
|
|
65
66
|
function shouldTraverseEdge(types) {
|
|
66
|
-
if (edgeIncludesType(types,
|
|
67
|
+
if (edgeIncludesType(types, alwaysTraverseEdgeTypes)) {
|
|
67
68
|
return 3 /* TraverseEdge.Always */;
|
|
68
69
|
}
|
|
69
70
|
else if (edgeIncludesType(types, 32 /* EdgeType.DefinedByOnCall */)) {
|
|
@@ -38,7 +38,7 @@ function processForLoop(name, args, rootId, data) {
|
|
|
38
38
|
}
|
|
39
39
|
data = { ...data, environment: headEnvironments };
|
|
40
40
|
/* process the body without any environment first, to retrieve all open references */
|
|
41
|
-
let environment = (0, environment_1.initializeCleanEnvironments)();
|
|
41
|
+
let environment = (0, environment_1.initializeCleanEnvironments)(false);
|
|
42
42
|
while (headEnvironments.level > environment.level) {
|
|
43
43
|
environment = (0, scoping_1.pushLocalEnvironment)(environment);
|
|
44
44
|
}
|
|
@@ -58,7 +58,7 @@ function patchFunctionCall({ nextGraph, rootId, name, data, argumentProcessResul
|
|
|
58
58
|
/* will be overwritten accordingly */
|
|
59
59
|
onlyBuiltin: false,
|
|
60
60
|
controlDependencies: data.controlDependencies,
|
|
61
|
-
args: argumentProcessResult.map(arg => arg === undefined ? r_function_call_1.EmptyArgument : { nodeId: arg.entryPoint, controlDependencies: undefined })
|
|
61
|
+
args: argumentProcessResult.map(arg => arg === undefined ? r_function_call_1.EmptyArgument : { nodeId: arg.entryPoint, controlDependencies: undefined, call: undefined })
|
|
62
62
|
});
|
|
63
63
|
for (const arg of argumentProcessResult) {
|
|
64
64
|
if (arg) {
|
|
@@ -41,7 +41,7 @@ function processKnownFunctionCall({ name, args, rootId, data, reverseOrder = fal
|
|
|
41
41
|
args: reverseOrder ? [...callArgs].reverse() : callArgs
|
|
42
42
|
});
|
|
43
43
|
const inIds = remainingReadInArgs;
|
|
44
|
-
const fnRef = { nodeId: rootId, name: functionCallName, controlDependencies: data.controlDependencies };
|
|
44
|
+
const fnRef = { nodeId: rootId, name: functionCallName, controlDependencies: data.controlDependencies, call: true };
|
|
45
45
|
inIds.push(fnRef);
|
|
46
46
|
return {
|
|
47
47
|
information: {
|
package/package.json
CHANGED
|
@@ -6,8 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.fingerprint = exports.envFingerprint = void 0;
|
|
7
7
|
const object_hash_1 = __importDefault(require("object-hash"));
|
|
8
8
|
const environment_1 = require("../../dataflow/environments/environment");
|
|
9
|
+
const built_in_1 = require("../../dataflow/environments/built-in");
|
|
9
10
|
function envFingerprint(env) {
|
|
10
|
-
return (0, object_hash_1.default)(env, { excludeKeys: key => key === 'id', replacer: (v) => v === environment_1.BuiltInEnvironment ? undefined : v });
|
|
11
|
+
return (0, object_hash_1.default)(env, { excludeKeys: key => key === 'id', replacer: (v) => (v === environment_1.BuiltInEnvironment || v === built_in_1.EmptyBuiltInMemory) ? undefined : v });
|
|
11
12
|
}
|
|
12
13
|
exports.envFingerprint = envFingerprint;
|
|
13
14
|
function fingerprint(id, envFingerprint, onlyForSideEffects) {
|
|
@@ -59,21 +59,16 @@ function sliceForCall(current, callerInfo, dataflowGraph, queue) {
|
|
|
59
59
|
exports.sliceForCall = sliceForCall;
|
|
60
60
|
/** Returns true if we found at least one return edge */
|
|
61
61
|
function handleReturns(queue, currentEdges, baseEnvFingerprint, baseEnvironment) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
found = true;
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (!found) {
|
|
62
|
+
const e = [...currentEdges.entries()];
|
|
63
|
+
const found = e.filter(([_, edge]) => (0, edge_1.edgeIncludesType)(edge.types, 8 /* EdgeType.Returns */));
|
|
64
|
+
if (found.length === 0) {
|
|
70
65
|
return false;
|
|
71
66
|
}
|
|
72
|
-
for (const [target,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
67
|
+
for (const [target,] of found) {
|
|
68
|
+
queue.add(target, baseEnvironment, baseEnvFingerprint, false);
|
|
69
|
+
}
|
|
70
|
+
for (const [target, edge] of e) {
|
|
71
|
+
if ((0, edge_1.edgeIncludesType)(edge.types, 1 /* EdgeType.Reads */)) {
|
|
77
72
|
queue.add(target, baseEnvironment, baseEnvFingerprint, false);
|
|
78
73
|
}
|
|
79
74
|
else if ((0, edge_1.edgeIncludesType)(edge.types, 64 /* EdgeType.Argument */)) {
|
|
@@ -45,9 +45,9 @@ function staticSlicing(graph, ast, criteria, threshold = 75) {
|
|
|
45
45
|
}
|
|
46
46
|
const [currentVertex, currentEdges] = currentInfo;
|
|
47
47
|
// we only add control dependencies iff 1) we are in different function call or 2) they have, at least, the same depth as the slicing seed
|
|
48
|
-
if (currentVertex.controlDependencies) {
|
|
48
|
+
if (currentVertex.controlDependencies && currentVertex.controlDependencies.length > 0) {
|
|
49
49
|
const topLevel = graph.isRoot(id) || sliceSeedIds.has(id);
|
|
50
|
-
for (const cd of currentVertex.controlDependencies) {
|
|
50
|
+
for (const cd of currentVertex.controlDependencies.filter(({ id }) => !queue.hasId(id))) {
|
|
51
51
|
if (!topLevel || (ast.idMap.get(cd.id)?.info.depth ?? 0) <= minDepth) {
|
|
52
52
|
queue.add(cd.id, baseEnvironment, baseEnvFingerprint, false);
|
|
53
53
|
}
|
|
@@ -19,5 +19,6 @@ export declare class VisitingQueue {
|
|
|
19
19
|
add(target: NodeId, env: REnvironmentInformation, envFingerprint: string, onlyForSideEffects: boolean): void;
|
|
20
20
|
next(): NodeToSlice;
|
|
21
21
|
nonEmpty(): boolean;
|
|
22
|
+
hasId(id: NodeId): boolean;
|
|
22
23
|
status(): Readonly<Pick<SliceResult, 'timesHitThreshold' | 'result'>>;
|
|
23
24
|
}
|
package/util/mermaid/dfg.js
CHANGED
|
@@ -57,11 +57,11 @@ function printArg(arg) {
|
|
|
57
57
|
return '[empty]';
|
|
58
58
|
}
|
|
59
59
|
else if ((0, graph_1.isNamedArgument)(arg)) {
|
|
60
|
-
const deps = arg.controlDependencies ? ', :maybe:' + arg.controlDependencies.join(',') : '';
|
|
60
|
+
const deps = arg.controlDependencies ? ', :maybe:' + arg.controlDependencies.map(c => c.id + (c.when ? '+' : '-')).join(',') : '';
|
|
61
61
|
return `${arg.name} (${arg.nodeId}${deps})`;
|
|
62
62
|
}
|
|
63
63
|
else if ((0, graph_1.isPositionalArgument)(arg)) {
|
|
64
|
-
const deps = arg.controlDependencies ? ' (:maybe:' + arg.controlDependencies.join(',') + ')' : '';
|
|
64
|
+
const deps = arg.controlDependencies ? ' (:maybe:' + arg.controlDependencies.map(c => c.id + (c.when ? '+' : '-')).join(',') + ')' : '';
|
|
65
65
|
return `${arg.nodeId}${deps}`;
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
@@ -100,7 +100,7 @@ function mermaidNodeBrackets(tag) {
|
|
|
100
100
|
return { open, close };
|
|
101
101
|
}
|
|
102
102
|
function printIdentifier(id) {
|
|
103
|
-
return `${id.name} (${id.nodeId}, ${id.kind},${id.controlDependencies ? ' {' + id.controlDependencies.join(',') + '},' : ''} def. @${id.definedAt})`;
|
|
103
|
+
return `${id.name} (${id.nodeId}, ${id.kind},${id.controlDependencies ? ' {' + id.controlDependencies.map(c => c.id + (c.when ? '+' : '-')).join(',') + '},' : ''} def. @${id.definedAt})`;
|
|
104
104
|
}
|
|
105
105
|
function printEnvironmentToLines(env) {
|
|
106
106
|
if (env === undefined) {
|
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.7';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|