@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.
@@ -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).
@@ -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);
@@ -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
- (0, assert_1.guard)(options.slice === 'all' || options.slice === 'no', 'slice must be either all or no');
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
- (0, assert_1.guard)(options.slice === 'all' || options.slice === 'no', 'slice must be either all or no');
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,
@@ -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
- exports.BuiltInMemory.set(name, [{
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
- exports.BuiltInMemory.set(name, [{
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
- registerBuiltInConstant('NULL', null);
90
- registerBuiltInConstant('NA', null);
91
- registerBuiltInConstant('TRUE', true);
92
- registerBuiltInConstant('T', true);
93
- registerBuiltInConstant('FALSE', false);
94
- registerBuiltInConstant('F', false);
95
- registerSimpleFunctions('~', '+', '-', '*', '/', '^', '!', '?', '**', '==', '!=', '>', '<', '>=', '<=', '%%', '%/%', '%*%', ':', 'list');
96
- registerBuiltInFunctions(['cat', 'switch'], defaultBuiltInProcessor, {}); /* returns null */
97
- registerBuiltInFunctions(['print', '('], defaultBuiltInProcessor, { returnsNthArgument: 0 });
98
- registerBuiltInFunctions(['return'], defaultBuiltInProcessor, { returnsNthArgument: 0, cfg: 1 /* ExitPointType.Return */ });
99
- registerBuiltInFunctions(['break'], defaultBuiltInProcessor, { cfg: 2 /* ExitPointType.Break */ });
100
- registerBuiltInFunctions(['next'], defaultBuiltInProcessor, { cfg: 3 /* ExitPointType.Next */ });
101
- registerBuiltInFunctions(['{'], built_in_expression_list_1.processExpressionList, {});
102
- registerBuiltInFunctions(['source'], built_in_source_1.processSourceCall, {});
103
- registerBuiltInFunctions(['[', '[['], built_in_access_1.processAccess, { treatIndicesAsString: false });
104
- registerBuiltInFunctions(['$', '@'], built_in_access_1.processAccess, { treatIndicesAsString: true });
105
- registerBuiltInFunctions(['if'], built_in_if_then_else_1.processIfThenElse, {});
106
- registerBuiltInFunctions(['get'], built_in_get_1.processGet, {});
107
- registerBuiltInFunctions(['library'], built_in_library_1.processLibrary, {});
108
- registerBuiltInFunctions(['<-', '='], built_in_assignment_1.processAssignment, { canBeReplacement: true });
109
- registerBuiltInFunctions([':=', 'assign'], built_in_assignment_1.processAssignment, {});
110
- registerBuiltInFunctions(['delayedAssign'], built_in_assignment_1.processAssignment, { quoteSource: true });
111
- registerBuiltInFunctions(['<<-'], built_in_assignment_1.processAssignment, { superAssignment: true, canBeReplacement: true });
112
- registerBuiltInFunctions(['->'], built_in_assignment_1.processAssignment, { swapSourceAndTarget: true, canBeReplacement: true });
113
- registerBuiltInFunctions(['->>'], built_in_assignment_1.processAssignment, { superAssignment: true, swapSourceAndTarget: true, canBeReplacement: true });
114
- registerBuiltInFunctions(['&&', '&'], built_in_logical_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: true });
115
- registerBuiltInFunctions(['||', '|'], built_in_logical_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: false });
116
- registerBuiltInFunctions(['|>', '%>%'], built_in_pipe_1.processPipe, {});
117
- registerBuiltInFunctions(['function', '\\'], built_in_function_definition_1.processFunctionDefinition, {});
118
- registerBuiltInFunctions(['quote', 'substitute', 'bquote'], built_in_quote_1.processQuote, { quoteArgumentsWithIndex: 0 });
119
- registerBuiltInFunctions(['for'], built_in_for_loop_1.processForLoop, {});
120
- registerBuiltInFunctions(['repeat'], built_in_repeat_loop_1.processRepeatLoop, {});
121
- registerBuiltInFunctions(['while'], built_in_while_loop_1.processWhileLoop, {});
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 = built_in_1.BuiltInMemory;
53
- function initializeCleanEnvironments() {
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
  }
@@ -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, 1 /* EdgeType.Reads */ | 2 /* EdgeType.DefinedBy */ | 64 /* EdgeType.Argument */ | 4 /* EdgeType.Calls */ | 16 /* EdgeType.DefinesOnCall */)) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "repository": {
@@ -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
- let found = false;
63
- for (const [, edge] of currentEdges) {
64
- if ((0, edge_1.edgeIncludesType)(edge.types, 8 /* EdgeType.Returns */)) {
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, edge] of currentEdges) {
73
- if ((0, edge_1.edgeIncludesType)(edge.types, 8 /* EdgeType.Returns */)) {
74
- queue.add(target, baseEnvironment, baseEnvFingerprint, false);
75
- }
76
- else if ((0, edge_1.edgeIncludesType)(edge.types, 1 /* EdgeType.Reads */)) {
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
  }
@@ -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,
@@ -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';
6
+ const version = '2.0.7';
7
7
  function flowrVersion() {
8
8
  return new semver_1.SemVer(version);
9
9
  }