@eagleoutice/flowr 2.0.0 → 2.0.2

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.
Files changed (65) hide show
  1. package/benchmark/slicer.js +30 -5
  2. package/benchmark/stats/print.js +28 -9
  3. package/benchmark/stats/stats.d.ts +5 -0
  4. package/benchmark/summarizer/data.d.ts +10 -1
  5. package/benchmark/summarizer/first-phase/process.d.ts +1 -1
  6. package/benchmark/summarizer/first-phase/process.js +83 -30
  7. package/benchmark/summarizer/second-phase/process.js +20 -4
  8. package/cli/repl/commands/commands.js +19 -1
  9. package/cli/slicer-app.js +1 -1
  10. package/dataflow/environments/append.js +1 -2
  11. package/dataflow/environments/built-in.js +2 -1
  12. package/dataflow/environments/clone.js +1 -1
  13. package/dataflow/environments/diff.d.ts +1 -1
  14. package/dataflow/environments/diff.js +16 -18
  15. package/dataflow/environments/environment.d.ts +4 -7
  16. package/dataflow/environments/environment.js +5 -8
  17. package/dataflow/environments/identifier.d.ts +2 -1
  18. package/dataflow/environments/overwrite.js +1 -2
  19. package/dataflow/environments/scoping.js +1 -1
  20. package/dataflow/graph/diff.js +11 -6
  21. package/dataflow/graph/graph.d.ts +6 -2
  22. package/dataflow/graph/graph.js +13 -7
  23. package/dataflow/graph/vertex.d.ts +2 -1
  24. package/dataflow/info.d.ts +10 -1
  25. package/dataflow/info.js +54 -2
  26. package/dataflow/internal/linker.d.ts +1 -1
  27. package/dataflow/internal/linker.js +1 -2
  28. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -5
  29. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
  30. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +21 -25
  31. package/dataflow/internal/process/functions/call/built-in/built-in-get.js +6 -1
  32. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +10 -8
  33. package/dataflow/internal/process/functions/call/built-in/built-in-logical-bin-op.d.ts +1 -0
  34. package/dataflow/internal/process/functions/call/built-in/built-in-logical-bin-op.js +1 -2
  35. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +1 -1
  36. package/dataflow/internal/process/functions/call/default-call-handling.js +1 -1
  37. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +1 -1
  38. package/dataflow/processor.d.ts +2 -3
  39. package/package.json +4 -2
  40. package/r-bridge/data/data.d.ts +1 -1
  41. package/r-bridge/data/data.js +1 -1
  42. package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +2 -2
  43. package/r-bridge/lang-4.x/ast/model/operators.js +1 -1
  44. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +1 -1
  45. package/r-bridge/lang-4.x/ast/model/processing/stateful-fold.js +1 -1
  46. package/r-bridge/lang-4.x/ast/model/processing/visitor.js +2 -2
  47. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/normalize-call.js +2 -2
  48. package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/normalize-binary.js +1 -1
  49. package/r-bridge/retriever.d.ts +1 -1
  50. package/r-bridge/retriever.js +3 -2
  51. package/r-bridge/shell.js +4 -3
  52. package/reconstruct/reconstruct.d.ts +3 -3
  53. package/reconstruct/reconstruct.js +40 -41
  54. package/slicing/criterion/filters/all-variables.js +1 -1
  55. package/slicing/static/static-slicer.js +2 -2
  56. package/statistics/features/common-syntax-probability.js +1 -1
  57. package/statistics/features/supported/control-flow/control-flow.js +1 -1
  58. package/statistics/features/supported/defined-functions/defined-functions.js +1 -1
  59. package/statistics/features/supported/loops/loops.js +1 -1
  60. package/statistics/features/supported/used-functions/used-functions.js +1 -1
  61. package/util/assert.d.ts +1 -1
  62. package/util/mermaid/ast.js +4 -0
  63. package/util/mermaid/dfg.js +15 -5
  64. package/util/mermaid/mermaid.js +21 -1
  65. package/util/version.js +1 -1
@@ -17,8 +17,8 @@ const strings_1 = require("../util/strings");
17
17
  const shell_1 = require("../r-bridge/shell");
18
18
  const default_pipelines_1 = require("../core/steps/pipeline/default-pipelines");
19
19
  const retriever_1 = require("../r-bridge/retriever");
20
- const collect_1 = require("../r-bridge/lang-4.x/ast/model/collect");
21
20
  const collect_all_1 = require("../slicing/criterion/collect-all");
21
+ const visitor_1 = require("../r-bridge/lang-4.x/ast/model/processing/visitor");
22
22
  exports.benchmarkLogger = log_1.log.getSubLogger({ name: 'benchmark' });
23
23
  /**
24
24
  * A slicer that can be used to slice exactly one file (multiple times).
@@ -67,6 +67,7 @@ class BenchmarkSlicer {
67
67
  const loadedContent = request.request === 'text' ? request.content : fs_1.default.readFileSync(request.content, 'utf-8');
68
68
  // retrieve number of R tokens - flowr_parsed should still contain the last parsed code
69
69
  const numberOfRTokens = await (0, retriever_1.retrieveNumberOfRTokensOfLastParse)(this.shell);
70
+ const numberOfRTokensNoComments = await (0, retriever_1.retrieveNumberOfRTokensOfLastParse)(this.shell, true);
70
71
  (0, assert_1.guard)(this.normalizedAst !== undefined, 'normalizedAst should be defined after initialization');
71
72
  (0, assert_1.guard)(this.dataflow !== undefined, 'dataflow should be defined after initialization');
72
73
  // collect dataflow graph size
@@ -84,16 +85,40 @@ class BenchmarkSlicer {
84
85
  numberOfDefinitions++;
85
86
  }
86
87
  }
88
+ let nodes = 0;
89
+ let nodesNoComments = 0;
90
+ let commentChars = 0;
91
+ let commentCharsNoWhitespace = 0;
92
+ (0, visitor_1.visitAst)(this.normalizedAst.ast, t => {
93
+ nodes++;
94
+ const comments = t.info.additionalTokens?.filter(t => t.type === "RComment" /* RType.Comment */);
95
+ if (comments && comments.length > 0) {
96
+ const content = comments.map(c => c.lexeme ?? '').join('');
97
+ commentChars += content.length;
98
+ commentCharsNoWhitespace += (0, strings_1.withoutWhitespace)(content).length;
99
+ }
100
+ else {
101
+ nodesNoComments++;
102
+ }
103
+ return false;
104
+ });
105
+ const split = loadedContent.split('\n');
106
+ const nonWhitespace = (0, strings_1.withoutWhitespace)(loadedContent).length;
87
107
  this.stats = {
88
108
  commonMeasurements: new Map(),
89
109
  perSliceMeasurements: this.perSliceMeasurements,
90
110
  request,
91
111
  input: {
92
- numberOfLines: loadedContent.split('\n').length,
112
+ numberOfLines: split.length,
113
+ numberOfNonEmptyLines: split.filter(l => l.trim().length > 0).length,
93
114
  numberOfCharacters: loadedContent.length,
94
- numberOfNonWhitespaceCharacters: (0, strings_1.withoutWhitespace)(loadedContent).length,
115
+ numberOfCharactersNoComments: loadedContent.length - commentChars,
116
+ numberOfNonWhitespaceCharacters: nonWhitespace,
117
+ numberOfNonWhitespaceCharactersNoComments: nonWhitespace - commentCharsNoWhitespace,
95
118
  numberOfRTokens: numberOfRTokens,
96
- numberOfNormalizedTokens: [...(0, collect_1.collectAllIds)(this.normalizedAst.ast)].length
119
+ numberOfRTokensNoComments: numberOfRTokensNoComments,
120
+ numberOfNormalizedTokens: nodes,
121
+ numberOfNormalizedTokensNoComments: nodesNoComments
97
122
  },
98
123
  dataflow: {
99
124
  numberOfNodes: [...this.dataflow.graph.vertices(true)].length,
@@ -122,7 +147,7 @@ class BenchmarkSlicer {
122
147
  timesHitThreshold: 0,
123
148
  reconstructedCode: {
124
149
  code: '',
125
- autoSelected: 0
150
+ linesWithAutoSelected: 0
126
151
  }
127
152
  };
128
153
  this.perSliceMeasurements.set(slicingCriteria, stats);
@@ -40,6 +40,7 @@ function asPercentage(num) {
40
40
  if (isNaN(num)) {
41
41
  return '??%';
42
42
  }
43
+ (0, assert_1.guard)(num >= 0 && num <= 1, `Percentage ${num} should be between 0 and 1`);
43
44
  return pad(`${roundTo(num * 100, 3)}%`);
44
45
  }
45
46
  function asFloat(num) {
@@ -81,11 +82,14 @@ Slicing summary for ${stats.perSliceMeasurements.numberOfSlices} slice${stats.pe
81
82
  Used Slice Criteria Sizes: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceCriteriaSizes)}
82
83
  Result Slice Sizes:
83
84
  Number of lines: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.lines)}
85
+ Number of non-empty lines: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.nonEmptyLines)}
84
86
  Number of characters: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.characters)}
85
87
  Number of non whitespace characters: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.nonWhitespaceCharacters)}
86
- Number of auto selected: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.autoSelected)}
88
+ Number of auto selected lines: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.linesWithAutoSelected)}
87
89
  Number of R tokens: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.tokens)}
90
+ Number of R tokens (w/o comments): ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.tokensNoComments)}
88
91
  Normalized R tokens: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.normalizedTokens)}
92
+ Normalized R tokens (w/o comments): ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.normalizedTokensNoComments)}
89
93
  Number of dataflow nodes: ${printCountSummarizedMeasurements(stats.perSliceMeasurements.sliceSize.dataflowNodes)}
90
94
  `;
91
95
  }
@@ -95,10 +99,15 @@ Total: ${print(stats.commonMeasurements, 'total')}
95
99
 
96
100
  Input:
97
101
  Number of lines: ${pad(stats.input.numberOfLines)}
102
+ Number of non empty lines: ${pad(stats.input.numberOfNonEmptyLines)}
98
103
  Number of characters: ${pad(stats.input.numberOfCharacters)}
104
+ Number of characters (w/o comments): ${pad(stats.input.numberOfCharactersNoComments)}
99
105
  Number of non whitespace characters: ${pad(stats.input.numberOfNonWhitespaceCharacters)}
106
+ Number of n. w. c. (w/o comments): ${pad(stats.input.numberOfNonWhitespaceCharactersNoComments)}
100
107
  Number of tokens: ${pad(stats.input.numberOfRTokens)}
108
+ Number of tokens (w/o comments): ${pad(stats.input.numberOfRTokensNoComments)}
101
109
  Normalized R tokens: ${pad(stats.input.numberOfNormalizedTokens)}
110
+ Normalized R tokens (w/o comments): ${pad(stats.input.numberOfNormalizedTokensNoComments)}
102
111
 
103
112
  Dataflow:
104
113
  Number of nodes: ${pad(stats.dataflow.numberOfNodes)}
@@ -122,24 +131,23 @@ Slice summary for:
122
131
  Reconstruction: ${formatSummarizedTimeMeasure(stats.perSliceMeasurements.get('reconstruct code'))}
123
132
  Failed to Re-Parse: ${pad(stats.failedToRepParse)}/${stats.totalSlices}
124
133
  Times hit Threshold: ${pad(stats.timesHitThreshold)}/${stats.totalSlices}
125
- Reductions (reduced by x%):
126
- Number of lines: ${formatSummarizedMeasure(stats.reduction.numberOfLines, asPercentage)}
127
- Number of lines no auto: ${formatSummarizedMeasure(stats.reduction.numberOfLinesNoAutoSelection, asPercentage)}
128
- Number of characters: ${formatSummarizedMeasure(stats.reduction.numberOfCharacters, asPercentage)}
129
- Number of non whitespace characters: ${formatSummarizedMeasure(stats.reduction.numberOfNonWhitespaceCharacters, asPercentage)}
130
- Number of R tokens: ${formatSummarizedMeasure(stats.reduction.numberOfRTokens, asPercentage)}
131
- Normalized R tokens: ${formatSummarizedMeasure(stats.reduction.numberOfNormalizedTokens, asPercentage)}
132
- Number of dataflow nodes: ${formatSummarizedMeasure(stats.reduction.numberOfDataflowNodes, asPercentage)}
134
+ ${reduction2String('Reductions', stats.reduction)}
135
+ ${reduction2String('Reductions without comments and empty lines', stats.reductionNoFluff)}
133
136
 
134
137
  Shell close: ${formatSummarizedTimeMeasure(stats.commonMeasurements.get('close R session'))}
135
138
  Total: ${formatSummarizedTimeMeasure(stats.commonMeasurements.get('total'))}
136
139
 
137
140
  Input:
138
141
  Number of lines: ${formatSummarizedMeasure(stats.input.numberOfLines)}
142
+ Number of non empty lines: ${formatSummarizedMeasure(stats.input.numberOfNonEmptyLines)}
139
143
  Number of characters: ${formatSummarizedMeasure(stats.input.numberOfCharacters)}
144
+ Number of characters (w/o comments): ${formatSummarizedMeasure(stats.input.numberOfCharactersNoComments)}
140
145
  Number of non whitespace characters: ${formatSummarizedMeasure(stats.input.numberOfNonWhitespaceCharacters)}
146
+ Number of n. w. c. (w/o comments): ${formatSummarizedMeasure(stats.input.numberOfNonWhitespaceCharactersNoComments)}
141
147
  Number of tokens: ${formatSummarizedMeasure(stats.input.numberOfRTokens)}
148
+ Number of tokens (w/o comments): ${formatSummarizedMeasure(stats.input.numberOfRTokensNoComments)}
142
149
  Normalized R tokens: ${formatSummarizedMeasure(stats.input.numberOfNormalizedTokens)}
150
+ Normalized R tokens (w/o comments): ${formatSummarizedMeasure(stats.input.numberOfNormalizedTokensNoComments)}
143
151
 
144
152
  Dataflow:
145
153
  Number of nodes: ${formatSummarizedMeasure(stats.dataflow.numberOfNodes)}
@@ -148,4 +156,15 @@ Dataflow:
148
156
  Number of function defs: ${formatSummarizedMeasure(stats.dataflow.numberOfFunctionDefinitions)}`;
149
157
  }
150
158
  exports.ultimateStats2String = ultimateStats2String;
159
+ function reduction2String(title, reduction) {
160
+ return `
161
+ ${title} (reduced by x%):
162
+ Number of lines: ${formatSummarizedMeasure(reduction.numberOfLines, asPercentage)}
163
+ Number of lines no auto: ${formatSummarizedMeasure(reduction.numberOfLinesNoAutoSelection, asPercentage)}
164
+ Number of characters: ${formatSummarizedMeasure(reduction.numberOfCharacters, asPercentage)}
165
+ Number of non whitespace characters: ${formatSummarizedMeasure(reduction.numberOfNonWhitespaceCharacters, asPercentage)}
166
+ Number of R tokens: ${formatSummarizedMeasure(reduction.numberOfRTokens, asPercentage)}
167
+ Normalized R tokens: ${formatSummarizedMeasure(reduction.numberOfNormalizedTokens, asPercentage)}
168
+ Number of dataflow nodes: ${formatSummarizedMeasure(reduction.numberOfDataflowNodes, asPercentage)}`;
169
+ }
151
170
  //# sourceMappingURL=print.js.map
@@ -19,10 +19,15 @@ export interface PerSliceStats {
19
19
  }
20
20
  export interface SlicerStatsInput<T = number> {
21
21
  numberOfLines: T;
22
+ numberOfNonEmptyLines: T;
22
23
  numberOfCharacters: T;
24
+ numberOfCharactersNoComments: T;
23
25
  numberOfNonWhitespaceCharacters: T;
26
+ numberOfNonWhitespaceCharactersNoComments: T;
24
27
  numberOfRTokens: T;
28
+ numberOfRTokensNoComments: T;
25
29
  numberOfNormalizedTokens: T;
30
+ numberOfNormalizedTokensNoComments: T;
26
31
  }
27
32
  export interface SlicerStatsDataflow<T = number> {
28
33
  numberOfNodes: T;
@@ -2,13 +2,18 @@ import type { SummarizedMeasurement } from '../../util/summarizer';
2
2
  import type { CommonSlicerMeasurements, PerSliceMeasurements, SlicerStats, SlicerStatsDataflow, SlicerStatsInput } from '../stats/stats';
3
3
  export interface SliceSizeCollection {
4
4
  lines: number[];
5
+ nonEmptyLines: number[];
5
6
  characters: number[];
7
+ charactersNoComments: number[];
6
8
  nonWhitespaceCharacters: number[];
9
+ nonWhitespaceCharactersNoComments: number[];
7
10
  /** like library statements during reconstruction */
8
- autoSelected: number[];
11
+ linesWithAutoSelected: number[];
9
12
  dataflowNodes: number[];
10
13
  tokens: number[];
14
+ tokensNoComments: number[];
11
15
  normalizedTokens: number[];
16
+ normalizedTokensNoComments: number[];
12
17
  }
13
18
  /**
14
19
  * @see SlicerStats
@@ -33,6 +38,8 @@ export interface SummarizedPerSliceStats {
33
38
  sliceCriteriaSizes: SummarizedMeasurement;
34
39
  measurements: Map<PerSliceMeasurements, SummarizedMeasurement>;
35
40
  reduction: Reduction<SummarizedMeasurement>;
41
+ /** reduction, but without taking into account comments and empty lines */
42
+ reductionNoFluff: Reduction<SummarizedMeasurement>;
36
43
  failedToRepParse: number;
37
44
  timesHitThreshold: number;
38
45
  sliceSize: {
@@ -49,6 +56,8 @@ export interface UltimateSlicerStats {
49
56
  /** sum */
50
57
  timesHitThreshold: number;
51
58
  reduction: Reduction<SummarizedMeasurement>;
59
+ /** reduction, but without taking into account comments and empty lines */
60
+ reductionNoFluff: Reduction<SummarizedMeasurement>;
52
61
  input: SlicerStatsInput<SummarizedMeasurement>;
53
62
  dataflow: SlicerStatsDataflow<SummarizedMeasurement>;
54
63
  }
@@ -8,4 +8,4 @@ import type { SlicingCriteria } from '../../../slicing/criterion/parse';
8
8
  */
9
9
  export declare function summarizeSlicerStats(stats: SlicerStats, report?: (criteria: SlicingCriteria, stats: PerSliceStats) => void): Promise<Readonly<SummarizedSlicerStats>>;
10
10
  export declare function summarizeSummarizedMeasurement(data: SummarizedMeasurement[]): SummarizedMeasurement;
11
- export declare function summarizeReductions(reductions: Reduction<SummarizedMeasurement>[]): Reduction<SummarizedMeasurement>;
11
+ export declare function summarizeSummarizedReductions(reductions: Reduction<SummarizedMeasurement>[]): Reduction<SummarizedMeasurement>;
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.summarizeReductions = exports.summarizeSummarizedMeasurement = exports.summarizeSlicerStats = void 0;
29
+ exports.summarizeSummarizedReductions = exports.summarizeSummarizedMeasurement = exports.summarizeSlicerStats = void 0;
30
30
  const tmp = __importStar(require("tmp"));
31
31
  const fs_1 = __importDefault(require("fs"));
32
32
  const defaultmap_1 = require("../../../util/defaultmap");
@@ -65,14 +65,24 @@ function safeDivPercentage(a, b) {
65
65
  }
66
66
  }
67
67
  }
68
- function calculateReductionForSlice(input, dataflow, perSlice) {
68
+ function calculateReductionForSlice(input, dataflow, perSlice, ignoreFluff) {
69
+ const perSliceLines = ignoreFluff ? perSlice.nonEmptyLines : perSlice.lines;
70
+ const inputLines = ignoreFluff ? input.numberOfNonEmptyLines : input.numberOfLines;
69
71
  return {
70
- numberOfLines: safeDivPercentage(perSlice.lines, input.numberOfLines),
71
- numberOfLinesNoAutoSelection: safeDivPercentage(perSlice.lines - perSlice.autoSelected, input.numberOfLines),
72
- numberOfCharacters: safeDivPercentage(perSlice.characters, input.numberOfCharacters),
73
- numberOfNonWhitespaceCharacters: safeDivPercentage(perSlice.nonWhitespaceCharacters, input.numberOfNonWhitespaceCharacters),
74
- numberOfRTokens: safeDivPercentage(perSlice.tokens, input.numberOfRTokens),
75
- numberOfNormalizedTokens: safeDivPercentage(perSlice.normalizedTokens, input.numberOfNormalizedTokens),
72
+ numberOfLines: safeDivPercentage(perSliceLines, inputLines),
73
+ numberOfLinesNoAutoSelection: safeDivPercentage(perSliceLines - perSlice.linesWithAutoSelected, inputLines),
74
+ numberOfCharacters: ignoreFluff ?
75
+ safeDivPercentage(perSlice.charactersNoComments, input.numberOfCharactersNoComments) :
76
+ safeDivPercentage(perSlice.characters, input.numberOfCharacters),
77
+ numberOfNonWhitespaceCharacters: ignoreFluff ?
78
+ safeDivPercentage(perSlice.nonWhitespaceCharactersNoComments, input.numberOfNonWhitespaceCharactersNoComments) :
79
+ safeDivPercentage(perSlice.nonWhitespaceCharacters, input.numberOfNonWhitespaceCharacters),
80
+ numberOfRTokens: ignoreFluff ?
81
+ safeDivPercentage(perSlice.tokensNoComments, input.numberOfRTokensNoComments) :
82
+ safeDivPercentage(perSlice.tokens, input.numberOfRTokens),
83
+ numberOfNormalizedTokens: ignoreFluff ?
84
+ safeDivPercentage(perSlice.normalizedTokensNoComments, input.numberOfNormalizedTokensNoComments) :
85
+ safeDivPercentage(perSlice.normalizedTokens, input.numberOfNormalizedTokens),
76
86
  numberOfDataflowNodes: safeDivPercentage(perSlice.dataflowNodes, dataflow.numberOfNodes)
77
87
  };
78
88
  }
@@ -87,14 +97,20 @@ async function summarizeSlicerStats(stats, report = () => {
87
97
  const sizeOfSliceCriteria = [];
88
98
  const reParseShellSession = new shell_1.RShell();
89
99
  const reductions = [];
100
+ const reductionsNoFluff = [];
90
101
  let failedOutputs = 0;
91
102
  const sliceSize = {
92
103
  lines: [],
93
- autoSelected: [],
104
+ nonEmptyLines: [],
105
+ linesWithAutoSelected: [],
94
106
  characters: [],
107
+ charactersNoComments: [],
95
108
  nonWhitespaceCharacters: [],
109
+ nonWhitespaceCharactersNoComments: [],
96
110
  tokens: [],
111
+ tokensNoComments: [],
97
112
  normalizedTokens: [],
113
+ normalizedTokensNoComments: [],
98
114
  dataflowNodes: []
99
115
  };
100
116
  let timesHitThreshold = 0;
@@ -105,10 +121,13 @@ async function summarizeSlicerStats(stats, report = () => {
105
121
  }
106
122
  sizeOfSliceCriteria.push(perSliceStat.slicingCriteria.length);
107
123
  timesHitThreshold += perSliceStat.timesHitThreshold > 0 ? 1 : 0;
108
- const { code: output, autoSelected } = perSliceStat.reconstructedCode;
109
- sliceSize.autoSelected.push(autoSelected);
110
- const lines = output.split('\n').length;
124
+ const { code: output, linesWithAutoSelected } = perSliceStat.reconstructedCode;
125
+ sliceSize.linesWithAutoSelected.push(linesWithAutoSelected);
126
+ const split = output.split('\n');
127
+ const lines = split.length;
128
+ const nonEmptyLines = split.filter(l => l.trim().length > 0).length;
111
129
  sliceSize.lines.push(lines);
130
+ sliceSize.nonEmptyLines.push(nonEmptyLines);
112
131
  sliceSize.characters.push(output.length);
113
132
  const nonWhitespace = (0, strings_1.withoutWhitespace)(output).length;
114
133
  sliceSize.nonWhitespaceCharacters.push(nonWhitespace);
@@ -118,22 +137,46 @@ async function summarizeSlicerStats(stats, report = () => {
118
137
  fs_1.default.writeFileSync(tempfile().name, output);
119
138
  const reParsed = await (0, retriever_1.retrieveNormalizedAstFromRCode)({ request: 'file', content: tempfile().name }, reParseShellSession);
120
139
  let numberOfNormalizedTokens = 0;
121
- (0, visitor_1.visitAst)(reParsed.ast, _ => {
140
+ let numberOfNormalizedTokensNoComments = 0;
141
+ let commentChars = 0;
142
+ let commentCharsNoWhitespace = 0;
143
+ (0, visitor_1.visitAst)(reParsed.ast, t => {
122
144
  numberOfNormalizedTokens++;
145
+ const comments = t.info.additionalTokens?.filter(t => t.type === "RComment" /* RType.Comment */);
146
+ if (comments && comments.length > 0) {
147
+ const content = comments.map(c => c.lexeme ?? '').join('');
148
+ commentChars += content.length;
149
+ commentCharsNoWhitespace += (0, strings_1.withoutWhitespace)(content).length;
150
+ }
151
+ else {
152
+ numberOfNormalizedTokensNoComments++;
153
+ }
123
154
  return false;
124
155
  });
125
156
  sliceSize.normalizedTokens.push(numberOfNormalizedTokens);
157
+ sliceSize.normalizedTokensNoComments.push(numberOfNormalizedTokensNoComments);
158
+ sliceSize.charactersNoComments.push(output.length - commentChars);
159
+ sliceSize.nonWhitespaceCharactersNoComments.push(nonWhitespace - commentCharsNoWhitespace);
126
160
  const numberOfRTokens = await (0, retriever_1.retrieveNumberOfRTokensOfLastParse)(reParseShellSession);
127
161
  sliceSize.tokens.push(numberOfRTokens);
128
- reductions.push(calculateReductionForSlice(stats.input, stats.dataflow, {
162
+ const numberOfRTokensNoComments = await (0, retriever_1.retrieveNumberOfRTokensOfLastParse)(reParseShellSession, true);
163
+ sliceSize.tokensNoComments.push(numberOfRTokensNoComments);
164
+ const perSlice = {
129
165
  lines: lines,
166
+ nonEmptyLines: nonEmptyLines,
130
167
  characters: output.length,
168
+ charactersNoComments: output.length - commentChars,
131
169
  nonWhitespaceCharacters: nonWhitespace,
132
- autoSelected: autoSelected,
170
+ nonWhitespaceCharactersNoComments: nonWhitespace - commentCharsNoWhitespace,
171
+ linesWithAutoSelected: linesWithAutoSelected,
133
172
  tokens: numberOfRTokens,
173
+ tokensNoComments: numberOfRTokensNoComments,
134
174
  normalizedTokens: numberOfNormalizedTokens,
175
+ normalizedTokensNoComments: numberOfNormalizedTokensNoComments,
135
176
  dataflowNodes: perSliceStat.numberOfDataflowNodesSliced
136
- }));
177
+ };
178
+ reductions.push(calculateReductionForSlice(stats.input, stats.dataflow, perSlice, false));
179
+ reductionsNoFluff.push(calculateReductionForSlice(stats.input, stats.dataflow, perSlice, true));
137
180
  }
138
181
  catch (e) {
139
182
  console.error(` ! Failed to re-parse the output of the slicer for ${JSON.stringify(criteria)}`); //, e
@@ -156,22 +199,20 @@ async function summarizeSlicerStats(stats, report = () => {
156
199
  measurements: summarized,
157
200
  failedToRepParse: failedOutputs,
158
201
  timesHitThreshold,
159
- reduction: {
160
- numberOfLines: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfLines).filter(assert_1.isNotUndefined)),
161
- numberOfLinesNoAutoSelection: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfLinesNoAutoSelection).filter(assert_1.isNotUndefined)),
162
- numberOfCharacters: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfCharacters).filter(assert_1.isNotUndefined)),
163
- numberOfNonWhitespaceCharacters: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfNonWhitespaceCharacters).filter(assert_1.isNotUndefined)),
164
- numberOfRTokens: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfRTokens).filter(assert_1.isNotUndefined)),
165
- numberOfNormalizedTokens: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfNormalizedTokens).filter(assert_1.isNotUndefined)),
166
- numberOfDataflowNodes: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfDataflowNodes).filter(assert_1.isNotUndefined))
167
- },
202
+ reduction: summarizeReductions(reductions),
203
+ reductionNoFluff: summarizeReductions(reductionsNoFluff),
168
204
  sliceSize: {
169
205
  lines: (0, summarizer_1.summarizeMeasurement)(sliceSize.lines),
206
+ nonEmptyLines: (0, summarizer_1.summarizeMeasurement)(sliceSize.nonEmptyLines),
170
207
  characters: (0, summarizer_1.summarizeMeasurement)(sliceSize.characters),
208
+ charactersNoComments: (0, summarizer_1.summarizeMeasurement)(sliceSize.charactersNoComments),
171
209
  nonWhitespaceCharacters: (0, summarizer_1.summarizeMeasurement)(sliceSize.nonWhitespaceCharacters),
172
- autoSelected: (0, summarizer_1.summarizeMeasurement)(sliceSize.autoSelected),
210
+ nonWhitespaceCharactersNoComments: (0, summarizer_1.summarizeMeasurement)(sliceSize.nonWhitespaceCharactersNoComments),
211
+ linesWithAutoSelected: (0, summarizer_1.summarizeMeasurement)(sliceSize.linesWithAutoSelected),
173
212
  tokens: (0, summarizer_1.summarizeMeasurement)(sliceSize.tokens),
213
+ tokensNoComments: (0, summarizer_1.summarizeMeasurement)(sliceSize.tokensNoComments),
174
214
  normalizedTokens: (0, summarizer_1.summarizeMeasurement)(sliceSize.normalizedTokens),
215
+ normalizedTokensNoComments: (0, summarizer_1.summarizeMeasurement)(sliceSize.normalizedTokensNoComments),
175
216
  dataflowNodes: (0, summarizer_1.summarizeMeasurement)(sliceSize.dataflowNodes)
176
217
  }
177
218
  }
@@ -181,8 +222,9 @@ exports.summarizeSlicerStats = summarizeSlicerStats;
181
222
  function summarizeSummarizedMeasurement(data) {
182
223
  const min = data.map(d => d.min).filter(assert_1.isNotUndefined).reduce((a, b) => Math.min(a, b), Infinity);
183
224
  const max = data.map(d => d.max).filter(assert_1.isNotUndefined).reduce((a, b) => Math.max(a, b), -Infinity);
184
- // get most average
185
- const median = data.map(d => d.median).filter(assert_1.isNotUndefined).reduce((a, b) => a + b, 0) / data.length;
225
+ // calculate median of medians (don't just average the median!)
226
+ const medians = data.map(d => d.median).filter(assert_1.isNotUndefined).sort((a, b) => a - b);
227
+ const median = medians[Math.floor(medians.length / 2)];
186
228
  const mean = data.map(d => d.mean).filter(assert_1.isNotUndefined).reduce((a, b) => a + b, 0) / data.length;
187
229
  // Method 1 of https://www.statology.org/averaging-standard-deviations/
188
230
  const std = Math.sqrt(data.map(d => d.std ** 2).filter(assert_1.isNotUndefined).reduce((a, b) => a + b, 0) / data.length);
@@ -190,7 +232,7 @@ function summarizeSummarizedMeasurement(data) {
190
232
  return { min, max, median, mean, std, total };
191
233
  }
192
234
  exports.summarizeSummarizedMeasurement = summarizeSummarizedMeasurement;
193
- function summarizeReductions(reductions) {
235
+ function summarizeSummarizedReductions(reductions) {
194
236
  return {
195
237
  numberOfDataflowNodes: summarizeSummarizedMeasurement(reductions.map(r => r.numberOfDataflowNodes)),
196
238
  numberOfLines: summarizeSummarizedMeasurement(reductions.map(r => r.numberOfLines)),
@@ -201,5 +243,16 @@ function summarizeReductions(reductions) {
201
243
  numberOfRTokens: summarizeSummarizedMeasurement(reductions.map(r => r.numberOfRTokens))
202
244
  };
203
245
  }
204
- exports.summarizeReductions = summarizeReductions;
246
+ exports.summarizeSummarizedReductions = summarizeSummarizedReductions;
247
+ function summarizeReductions(reductions) {
248
+ return {
249
+ numberOfLines: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfLines).filter(assert_1.isNotUndefined)),
250
+ numberOfLinesNoAutoSelection: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfLinesNoAutoSelection).filter(assert_1.isNotUndefined)),
251
+ numberOfCharacters: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfCharacters).filter(assert_1.isNotUndefined)),
252
+ numberOfNonWhitespaceCharacters: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfNonWhitespaceCharacters).filter(assert_1.isNotUndefined)),
253
+ numberOfRTokens: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfRTokens).filter(assert_1.isNotUndefined)),
254
+ numberOfNormalizedTokens: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfNormalizedTokens).filter(assert_1.isNotUndefined)),
255
+ numberOfDataflowNodes: (0, summarizer_1.summarizeMeasurement)(reductions.map(r => r.numberOfDataflowNodes).filter(assert_1.isNotUndefined))
256
+ };
257
+ }
205
258
  //# sourceMappingURL=process.js.map
@@ -10,6 +10,7 @@ function summarizeAllSummarizedStats(stats) {
10
10
  const commonMeasurements = new defaultmap_1.DefaultMap(() => []);
11
11
  const perSliceMeasurements = new defaultmap_1.DefaultMap(() => []);
12
12
  const reductions = [];
13
+ const reductionsNoFluff = [];
13
14
  const inputs = [];
14
15
  const dataflows = [];
15
16
  let failedToRepParse = 0;
@@ -23,6 +24,7 @@ function summarizeAllSummarizedStats(stats) {
23
24
  perSliceMeasurements.get(k).push(v);
24
25
  }
25
26
  reductions.push(stat.perSliceMeasurements.reduction);
27
+ reductionsNoFluff.push(stat.perSliceMeasurements.reductionNoFluff);
26
28
  inputs.push(stat.input);
27
29
  dataflows.push(stat.dataflow);
28
30
  failedToRepParse += stat.perSliceMeasurements.failedToRepParse;
@@ -36,13 +38,19 @@ function summarizeAllSummarizedStats(stats) {
36
38
  perSliceMeasurements: new Map([...perSliceMeasurements.entries()].map(([k, v]) => [k, (0, process_1.summarizeSummarizedMeasurement)(v)])),
37
39
  failedToRepParse,
38
40
  timesHitThreshold,
39
- reduction: (0, process_1.summarizeReductions)(reductions),
41
+ reduction: (0, process_1.summarizeSummarizedReductions)(reductions),
42
+ reductionNoFluff: (0, process_1.summarizeSummarizedReductions)(reductionsNoFluff),
40
43
  input: {
41
44
  numberOfLines: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfLines)),
45
+ numberOfNonEmptyLines: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfNonEmptyLines)),
42
46
  numberOfCharacters: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfCharacters)),
47
+ numberOfCharactersNoComments: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfCharactersNoComments)),
43
48
  numberOfNonWhitespaceCharacters: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfNonWhitespaceCharacters)),
49
+ numberOfNonWhitespaceCharactersNoComments: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfNonWhitespaceCharactersNoComments)),
44
50
  numberOfRTokens: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfRTokens)),
45
- numberOfNormalizedTokens: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfNormalizedTokens))
51
+ numberOfRTokensNoComments: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfRTokensNoComments)),
52
+ numberOfNormalizedTokens: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfNormalizedTokens)),
53
+ numberOfNormalizedTokensNoComments: (0, summarizer_1.summarizeMeasurement)(inputs.map(i => i.numberOfNormalizedTokensNoComments))
46
54
  },
47
55
  dataflow: {
48
56
  numberOfNodes: (0, summarizer_1.summarizeMeasurement)(dataflows.map(d => d.numberOfNodes)),
@@ -63,13 +71,19 @@ function summarizeAllUltimateStats(stats) {
63
71
  // average out / summarize other measurements
64
72
  commonMeasurements: new Map(stats_1.CommonSlicerMeasurements.map(m => [m, (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.commonMeasurements.get(m)))])),
65
73
  perSliceMeasurements: new Map(stats_1.PerSliceMeasurements.map(m => [m, (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.perSliceMeasurements.get(m)))])),
66
- reduction: (0, process_1.summarizeReductions)(stats.map(s => s.reduction)),
74
+ reduction: (0, process_1.summarizeSummarizedReductions)(stats.map(s => s.reduction)),
75
+ reductionNoFluff: (0, process_1.summarizeSummarizedReductions)(stats.map(s => s.reductionNoFluff)),
67
76
  input: {
68
77
  numberOfLines: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfLines)),
78
+ numberOfNonEmptyLines: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfNonEmptyLines)),
69
79
  numberOfCharacters: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfCharacters)),
80
+ numberOfCharactersNoComments: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfCharactersNoComments)),
70
81
  numberOfNonWhitespaceCharacters: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfNonWhitespaceCharacters)),
82
+ numberOfNonWhitespaceCharactersNoComments: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfNonWhitespaceCharactersNoComments)),
71
83
  numberOfRTokens: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfRTokens)),
72
- numberOfNormalizedTokens: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfNormalizedTokens))
84
+ numberOfRTokensNoComments: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfRTokensNoComments)),
85
+ numberOfNormalizedTokens: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfNormalizedTokens)),
86
+ numberOfNormalizedTokensNoComments: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.input.numberOfNormalizedTokensNoComments))
73
87
  },
74
88
  dataflow: {
75
89
  numberOfNodes: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataflow.numberOfNodes)),
@@ -97,6 +111,7 @@ function processNextSummary(line, allSummarized) {
97
111
  sliceCriteriaSizes: got.summarize.perSliceMeasurements.sliceCriteriaSizes,
98
112
  measurements: new Map(got.summarize.perSliceMeasurements.measurements),
99
113
  reduction: got.summarize.perSliceMeasurements.reduction,
114
+ reductionNoFluff: got.summarize.perSliceMeasurements.reductionNoFluff,
100
115
  timesHitThreshold: got.summarize.perSliceMeasurements.timesHitThreshold,
101
116
  failedToRepParse: got.summarize.perSliceMeasurements.failedToRepParse,
102
117
  sliceSize: got.summarize.perSliceMeasurements.sliceSize
@@ -117,6 +132,7 @@ function processNextUltimateSummary(line, allSummarized) {
117
132
  failedToRepParse: got.summarize.failedToRepParse,
118
133
  timesHitThreshold: got.summarize.timesHitThreshold,
119
134
  reduction: got.summarize.reduction,
135
+ reductionNoFluff: got.summarize.reductionNoFluff,
120
136
  input: got.summarize.input,
121
137
  dataflow: got.summarize.dataflow,
122
138
  }
@@ -61,6 +61,15 @@ const _commands = {
61
61
  'controlflow*': cfg_1.controlflowStarCommand
62
62
  };
63
63
  let commandsInitialized = false;
64
+ function hasModule(path) {
65
+ try {
66
+ require.resolve(path);
67
+ return true;
68
+ }
69
+ catch (e) {
70
+ return false;
71
+ }
72
+ }
64
73
  function commands() {
65
74
  if (commandsInitialized) {
66
75
  return _commands;
@@ -74,7 +83,16 @@ function commands() {
74
83
  script: true,
75
84
  usageExample: `:${script} --help`,
76
85
  fn: async (output, _s, remainingLine) => {
77
- await (0, execute_1.waitOnScript)(`${__dirname}/../../${target}`, (0, args_1.splitAtEscapeSensitive)(remainingLine), stdio => (0, execute_1.stdioCaptureProcessor)(stdio, msg => output.stdout(msg), msg => output.stderr(msg)));
86
+ // check if the target *module* exists in the current directory, else try two dirs up, otherwise, fail with a message
87
+ let path = `${__dirname}/${target}`;
88
+ if (!hasModule(path)) {
89
+ path = `${__dirname}/../../${target}`;
90
+ if (!hasModule(path)) {
91
+ output.stderr(`Could not find the target script ${target} in the current directory or two directories up.`);
92
+ return;
93
+ }
94
+ }
95
+ await (0, execute_1.waitOnScript)(path, (0, args_1.splitAtEscapeSensitive)(remainingLine), stdio => (0, execute_1.stdioCaptureProcessor)(stdio, msg => output.stdout(msg), msg => output.stderr(msg)));
78
96
  }
79
97
  };
80
98
  }
package/cli/slicer-app.js CHANGED
@@ -40,7 +40,7 @@ async function getSlice() {
40
40
  reconstruct = reconstructedCode;
41
41
  if (options.output) {
42
42
  console.log('Written reconstructed code to', options.output);
43
- console.log(`Automatically selected ${reconstructedCode.autoSelected} statements`);
43
+ console.log(`Automatically selected ${reconstructedCode.linesWithAutoSelected} lines`);
44
44
  fs_1.default.writeFileSync(options.output, reconstructedCode.code);
45
45
  }
46
46
  else if (!options.api && !options.diff) {
@@ -15,7 +15,6 @@ function uniqueMergeValues(old, value) {
15
15
  }
16
16
  function appendIEnvironmentWith(base, next) {
17
17
  (0, assert_1.guard)(base !== undefined && next !== undefined, 'can not append environments with undefined');
18
- (0, assert_1.guard)(base.name === next.name, 'cannot overwrite environments with different names');
19
18
  const map = new Map(base.memory);
20
19
  for (const [key, value] of next.memory) {
21
20
  const old = map.get(key);
@@ -27,7 +26,7 @@ function appendIEnvironmentWith(base, next) {
27
26
  }
28
27
  }
29
28
  const parent = base.parent === environment_1.BuiltInEnvironment ? environment_1.BuiltInEnvironment : appendIEnvironmentWith(base.parent, next.parent);
30
- const out = new environment_1.Environment(base.name, parent);
29
+ const out = new environment_1.Environment(parent);
31
30
  out.memory = map;
32
31
  return out;
33
32
  }
@@ -111,7 +111,8 @@ registerBuiltInFunctions(['delayedAssign'], built_in_assignment_1.processAssignm
111
111
  registerBuiltInFunctions(['<<-'], built_in_assignment_1.processAssignment, { superAssignment: true, canBeReplacement: true });
112
112
  registerBuiltInFunctions(['->'], built_in_assignment_1.processAssignment, { swapSourceAndTarget: true, canBeReplacement: true });
113
113
  registerBuiltInFunctions(['->>'], built_in_assignment_1.processAssignment, { superAssignment: true, swapSourceAndTarget: true, canBeReplacement: true });
114
- registerBuiltInFunctions(['&&', '||', '&', '|'], built_in_logical_bin_op_1.processSpecialBinOp, { lazy: 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 });
115
116
  registerBuiltInFunctions(['|>', '%>%'], built_in_pipe_1.processPipe, {});
116
117
  registerBuiltInFunctions(['function', '\\'], built_in_function_definition_1.processFunctionDefinition, {});
117
118
  registerBuiltInFunctions(['quote', 'substitute', 'bquote'], built_in_quote_1.processQuote, { quoteArgumentsWithIndex: 0 });
@@ -9,7 +9,7 @@ function cloneEnvironment(environment, recurseParents) {
9
9
  else if (environment.id === environment_1.BuiltInEnvironment.id) {
10
10
  return environment_1.BuiltInEnvironment;
11
11
  }
12
- const clone = new environment_1.Environment(environment.name, recurseParents ? cloneEnvironment(environment.parent, recurseParents) : environment.parent);
12
+ const clone = new environment_1.Environment(recurseParents ? cloneEnvironment(environment.parent, recurseParents) : environment.parent);
13
13
  clone.memory = new Map(JSON.parse(JSON.stringify([...environment.memory])));
14
14
  return clone;
15
15
  }
@@ -2,5 +2,5 @@ import type { GenericDifferenceInformation, WriteableDifferenceReport } from '..
2
2
  import type { IEnvironment, REnvironmentInformation } from './environment';
3
3
  import type { IdentifierReference } from './identifier';
4
4
  export declare function diffIdentifierReferences<Report extends WriteableDifferenceReport>(a: IdentifierReference | undefined, b: IdentifierReference | undefined, info: GenericDifferenceInformation<Report>): void;
5
- export declare function diffEnvironment<Report extends WriteableDifferenceReport>(a: IEnvironment | undefined, b: IEnvironment | undefined, info: GenericDifferenceInformation<Report>): void;
5
+ export declare function diffEnvironment<Report extends WriteableDifferenceReport>(a: IEnvironment | undefined, b: IEnvironment | undefined, info: GenericDifferenceInformation<Report>, depth: number): void;
6
6
  export declare function diffEnvironmentInformation<Report extends WriteableDifferenceReport>(a: REnvironmentInformation | undefined, b: REnvironmentInformation | undefined, info: GenericDifferenceInformation<Report>): void;