@eagleoutice/flowr 2.0.6 → 2.0.8
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/benchmark/stats/size-of.js +1 -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 +7 -1
- package/dataflow/environments/environment.d.ts +2 -1
- package/dataflow/environments/environment.js +24 -4
- package/dataflow/graph/edge.js +2 -1
- package/dataflow/graph/graph.d.ts +1 -0
- package/dataflow/graph/graph.js +3 -1
- package/dataflow/graph/vertex.d.ts +1 -1
- package/dataflow/internal/linker.d.ts +1 -1
- package/dataflow/internal/linker.js +2 -2
- 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/dataflow/internal/process/functions/call/named-call-handling.js +1 -0
- package/package.json +1 -1
- package/slicing/static/fingerprint.js +2 -1
- package/slicing/static/slice-call.js +20 -19
- package/slicing/static/static-slicer.js +9 -7
- package/slicing/static/visiting-queue.d.ts +2 -1
- package/slicing/static/visiting-queue.js +4 -1
- 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
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.diffEnvironmentInformation = exports.diffEnvironment = exports.diffIdentifierReferences = void 0;
|
|
4
4
|
const diff_1 = require("../../util/diff");
|
|
5
|
+
const environment_1 = require("./environment");
|
|
5
6
|
const json_1 = require("../../util/json");
|
|
6
7
|
const info_1 = require("../info");
|
|
8
|
+
const built_in_1 = require("./built-in");
|
|
7
9
|
function diffIdentifierReferences(a, b, info) {
|
|
8
10
|
if (a === undefined || b === undefined) {
|
|
9
11
|
if (a !== b) {
|
|
@@ -56,6 +58,10 @@ function diffEnvironment(a, b, info, depth) {
|
|
|
56
58
|
}
|
|
57
59
|
return;
|
|
58
60
|
}
|
|
61
|
+
if ((a.memory === built_in_1.BuiltInMemory || a.memory === built_in_1.EmptyBuiltInMemory) &&
|
|
62
|
+
(b.memory === built_in_1.BuiltInMemory || b.memory === built_in_1.EmptyBuiltInMemory)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
59
65
|
if (a.memory.size !== b.memory.size) {
|
|
60
66
|
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
67
|
(0, diff_1.setDifference)(new Set([...a.memory.keys()]), new Set([...b.memory.keys()]), {
|
|
@@ -70,7 +76,7 @@ exports.diffEnvironment = diffEnvironment;
|
|
|
70
76
|
function diffEnvironmentInformation(a, b, info) {
|
|
71
77
|
if (a === undefined || b === undefined) {
|
|
72
78
|
if (a !== b) {
|
|
73
|
-
info.report.addComment(`${info.position}Different environments: ${JSON.stringify(a,
|
|
79
|
+
info.report.addComment(`${info.position}Different environments: ${JSON.stringify(a, environment_1.builtInEnvJsonReplacer)} vs. ${JSON.stringify(b, environment_1.builtInEnvJsonReplacer)}`);
|
|
74
80
|
}
|
|
75
81
|
return;
|
|
76
82
|
}
|
|
@@ -40,4 +40,5 @@ 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;
|
|
44
|
+
export declare function builtInEnvJsonReplacer(k: unknown, v: unknown): unknown;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.initializeCleanEnvironments = exports.BuiltInEnvironment = exports.Environment = exports.makeAllMaybe = exports.makeReferenceMaybe = void 0;
|
|
3
|
+
exports.builtInEnvJsonReplacer = exports.initializeCleanEnvironments = exports.BuiltInEnvironment = exports.Environment = exports.makeAllMaybe = exports.makeReferenceMaybe = void 0;
|
|
4
4
|
const built_in_1 = require("./built-in");
|
|
5
5
|
const resolve_by_name_1 = require("./resolve-by-name");
|
|
6
|
+
const json_1 = require("../../util/json");
|
|
6
7
|
function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = undefined) {
|
|
7
8
|
const node = graph.get(ref.nodeId, true);
|
|
8
9
|
if (includeDefs) {
|
|
@@ -49,12 +50,31 @@ class Environment {
|
|
|
49
50
|
exports.Environment = Environment;
|
|
50
51
|
/* the built-in environment is the root of all environments */
|
|
51
52
|
exports.BuiltInEnvironment = new Environment(undefined);
|
|
52
|
-
exports.BuiltInEnvironment.memory =
|
|
53
|
-
|
|
53
|
+
exports.BuiltInEnvironment.memory = undefined;
|
|
54
|
+
const EmptyBuiltInEnvironment = {
|
|
55
|
+
id: exports.BuiltInEnvironment.id,
|
|
56
|
+
memory: undefined,
|
|
57
|
+
parent: undefined
|
|
58
|
+
};
|
|
59
|
+
function initializeCleanEnvironments(fullBuiltIns = true) {
|
|
60
|
+
exports.BuiltInEnvironment.memory ??= built_in_1.BuiltInMemory;
|
|
61
|
+
EmptyBuiltInEnvironment.memory ??= built_in_1.EmptyBuiltInMemory;
|
|
54
62
|
return {
|
|
55
|
-
current: new Environment(exports.BuiltInEnvironment),
|
|
63
|
+
current: new Environment(fullBuiltIns ? exports.BuiltInEnvironment : EmptyBuiltInEnvironment),
|
|
56
64
|
level: 0
|
|
57
65
|
};
|
|
58
66
|
}
|
|
59
67
|
exports.initializeCleanEnvironments = initializeCleanEnvironments;
|
|
68
|
+
function builtInEnvJsonReplacer(k, v) {
|
|
69
|
+
if (v === exports.BuiltInEnvironment) {
|
|
70
|
+
return '<BuiltInEnvironment>';
|
|
71
|
+
}
|
|
72
|
+
else if (v === EmptyBuiltInEnvironment) {
|
|
73
|
+
return '<EmptyBuiltInEnvironment>';
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return (0, json_1.jsonReplacer)(k, v);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.builtInEnvJsonReplacer = builtInEnvJsonReplacer;
|
|
60
80
|
//# sourceMappingURL=environment.js.map
|
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 */)) {
|
|
@@ -47,6 +47,7 @@ type EdgeData<Edge extends DataflowGraphEdge> = Omit<Edge, 'from' | 'to' | 'type
|
|
|
47
47
|
export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo, Edge extends DataflowGraphEdge = DataflowGraphEdge> {
|
|
48
48
|
private static DEFAULT_ENVIRONMENT;
|
|
49
49
|
private _idMap;
|
|
50
|
+
readonly functionCache: Map<NodeId, Set<DataflowGraphVertexInfo>>;
|
|
50
51
|
constructor(idMap: AstIdMap | undefined);
|
|
51
52
|
/** Contains the vertices of the root level graph (i.e., included those vertices from the complete graph, that are nested within function definitions) */
|
|
52
53
|
private rootVertices;
|
package/dataflow/graph/graph.js
CHANGED
|
@@ -42,6 +42,8 @@ function extractEdgeIds(from, to) {
|
|
|
42
42
|
class DataflowGraph {
|
|
43
43
|
static DEFAULT_ENVIRONMENT = undefined;
|
|
44
44
|
_idMap;
|
|
45
|
+
// this should be linked separately
|
|
46
|
+
functionCache = new Map();
|
|
45
47
|
constructor(idMap) {
|
|
46
48
|
DataflowGraph.DEFAULT_ENVIRONMENT ??= (0, environment_1.initializeCleanEnvironments)();
|
|
47
49
|
this._idMap = idMap;
|
|
@@ -155,7 +157,7 @@ class DataflowGraph {
|
|
|
155
157
|
if (oldVertex !== undefined) {
|
|
156
158
|
return this;
|
|
157
159
|
}
|
|
158
|
-
const fallback = vertex.tag === "variable-definition" /* VertexType.VariableDefinition */ || vertex.tag === "use" /* VertexType.Use */ || vertex.tag === "value" /* VertexType.Value */ ? undefined : DataflowGraph.DEFAULT_ENVIRONMENT;
|
|
160
|
+
const fallback = vertex.tag === "variable-definition" /* VertexType.VariableDefinition */ || vertex.tag === "use" /* VertexType.Use */ || vertex.tag === "value" /* VertexType.Value */ || (vertex.tag === "function-call" /* VertexType.FunctionCall */ && vertex.onlyBuiltin) ? undefined : DataflowGraph.DEFAULT_ENVIRONMENT;
|
|
159
161
|
// keep a clone of the original environment
|
|
160
162
|
const environment = vertex.environment === undefined ? fallback : (0, clone_1.cloneEnvironmentInformation)(vertex.environment);
|
|
161
163
|
this.vertexInformation.set(vertex.id, {
|
|
@@ -62,7 +62,7 @@ export interface DataflowGraphVertexFunctionCall extends DataflowGraphVertexBase
|
|
|
62
62
|
args: FunctionArgument[];
|
|
63
63
|
/** a performance flag to indicate that the respective call is _only_ calling a builtin function without any df graph attached */
|
|
64
64
|
onlyBuiltin: boolean;
|
|
65
|
-
|
|
65
|
+
environment: REnvironmentInformation | undefined;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* Arguments required to construct a vertex which represents the definition of a variable in the dataflow graph.
|
|
@@ -17,7 +17,7 @@ export declare function linkFunctionCalls(graph: DataflowGraph, idMap: AstIdMap,
|
|
|
17
17
|
functionCall: NodeId;
|
|
18
18
|
called: readonly DataflowGraphVertexInfo[];
|
|
19
19
|
}[];
|
|
20
|
-
export declare function getAllLinkedFunctionDefinitions(functionDefinitionReadIds: ReadonlySet<NodeId>, dataflowGraph: DataflowGraph):
|
|
20
|
+
export declare function getAllLinkedFunctionDefinitions(functionDefinitionReadIds: ReadonlySet<NodeId>, dataflowGraph: DataflowGraph): Set<DataflowGraphVertexInfo>;
|
|
21
21
|
/**
|
|
22
22
|
* This method links a set of read variables to definitions in an environment.
|
|
23
23
|
*
|
|
@@ -133,7 +133,7 @@ exports.linkFunctionCalls = linkFunctionCalls;
|
|
|
133
133
|
function getAllLinkedFunctionDefinitions(functionDefinitionReadIds, dataflowGraph) {
|
|
134
134
|
const potential = [...functionDefinitionReadIds];
|
|
135
135
|
const visited = new Set();
|
|
136
|
-
const result = new
|
|
136
|
+
const result = new Set();
|
|
137
137
|
while (potential.length > 0) {
|
|
138
138
|
const currentId = potential.pop();
|
|
139
139
|
// do not traverse builtins
|
|
@@ -156,7 +156,7 @@ function getAllLinkedFunctionDefinitions(functionDefinitionReadIds, dataflowGrap
|
|
|
156
156
|
const followBits = 1 /* EdgeType.Reads */ | 2 /* EdgeType.DefinedBy */ | 32 /* EdgeType.DefinedByOnCall */;
|
|
157
157
|
const followEdges = outgoingEdges.filter(([_, e]) => (0, edge_1.edgeIncludesType)(e.types, followBits));
|
|
158
158
|
if (currentInfo[0].subflow !== undefined) {
|
|
159
|
-
result.
|
|
159
|
+
result.add(currentInfo[0]);
|
|
160
160
|
}
|
|
161
161
|
// trace all joined reads
|
|
162
162
|
potential.push(...followEdges.map(([target]) => target).filter(id => !visited.has(id)));
|
|
@@ -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: {
|
|
@@ -45,6 +45,7 @@ function processNamedCall(name, args, rootId, data) {
|
|
|
45
45
|
const v = information.graph.getVertex(rootId);
|
|
46
46
|
if (v?.tag === "function-call" /* VertexType.FunctionCall */) {
|
|
47
47
|
v.onlyBuiltin = true;
|
|
48
|
+
v.environment = undefined;
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
return information ?? (0, info_1.initializeCleanDataflowInformation)(rootId, data);
|
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) {
|
|
@@ -4,6 +4,7 @@ exports.handleReturns = exports.sliceForCall = void 0;
|
|
|
4
4
|
const assert_1 = require("../../util/assert");
|
|
5
5
|
const fingerprint_1 = require("./fingerprint");
|
|
6
6
|
const linker_1 = require("../../dataflow/internal/linker");
|
|
7
|
+
const environment_1 = require("../../dataflow/environments/environment");
|
|
7
8
|
const scoping_1 = require("../../dataflow/environments/scoping");
|
|
8
9
|
const overwrite_1 = require("../../dataflow/environments/overwrite");
|
|
9
10
|
const built_in_1 = require("../../dataflow/environments/built-in");
|
|
@@ -11,12 +12,13 @@ const resolve_by_name_1 = require("../../dataflow/environments/resolve-by-name")
|
|
|
11
12
|
const edge_1 = require("../../dataflow/graph/edge");
|
|
12
13
|
function retrieveActiveEnvironment(callerInfo, baseEnvironment) {
|
|
13
14
|
let callerEnvironment = callerInfo.environment;
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const level = callerEnvironment?.level ?? 0;
|
|
16
|
+
if (baseEnvironment.level !== level) {
|
|
17
|
+
while (baseEnvironment.level < level) {
|
|
16
18
|
baseEnvironment = (0, scoping_1.pushLocalEnvironment)(baseEnvironment);
|
|
17
19
|
}
|
|
18
|
-
while (baseEnvironment.level >
|
|
19
|
-
callerEnvironment = (0, scoping_1.pushLocalEnvironment)(callerEnvironment);
|
|
20
|
+
while (baseEnvironment.level > level) {
|
|
21
|
+
callerEnvironment = (0, scoping_1.pushLocalEnvironment)(callerEnvironment ?? (0, environment_1.initializeCleanEnvironments)(true));
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
return (0, overwrite_1.overwriteEnvironment)(baseEnvironment, callerEnvironment);
|
|
@@ -40,7 +42,7 @@ function sliceForCall(current, callerInfo, dataflowGraph, queue) {
|
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
const functionCallTargets = (0, linker_1.getAllLinkedFunctionDefinitions)(new Set(functionCallDefs), dataflowGraph);
|
|
43
|
-
for (const
|
|
45
|
+
for (const functionCallTarget of functionCallTargets) {
|
|
44
46
|
// all those linked within the scopes of other functions are already linked when exiting a function definition
|
|
45
47
|
for (const openIn of functionCallTarget.subflow.in) {
|
|
46
48
|
const defs = openIn.name ? (0, resolve_by_name_1.resolveByName)(openIn.name, activeEnvironment) : undefined;
|
|
@@ -59,25 +61,24 @@ function sliceForCall(current, callerInfo, dataflowGraph, queue) {
|
|
|
59
61
|
exports.sliceForCall = sliceForCall;
|
|
60
62
|
/** Returns true if we found at least one return edge */
|
|
61
63
|
function handleReturns(queue, currentEdges, baseEnvFingerprint, baseEnvironment) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
found = true;
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (!found) {
|
|
64
|
+
const e = [...currentEdges.entries()];
|
|
65
|
+
const found = e.filter(([_, edge]) => (0, edge_1.edgeIncludesType)(edge.types, 8 /* EdgeType.Returns */));
|
|
66
|
+
if (found.length === 0) {
|
|
70
67
|
return false;
|
|
71
68
|
}
|
|
72
|
-
for (const [target,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
for (const [target,] of found) {
|
|
70
|
+
queue.add(target, baseEnvironment, baseEnvFingerprint, false);
|
|
71
|
+
}
|
|
72
|
+
for (const [target, edge] of e) {
|
|
73
|
+
if ((0, edge_1.edgeIncludesType)(edge.types, 1 /* EdgeType.Reads */)) {
|
|
77
74
|
queue.add(target, baseEnvironment, baseEnvFingerprint, false);
|
|
78
75
|
}
|
|
79
76
|
else if ((0, edge_1.edgeIncludesType)(edge.types, 64 /* EdgeType.Argument */)) {
|
|
80
|
-
queue.potentialArguments.
|
|
77
|
+
queue.potentialArguments.set(target, {
|
|
78
|
+
id: target,
|
|
79
|
+
baseEnvironment,
|
|
80
|
+
onlyForSideEffects: false
|
|
81
|
+
});
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
return true;
|
|
@@ -9,7 +9,6 @@ const slice_call_1 = require("./slice-call");
|
|
|
9
9
|
const parse_1 = require("../criterion/parse");
|
|
10
10
|
const environment_1 = require("../../dataflow/environments/environment");
|
|
11
11
|
const edge_1 = require("../../dataflow/graph/edge");
|
|
12
|
-
const built_in_1 = require("../../dataflow/environments/built-in");
|
|
13
12
|
exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
|
|
14
13
|
/**
|
|
15
14
|
* This returns the ids to include in the slice, when slicing with the given seed id's (must be at least one).
|
|
@@ -45,9 +44,9 @@ function staticSlicing(graph, ast, criteria, threshold = 75) {
|
|
|
45
44
|
}
|
|
46
45
|
const [currentVertex, currentEdges] = currentInfo;
|
|
47
46
|
// 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) {
|
|
47
|
+
if (currentVertex.controlDependencies && currentVertex.controlDependencies.length > 0) {
|
|
49
48
|
const topLevel = graph.isRoot(id) || sliceSeedIds.has(id);
|
|
50
|
-
for (const cd of currentVertex.controlDependencies) {
|
|
49
|
+
for (const cd of currentVertex.controlDependencies.filter(({ id }) => !queue.hasId(id))) {
|
|
51
50
|
if (!topLevel || (ast.idMap.get(cd.id)?.info.depth ?? 0) <= minDepth) {
|
|
52
51
|
queue.add(cd.id, baseEnvironment, baseEnvFingerprint, false);
|
|
53
52
|
}
|
|
@@ -63,16 +62,19 @@ function staticSlicing(graph, ast, criteria, threshold = 75) {
|
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
64
|
for (const [target, { types }] of currentEdges) {
|
|
66
|
-
if (
|
|
65
|
+
if ((0, edge_1.edgeIncludesType)(types, 256 /* EdgeType.NonStandardEvaluation */)) {
|
|
67
66
|
continue;
|
|
68
67
|
}
|
|
69
68
|
const t = (0, edge_1.shouldTraverseEdge)(types);
|
|
70
69
|
if (t === 3 /* TraverseEdge.Always */) {
|
|
71
70
|
queue.add(target, baseEnvironment, baseEnvFingerprint, false);
|
|
72
71
|
}
|
|
73
|
-
else if (t === 2 /* TraverseEdge.DefinedByOnCall */
|
|
74
|
-
queue.
|
|
75
|
-
|
|
72
|
+
else if (t === 2 /* TraverseEdge.DefinedByOnCall */) {
|
|
73
|
+
const n = queue.potentialArguments.get(target);
|
|
74
|
+
if (n) {
|
|
75
|
+
queue.add(target, n.baseEnvironment, (0, fingerprint_1.envFingerprint)(n.baseEnvironment), n.onlyForSideEffects);
|
|
76
|
+
queue.potentialArguments.delete(target);
|
|
77
|
+
}
|
|
76
78
|
}
|
|
77
79
|
else if (t === 1 /* TraverseEdge.SideEffect */) {
|
|
78
80
|
queue.add(target, baseEnvironment, baseEnvFingerprint, true);
|
|
@@ -7,7 +7,7 @@ export declare class VisitingQueue {
|
|
|
7
7
|
private seen;
|
|
8
8
|
private idThreshold;
|
|
9
9
|
private queue;
|
|
10
|
-
potentialArguments:
|
|
10
|
+
potentialArguments: Map<NodeId, NodeToSlice>;
|
|
11
11
|
constructor(threshold: number);
|
|
12
12
|
/**
|
|
13
13
|
* Adds a node to the queue if it has not been seen before.
|
|
@@ -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
|
}
|
|
@@ -10,7 +10,7 @@ class VisitingQueue {
|
|
|
10
10
|
idThreshold = new Map();
|
|
11
11
|
queue = [];
|
|
12
12
|
// the set of potential arguments holds arguments which may be added if found with the `defined-by-on-call` edge
|
|
13
|
-
potentialArguments = new
|
|
13
|
+
potentialArguments = new Map();
|
|
14
14
|
constructor(threshold) {
|
|
15
15
|
this.threshold = threshold;
|
|
16
16
|
}
|
|
@@ -42,6 +42,9 @@ class VisitingQueue {
|
|
|
42
42
|
nonEmpty() {
|
|
43
43
|
return this.queue.length > 0;
|
|
44
44
|
}
|
|
45
|
+
hasId(id) {
|
|
46
|
+
return this.idThreshold.has(id);
|
|
47
|
+
}
|
|
45
48
|
status() {
|
|
46
49
|
return {
|
|
47
50
|
timesHitThreshold: this.timesHitThreshold,
|
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.8';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|