@eagleoutice/flowr 2.2.16 → 2.4.0

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 (147) hide show
  1. package/README.md +48 -20
  2. package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
  3. package/abstract-interpretation/data-frame/absint-info.js +31 -0
  4. package/abstract-interpretation/data-frame/absint-visitor.d.ts +58 -0
  5. package/abstract-interpretation/data-frame/absint-visitor.js +171 -0
  6. package/abstract-interpretation/data-frame/domain.d.ts +107 -0
  7. package/abstract-interpretation/data-frame/domain.js +315 -0
  8. package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
  9. package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
  10. package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
  11. package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
  12. package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
  13. package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
  14. package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
  15. package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
  16. package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
  17. package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
  18. package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
  19. package/abstract-interpretation/data-frame/resolve-args.js +118 -0
  20. package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
  21. package/abstract-interpretation/data-frame/semantics.js +363 -0
  22. package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
  23. package/abstract-interpretation/data-frame/shape-inference.js +111 -0
  24. package/benchmark/slicer.d.ts +15 -1
  25. package/benchmark/slicer.js +137 -0
  26. package/benchmark/stats/print.js +123 -45
  27. package/benchmark/stats/size-of.d.ts +7 -0
  28. package/benchmark/stats/size-of.js +1 -0
  29. package/benchmark/stats/stats.d.ts +30 -1
  30. package/benchmark/stats/stats.js +4 -2
  31. package/benchmark/summarizer/data.d.ts +33 -2
  32. package/benchmark/summarizer/first-phase/input.js +5 -1
  33. package/benchmark/summarizer/first-phase/process.js +47 -1
  34. package/benchmark/summarizer/second-phase/graph.js +1 -1
  35. package/benchmark/summarizer/second-phase/process.js +102 -4
  36. package/cli/benchmark-app.d.ts +2 -0
  37. package/cli/benchmark-app.js +2 -0
  38. package/cli/benchmark-helper-app.d.ts +2 -0
  39. package/cli/benchmark-helper-app.js +10 -3
  40. package/cli/common/options.js +4 -0
  41. package/cli/repl/commands/repl-query.js +1 -1
  42. package/cli/repl/server/connection.js +14 -5
  43. package/config.d.ts +31 -0
  44. package/config.js +21 -1
  45. package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
  46. package/control-flow/basic-cfg-guided-visitor.js +0 -6
  47. package/control-flow/cfg-simplification.d.ts +6 -0
  48. package/control-flow/cfg-simplification.js +18 -9
  49. package/control-flow/control-flow-graph.d.ts +3 -8
  50. package/control-flow/control-flow-graph.js +5 -6
  51. package/control-flow/dfg-cfg-guided-visitor.js +1 -1
  52. package/control-flow/extract-cfg.d.ts +2 -2
  53. package/control-flow/extract-cfg.js +52 -63
  54. package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
  55. package/control-flow/semantic-cfg-guided-visitor.js +1 -1
  56. package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
  57. package/core/steps/all/static-slicing/00-slice.js +9 -3
  58. package/core/steps/pipeline/default-pipelines.d.ts +74 -74
  59. package/dataflow/environments/built-in.d.ts +7 -5
  60. package/dataflow/environments/built-in.js +16 -13
  61. package/dataflow/eval/resolve/alias-tracking.js +2 -2
  62. package/dataflow/eval/resolve/resolve.d.ts +53 -9
  63. package/dataflow/eval/resolve/resolve.js +132 -38
  64. package/dataflow/graph/dataflowgraph-builder.js +2 -2
  65. package/dataflow/graph/graph.js +1 -1
  66. package/dataflow/graph/invert-dfg.d.ts +2 -0
  67. package/dataflow/graph/invert-dfg.js +17 -0
  68. package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +1 -0
  69. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +4 -0
  70. package/documentation/doc-util/doc-query.js +11 -1
  71. package/documentation/doc-util/doc-search.js +2 -2
  72. package/documentation/print-cfg-wiki.js +3 -4
  73. package/documentation/print-core-wiki.js +2 -2
  74. package/documentation/print-dataflow-graph-wiki.js +7 -0
  75. package/documentation/print-faq-wiki.js +4 -0
  76. package/documentation/print-interface-wiki.js +11 -0
  77. package/documentation/print-linter-wiki.js +36 -4
  78. package/documentation/print-linting-and-testing-wiki.js +13 -1
  79. package/documentation/print-onboarding-wiki.js +4 -0
  80. package/documentation/print-query-wiki.js +29 -3
  81. package/linter/linter-executor.js +1 -2
  82. package/linter/linter-format.d.ts +26 -4
  83. package/linter/linter-format.js +25 -6
  84. package/linter/linter-rules.d.ts +63 -12
  85. package/linter/linter-rules.js +5 -1
  86. package/linter/rules/absolute-path.d.ts +4 -7
  87. package/linter/rules/absolute-path.js +9 -6
  88. package/linter/rules/dataframe-access-validation.d.ts +55 -0
  89. package/linter/rules/dataframe-access-validation.js +118 -0
  90. package/linter/rules/dead-code.d.ts +43 -0
  91. package/linter/rules/dead-code.js +50 -0
  92. package/linter/rules/deprecated-functions.d.ts +3 -2
  93. package/linter/rules/deprecated-functions.js +3 -1
  94. package/linter/rules/file-path-validity.d.ts +4 -4
  95. package/linter/rules/file-path-validity.js +8 -6
  96. package/linter/rules/naming-convention.d.ts +5 -4
  97. package/linter/rules/naming-convention.js +8 -2
  98. package/linter/rules/seeded-randomness.d.ts +4 -3
  99. package/linter/rules/seeded-randomness.js +3 -1
  100. package/linter/rules/unused-definition.d.ts +2 -0
  101. package/linter/rules/unused-definition.js +3 -1
  102. package/package.json +2 -2
  103. package/queries/catalog/dependencies-query/dependencies-query-executor.js +6 -1
  104. package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -0
  105. package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
  106. package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
  107. package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
  108. package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
  109. package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
  110. package/queries/catalog/linter-query/linter-query-format.js +1 -1
  111. package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
  112. package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
  113. package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
  114. package/queries/catalog/search-query/search-query-executor.js +1 -1
  115. package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -1
  116. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
  117. package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
  118. package/queries/query-print.d.ts +1 -1
  119. package/queries/query-print.js +0 -1
  120. package/queries/query.d.ts +77 -6
  121. package/queries/query.js +26 -11
  122. package/search/flowr-search-builder.d.ts +6 -6
  123. package/search/flowr-search-executor.d.ts +2 -2
  124. package/search/flowr-search-executor.js +1 -1
  125. package/search/flowr-search.d.ts +13 -8
  126. package/search/flowr-search.js +21 -0
  127. package/search/search-executor/search-enrichers.d.ts +87 -20
  128. package/search/search-executor/search-enrichers.js +44 -5
  129. package/search/search-executor/search-generators.d.ts +4 -4
  130. package/search/search-executor/search-generators.js +12 -7
  131. package/search/search-executor/search-mappers.js +3 -2
  132. package/search/search-executor/search-transformer.d.ts +3 -3
  133. package/search/search-executor/search-transformer.js +2 -2
  134. package/slicing/static/static-slicer.d.ts +4 -2
  135. package/slicing/static/static-slicer.js +10 -4
  136. package/util/collections/arrays.d.ts +2 -0
  137. package/util/collections/arrays.js +9 -0
  138. package/util/files.d.ts +8 -2
  139. package/util/files.js +22 -4
  140. package/util/mermaid/dfg.js +4 -2
  141. package/util/r-value.d.ts +23 -0
  142. package/util/r-value.js +113 -0
  143. package/util/range.d.ts +1 -0
  144. package/util/range.js +5 -1
  145. package/util/version.js +1 -1
  146. package/util/cfg/cfg.d.ts +0 -0
  147. package/util/cfg/cfg.js +0 -2
@@ -0,0 +1,363 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataFrameOperationNames = exports.ConstraintType = void 0;
4
+ exports.applyDataFrameSemantics = applyDataFrameSemantics;
5
+ exports.getConstraintType = getConstraintType;
6
+ const assert_1 = require("../../util/assert");
7
+ const domain_1 = require("./domain");
8
+ /**
9
+ * Represents the different types of resulting constraints that are inferred by abstract data frame operations.
10
+ */
11
+ var ConstraintType;
12
+ (function (ConstraintType) {
13
+ /** The inferred constraints must hold for the operand at the point of the operation */
14
+ ConstraintType[ConstraintType["OperandPrecondition"] = 0] = "OperandPrecondition";
15
+ /** The inferred constraints are applied to the operand during the operation */
16
+ ConstraintType[ConstraintType["OperandModification"] = 1] = "OperandModification";
17
+ /** The inferred constraints must hold for the returned result of the operation */
18
+ ConstraintType[ConstraintType["ResultPostcondition"] = 2] = "ResultPostcondition";
19
+ })(ConstraintType || (exports.ConstraintType = ConstraintType = {}));
20
+ /**
21
+ * Mapper for defining the abstract data frame operations and mapping them to semantics applier functions,
22
+ * including information about the type of the resulting constraints that are inferred by the operation.
23
+ */
24
+ const DataFrameSemanticsMapper = {
25
+ 'create': { apply: applyCreateSemantics, type: ConstraintType.ResultPostcondition },
26
+ 'read': { apply: applyReadSemantics, type: ConstraintType.ResultPostcondition },
27
+ 'accessCols': { apply: applyAccessColsSemantics, type: ConstraintType.OperandPrecondition },
28
+ 'accessRows': { apply: applyAccessRowsSemantics, type: ConstraintType.OperandPrecondition },
29
+ 'assignCols': { apply: applyAssignColsSemantics, type: ConstraintType.OperandModification },
30
+ 'assignRows': { apply: applyAssignRowsSemantics, type: ConstraintType.OperandModification },
31
+ 'setColNames': { apply: applySetColNamesSemantics, type: ConstraintType.OperandModification },
32
+ 'addCols': { apply: applyAddColsSemantics, type: ConstraintType.ResultPostcondition },
33
+ 'addRows': { apply: applyAddRowsSemantics, type: ConstraintType.ResultPostcondition },
34
+ 'removeCols': { apply: applyRemoveColsSemantics, type: ConstraintType.ResultPostcondition },
35
+ 'removeRows': { apply: applyRemoveRowsSemantics, type: ConstraintType.ResultPostcondition },
36
+ 'concatCols': { apply: applyConcatColsSemantics, type: ConstraintType.ResultPostcondition },
37
+ 'concatRows': { apply: applyConcatRowsSemantics, type: ConstraintType.ResultPostcondition },
38
+ 'subsetCols': { apply: applySubsetColsSemantics, type: ConstraintType.ResultPostcondition },
39
+ 'subsetRows': { apply: applySubsetRowsSemantics, type: ConstraintType.ResultPostcondition },
40
+ 'filterRows': { apply: applyFilterRowsSemantics, type: ConstraintType.ResultPostcondition },
41
+ 'mutateCols': { apply: applyMutateColsSemantics, type: ConstraintType.ResultPostcondition },
42
+ 'groupBy': { apply: applyGroupBySemantics, type: ConstraintType.ResultPostcondition },
43
+ 'summarize': { apply: applySummarizeSemantics, type: ConstraintType.ResultPostcondition },
44
+ 'join': { apply: applyJoinSemantics, type: ConstraintType.ResultPostcondition },
45
+ 'unknown': { apply: applyUnknownSemantics, type: ConstraintType.ResultPostcondition },
46
+ 'identity': { apply: applyIdentitySemantics, type: ConstraintType.ResultPostcondition }
47
+ };
48
+ /** The names of all abstract data frame operations */
49
+ exports.DataFrameOperationNames = Object.keys(DataFrameSemanticsMapper);
50
+ /**
51
+ * Applies the abstract semantics of an abstract data frame operation with respect to the data frame shape domain.
52
+ * This expects that all arguments have already been sanitized according to the original concrete data frame function (e.g. by replacing duplicate/invalid column names).
53
+ *
54
+ * @param operation - The name of the abstract operation to apply the semantics of
55
+ * @param value - The abstract data frame shape of the operand of the abstract operation
56
+ * @param args - The arguments for applying the abstract semantics of the abstract operation
57
+ * @param options - The optional additional options of the abstract operation
58
+ * @returns The resulting new data frame shape constraints.
59
+ * The semantic type of the resulting constraints depends on the {@link ConstraintType} of the abstract operation.
60
+ */
61
+ function applyDataFrameSemantics(operation, value, args, options) {
62
+ const applier = DataFrameSemanticsMapper[operation];
63
+ return applier.apply(value, args, options);
64
+ }
65
+ /**
66
+ * Gets the default resulting constraint type for an abstract data frame operation.
67
+ */
68
+ function getConstraintType(operation) {
69
+ return DataFrameSemanticsMapper[operation].type;
70
+ }
71
+ function applyCreateSemantics(value, { colnames, rows }) {
72
+ const cols = colnames?.length;
73
+ return {
74
+ colnames: colnames?.every(assert_1.isNotUndefined) ? colnames : domain_1.ColNamesTop,
75
+ cols: cols !== undefined ? [cols, cols] : domain_1.IntervalTop,
76
+ rows: Array.isArray(rows) ? rows : typeof rows === 'number' ? [rows, rows] : domain_1.IntervalTop
77
+ };
78
+ }
79
+ function applyReadSemantics(value, { colnames, rows }) {
80
+ return applyCreateSemantics(value, { colnames, rows });
81
+ }
82
+ function applyAccessColsSemantics(value, { columns }) {
83
+ if (columns?.every(col => typeof col === 'string')) {
84
+ return {
85
+ ...value,
86
+ colnames: (0, domain_1.joinColNames)(value.colnames, columns)
87
+ };
88
+ }
89
+ else if (columns?.every(col => typeof col === 'number')) {
90
+ return {
91
+ ...value,
92
+ cols: columns.reduce((a, b) => (0, domain_1.maxInterval)(a, [b, b]), value.cols)
93
+ };
94
+ }
95
+ return value;
96
+ }
97
+ function applyAccessRowsSemantics(value, { rows }) {
98
+ if (rows !== undefined) {
99
+ return {
100
+ ...value,
101
+ rows: rows.reduce((a, b) => (0, domain_1.maxInterval)(a, [b, b]), value.rows)
102
+ };
103
+ }
104
+ return value;
105
+ }
106
+ function applyAssignColsSemantics(value, { columns }) {
107
+ if (columns?.every(col => typeof col === 'string')) {
108
+ const cols = columns.length;
109
+ return {
110
+ ...value,
111
+ colnames: (0, domain_1.joinColNames)(value.colnames, columns),
112
+ cols: (0, domain_1.maxInterval)((0, domain_1.addInterval)(value.cols, [0, cols]), [cols, cols])
113
+ };
114
+ }
115
+ else if (columns?.every(col => typeof col === 'number')) {
116
+ return {
117
+ ...value,
118
+ colnames: domain_1.ColNamesTop,
119
+ cols: columns.reduce((a, b) => (0, domain_1.maxInterval)(a, [b, b]), value.cols)
120
+ };
121
+ }
122
+ return {
123
+ ...value,
124
+ colnames: domain_1.ColNamesTop,
125
+ cols: (0, domain_1.extendIntervalToInfinity)(value.cols)
126
+ };
127
+ }
128
+ function applyAssignRowsSemantics(value, { rows }) {
129
+ if (rows !== undefined) {
130
+ return {
131
+ ...value,
132
+ rows: rows.reduce((a, b) => (0, domain_1.maxInterval)(a, [b, b]), value.rows)
133
+ };
134
+ }
135
+ return {
136
+ ...value,
137
+ rows: (0, domain_1.extendIntervalToInfinity)(value.rows)
138
+ };
139
+ }
140
+ function applySetColNamesSemantics(value, { colnames }, options) {
141
+ if (options?.partial) {
142
+ return {
143
+ ...value,
144
+ colnames: colnames?.every(assert_1.isNotUndefined) ? (0, domain_1.joinColNames)(value.colnames, colnames) : domain_1.ColNamesTop,
145
+ };
146
+ }
147
+ const cols = colnames?.length;
148
+ const allColNames = value.cols !== domain_1.IntervalBottom && cols !== undefined && cols >= value.cols[1];
149
+ return {
150
+ ...value,
151
+ colnames: allColNames && colnames?.every(assert_1.isNotUndefined) ? colnames : domain_1.ColNamesTop,
152
+ };
153
+ }
154
+ function applyAddColsSemantics(value, { colnames }) {
155
+ const cols = colnames?.length;
156
+ return {
157
+ ...value,
158
+ colnames: colnames?.every(assert_1.isNotUndefined) ? (0, domain_1.joinColNames)(value.colnames, colnames) : domain_1.ColNamesTop,
159
+ cols: cols !== undefined ? (0, domain_1.addInterval)(value.cols, [cols, cols]) : (0, domain_1.extendIntervalToInfinity)(value.cols)
160
+ };
161
+ }
162
+ function applyAddRowsSemantics(value, { rows }) {
163
+ return {
164
+ ...value,
165
+ rows: rows !== undefined ? (0, domain_1.addInterval)(value.rows, [rows, rows]) : (0, domain_1.extendIntervalToInfinity)(value.rows)
166
+ };
167
+ }
168
+ function applyRemoveColsSemantics(value, { colnames }, options) {
169
+ const cols = colnames?.length;
170
+ if (options?.maybe) {
171
+ return {
172
+ ...value,
173
+ colnames: colnames !== undefined ? (0, domain_1.subtractColNames)(value.colnames, colnames.filter(assert_1.isNotUndefined)) : value.colnames,
174
+ cols: cols !== undefined ? (0, domain_1.subtractInterval)(value.cols, [cols, 0]) : (0, domain_1.extendIntervalToZero)(value.cols)
175
+ };
176
+ }
177
+ return {
178
+ ...value,
179
+ colnames: colnames !== undefined ? (0, domain_1.subtractColNames)(value.colnames, colnames.filter(assert_1.isNotUndefined)) : value.colnames,
180
+ cols: cols !== undefined ? (0, domain_1.subtractInterval)(value.cols, [cols, cols]) : (0, domain_1.extendIntervalToZero)(value.cols)
181
+ };
182
+ }
183
+ function applyRemoveRowsSemantics(value, { rows }, options) {
184
+ if (options?.maybe) {
185
+ return {
186
+ ...value,
187
+ cols: rows !== undefined ? (0, domain_1.subtractInterval)(value.cols, [rows, 0]) : (0, domain_1.extendIntervalToZero)(value.cols)
188
+ };
189
+ }
190
+ return {
191
+ ...value,
192
+ rows: rows !== undefined ? (0, domain_1.subtractInterval)(value.rows, [rows, rows]) : (0, domain_1.extendIntervalToZero)(value.rows)
193
+ };
194
+ }
195
+ function applyConcatColsSemantics(value, { other }) {
196
+ return {
197
+ ...value,
198
+ colnames: (0, domain_1.joinColNames)(value.colnames, other.colnames),
199
+ cols: (0, domain_1.addInterval)(value.cols, other.cols)
200
+ };
201
+ }
202
+ function applyConcatRowsSemantics(value, { other }) {
203
+ if (value.cols !== domain_1.IntervalBottom && value.cols[0] === 0) {
204
+ return {
205
+ ...value,
206
+ colnames: (0, domain_1.joinColNames)(value.colnames, other.colnames),
207
+ cols: (0, domain_1.joinInterval)(value.cols, other.cols),
208
+ rows: (0, domain_1.addInterval)(value.rows, other.rows)
209
+ };
210
+ }
211
+ return {
212
+ ...value,
213
+ rows: (0, domain_1.addInterval)(value.rows, other.rows)
214
+ };
215
+ }
216
+ function applySubsetColsSemantics(value, { colnames }, options) {
217
+ const cols = colnames?.length;
218
+ if (options?.duplicateCols) {
219
+ return {
220
+ ...value,
221
+ colnames: domain_1.ColNamesTop,
222
+ cols: cols !== undefined ? [cols, cols] : domain_1.IntervalTop
223
+ };
224
+ }
225
+ else if (options?.renamedCols) {
226
+ return {
227
+ ...value,
228
+ colnames: domain_1.ColNamesTop,
229
+ cols: cols !== undefined ? (0, domain_1.minInterval)(value.cols, [cols, cols]) : (0, domain_1.extendIntervalToZero)(value.cols)
230
+ };
231
+ }
232
+ return {
233
+ ...value,
234
+ colnames: colnames?.every(assert_1.isNotUndefined) ? (0, domain_1.meetColNames)(value.colnames, colnames) : value.colnames,
235
+ cols: cols !== undefined ? (0, domain_1.minInterval)(value.cols, [cols, cols]) : (0, domain_1.extendIntervalToZero)(value.cols)
236
+ };
237
+ }
238
+ function applySubsetRowsSemantics(value, { rows }, options) {
239
+ if (options?.duplicateRows) {
240
+ return {
241
+ ...value,
242
+ rows: rows !== undefined ? [rows, rows] : domain_1.IntervalTop
243
+ };
244
+ }
245
+ return {
246
+ ...value,
247
+ rows: rows !== undefined ? (0, domain_1.minInterval)(value.rows, [rows, rows]) : (0, domain_1.extendIntervalToZero)(value.rows)
248
+ };
249
+ }
250
+ function applyFilterRowsSemantics(value, { condition }) {
251
+ return {
252
+ ...value,
253
+ rows: condition ? value.rows : condition === false ? [0, 0] : (0, domain_1.extendIntervalToZero)(value.rows)
254
+ };
255
+ }
256
+ function applyMutateColsSemantics(value, { colnames }) {
257
+ const cols = colnames?.length;
258
+ return {
259
+ ...value,
260
+ colnames: colnames?.every(assert_1.isNotUndefined) ? (0, domain_1.joinColNames)(value.colnames, colnames) : domain_1.ColNamesTop,
261
+ cols: cols !== undefined ? (0, domain_1.maxInterval)((0, domain_1.addInterval)(value.cols, [0, cols]), [cols, cols]) : (0, domain_1.extendIntervalToInfinity)(value.cols)
262
+ };
263
+ }
264
+ function applyGroupBySemantics(value, { by }, options) {
265
+ if (options?.mutatedCols) {
266
+ return {
267
+ ...value,
268
+ colnames: by.every(assert_1.isNotUndefined) ? (0, domain_1.joinColNames)(value.colnames, by) : domain_1.ColNamesTop,
269
+ cols: (0, domain_1.addInterval)(value.cols, [0, by.length])
270
+ };
271
+ }
272
+ // Group by only marks columns as groups but does not change the shape itself
273
+ return value;
274
+ }
275
+ function applySummarizeSemantics(value, { colnames }) {
276
+ const cols = colnames?.length;
277
+ return {
278
+ ...value,
279
+ colnames: colnames?.every(assert_1.isNotUndefined) ? (0, domain_1.joinColNames)(value.colnames, colnames) : domain_1.ColNamesTop,
280
+ cols: cols !== undefined ? (0, domain_1.minInterval)((0, domain_1.addInterval)(value.cols, [0, cols]), [cols, Infinity]) : (0, domain_1.extendIntervalToInfinity)(value.rows),
281
+ rows: (0, domain_1.maxInterval)((0, domain_1.minInterval)(value.rows, [1, Infinity]), [0, 1])
282
+ };
283
+ }
284
+ function applyJoinSemantics(value, { other, by }, options) {
285
+ // Merge two intervals by creating the maximum of the lower bounds and adding the upper bounds
286
+ const mergeInterval = (interval1, interval2) => {
287
+ if (interval1 === domain_1.IntervalBottom || interval2 === domain_1.IntervalBottom) {
288
+ return domain_1.IntervalBottom;
289
+ }
290
+ else {
291
+ return [Math.max(interval1[0], interval2[0]), interval1[1] + interval2[1]];
292
+ }
293
+ };
294
+ // Creating the Cartesian product of two intervals by keeping the lower bound and multiplying the upper bounds
295
+ const productInterval = (lower, interval1, interval2) => {
296
+ if (lower === domain_1.IntervalBottom || interval1 === domain_1.IntervalBottom || interval2 === domain_1.IntervalBottom) {
297
+ return domain_1.IntervalBottom;
298
+ }
299
+ else {
300
+ return [lower[0], interval1[1] * interval2[1]];
301
+ }
302
+ };
303
+ const commonCols = (0, domain_1.meetColNames)(value.colnames, other.colnames);
304
+ let duplicateCols; // whether columns may be renamed due to occurrence in both data frames
305
+ let productRows; // whether the resulting rows may be a Cartesian product of the rows of the data frames
306
+ if (options?.natural) {
307
+ duplicateCols = false;
308
+ productRows = commonCols !== domain_1.ColNamesTop && commonCols.length === 0;
309
+ }
310
+ else if (by === undefined) {
311
+ duplicateCols = true;
312
+ productRows = true;
313
+ }
314
+ else if (by.length === 0) {
315
+ duplicateCols = commonCols === domain_1.ColNamesTop || commonCols.length > 0;
316
+ productRows = true;
317
+ }
318
+ else if (by.every(assert_1.isNotUndefined)) {
319
+ const remainingCols = (0, domain_1.subtractColNames)(commonCols, by);
320
+ duplicateCols = remainingCols === domain_1.ColNamesTop || remainingCols.length > 0;
321
+ productRows = false;
322
+ }
323
+ else {
324
+ duplicateCols = true;
325
+ productRows = false;
326
+ }
327
+ const joinType = options?.join ?? 'inner';
328
+ let rows;
329
+ switch (joinType) {
330
+ case 'inner':
331
+ rows = (0, domain_1.extendIntervalToZero)((0, domain_1.minInterval)(value.rows, other.rows));
332
+ break;
333
+ case 'left':
334
+ rows = value.rows;
335
+ break;
336
+ case 'right':
337
+ rows = other.rows;
338
+ break;
339
+ case 'full':
340
+ rows = mergeInterval(value.rows, other.rows);
341
+ break;
342
+ default:
343
+ (0, assert_1.assertUnreachable)(joinType);
344
+ }
345
+ const byCols = by?.length;
346
+ return {
347
+ ...value,
348
+ colnames: duplicateCols ? domain_1.ColNamesTop : (0, domain_1.joinColNames)(value.colnames, other.colnames),
349
+ cols: byCols !== undefined ? (0, domain_1.subtractInterval)((0, domain_1.addInterval)(value.cols, other.cols), [byCols, byCols]) : mergeInterval(value.cols, other.cols),
350
+ rows: productRows ? productInterval(rows, value.rows, other.rows) : rows
351
+ };
352
+ }
353
+ function applyIdentitySemantics(value,
354
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
355
+ _args) {
356
+ return value;
357
+ }
358
+ function applyUnknownSemantics(_value,
359
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
360
+ _args) {
361
+ return domain_1.DataFrameTop;
362
+ }
363
+ //# sourceMappingURL=semantics.js.map
@@ -0,0 +1,38 @@
1
+ import type { FlowrConfigOptions } from '../../config';
2
+ import { type ControlFlowInformation } from '../../control-flow/control-flow-graph';
3
+ import type { DataflowGraph } from '../../dataflow/graph/graph';
4
+ import type { RNode } from '../../r-bridge/lang-4.x/ast/model/model';
5
+ import type { NormalizedAst, ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
6
+ import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
7
+ import { type AbstractInterpretationInfo } from './absint-info';
8
+ import { type DataFrameDomain, type DataFrameStateDomain } from './domain';
9
+ /**
10
+ * Infers the shape of data frames by performing abstract interpretation using the control flow graph of a program.
11
+ * This directly attaches the inferred data frames shapes to the AST (see {@link AbstractInterpretationInfo}).
12
+ *
13
+ * @param cfinfo - The control flow information containing the control flow graph
14
+ * @param dfg - The data flow graph to resolve variable origins and function arguments
15
+ * @param ast - The abstract syntax tree to resolve node IDs to AST nodes
16
+ * @param config - The flowR configuration to use for the shape inference
17
+ * @returns The abstract data frame state at the exit node of the control flow graph (see {@link DataFrameStateDomain}).
18
+ * The abstract data frame states for all other nodes are attached to the AST.
19
+ */
20
+ export declare function inferDataFrameShapes(cfinfo: ControlFlowInformation, dfg: DataflowGraph, ast: NormalizedAst<ParentInformation & AbstractInterpretationInfo>, config: FlowrConfigOptions): DataFrameStateDomain;
21
+ /**
22
+ * Resolves the abstract data frame shape of a node in the AST.
23
+ * This requires that the data frame shape inference has been executed before using {@link inferDataFrameShapes}.
24
+ *
25
+ * @param id - The node or node ID to get the data frame shape for
26
+ * @param dfg - The data flow graph used to resolve the data frame shape
27
+ * @param domain - An optional abstract data frame state domain used to resolve the data frame shape (defaults to the state at the requested node)
28
+ * @returns The abstract data frame shape of the node, or `undefined` if no data frame shape was inferred for the node
29
+ */
30
+ export declare function resolveIdToDataFrameShape(id: RNode<ParentInformation & AbstractInterpretationInfo> | NodeId | undefined, dfg: DataflowGraph | undefined, domain?: DataFrameStateDomain): DataFrameDomain | undefined;
31
+ /**
32
+ * Gets all origins of a variable in the data flow graph that have already been visited.
33
+ *
34
+ * @param node - The node to get the origins for
35
+ * @param dfg - The data flow graph for resolving the origins
36
+ * @returns The origins nodes of the variable
37
+ */
38
+ export declare function getVariableOrigins(node: NodeId, dfg: DataflowGraph): RNode<ParentInformation & AbstractInterpretationInfo>[];
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.inferDataFrameShapes = inferDataFrameShapes;
4
+ exports.resolveIdToDataFrameShape = resolveIdToDataFrameShape;
5
+ exports.getVariableOrigins = getVariableOrigins;
6
+ const control_flow_graph_1 = require("../../control-flow/control-flow-graph");
7
+ const vertex_1 = require("../../dataflow/graph/vertex");
8
+ const dfg_get_origin_1 = require("../../dataflow/origin/dfg-get-origin");
9
+ const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
10
+ const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
11
+ const assert_1 = require("../../util/assert");
12
+ const absint_info_1 = require("./absint-info");
13
+ const absint_visitor_1 = require("./absint-visitor");
14
+ const domain_1 = require("./domain");
15
+ /**
16
+ * Infers the shape of data frames by performing abstract interpretation using the control flow graph of a program.
17
+ * This directly attaches the inferred data frames shapes to the AST (see {@link AbstractInterpretationInfo}).
18
+ *
19
+ * @param cfinfo - The control flow information containing the control flow graph
20
+ * @param dfg - The data flow graph to resolve variable origins and function arguments
21
+ * @param ast - The abstract syntax tree to resolve node IDs to AST nodes
22
+ * @param config - The flowR configuration to use for the shape inference
23
+ * @returns The abstract data frame state at the exit node of the control flow graph (see {@link DataFrameStateDomain}).
24
+ * The abstract data frame states for all other nodes are attached to the AST.
25
+ */
26
+ function inferDataFrameShapes(cfinfo, dfg, ast, config) {
27
+ const visitor = new absint_visitor_1.DataFrameShapeInferenceVisitor({ controlFlow: cfinfo, dfg: dfg, normalizedAst: ast, flowrConfig: config });
28
+ visitor.start();
29
+ const exitPoints = cfinfo.exitPoints.map(id => cfinfo.graph.getVertex(id)).filter(assert_1.isNotUndefined);
30
+ const exitNodes = exitPoints.map(vertex => ast.idMap.get((0, control_flow_graph_1.getVertexRootId)(vertex))).filter(assert_1.isNotUndefined);
31
+ const result = exitNodes.map(node => node.info.dataFrame?.domain ?? new Map());
32
+ return (0, domain_1.joinDataFrameStates)(...result);
33
+ }
34
+ /**
35
+ * Resolves the abstract data frame shape of a node in the AST.
36
+ * This requires that the data frame shape inference has been executed before using {@link inferDataFrameShapes}.
37
+ *
38
+ * @param id - The node or node ID to get the data frame shape for
39
+ * @param dfg - The data flow graph used to resolve the data frame shape
40
+ * @param domain - An optional abstract data frame state domain used to resolve the data frame shape (defaults to the state at the requested node)
41
+ * @returns The abstract data frame shape of the node, or `undefined` if no data frame shape was inferred for the node
42
+ */
43
+ function resolveIdToDataFrameShape(id, dfg, domain) {
44
+ const node = id === undefined || typeof id === 'object' ? id : dfg?.idMap?.get(id);
45
+ domain ??= node?.info.dataFrame?.domain;
46
+ if (dfg === undefined || node === undefined || domain === undefined) {
47
+ return;
48
+ }
49
+ else if (domain.has(node.info.id)) {
50
+ return domain.get(node.info.id);
51
+ }
52
+ const vertex = dfg.getVertex(node.info.id);
53
+ const call = vertex?.tag === vertex_1.VertexType.FunctionCall ? vertex : undefined;
54
+ const origins = Array.isArray(call?.origin) ? call.origin : [];
55
+ if (node.type === type_1.RType.Symbol) {
56
+ const values = getVariableOrigins(node.info.id, dfg).map(origin => domain.get(origin.info.id));
57
+ if (values.length > 0 && values.every(assert_1.isNotUndefined)) {
58
+ return (0, domain_1.joinDataFrames)(...values);
59
+ }
60
+ }
61
+ else if (node.type === type_1.RType.Argument && node.value !== undefined) {
62
+ return resolveIdToDataFrameShape(node.value, dfg, domain);
63
+ }
64
+ else if (node.type === type_1.RType.ExpressionList && node.children.length > 0) {
65
+ return resolveIdToDataFrameShape(node.children[node.children.length - 1], dfg, domain);
66
+ }
67
+ else if (node.type === type_1.RType.Pipe) {
68
+ return resolveIdToDataFrameShape(node.rhs, dfg, domain);
69
+ }
70
+ else if (origins.includes('builtin:pipe')) {
71
+ if (node.type === type_1.RType.BinaryOp) {
72
+ return resolveIdToDataFrameShape(node.rhs, dfg, domain);
73
+ }
74
+ else if (call?.args.length === 2 && call?.args[1] !== r_function_call_1.EmptyArgument) {
75
+ return resolveIdToDataFrameShape(call.args[1].nodeId, dfg, domain);
76
+ }
77
+ }
78
+ else if (node.type === type_1.RType.IfThenElse) {
79
+ if (node.otherwise !== undefined) {
80
+ const values = [node.then, node.otherwise].map(entry => resolveIdToDataFrameShape(entry, dfg, domain));
81
+ if (values.length > 0 && values.every(assert_1.isNotUndefined)) {
82
+ return (0, domain_1.joinDataFrames)(...values);
83
+ }
84
+ }
85
+ }
86
+ else if (origins.includes('builtin:if-then-else') && call?.args.every(arg => arg !== r_function_call_1.EmptyArgument)) {
87
+ if (call.args.length === 3) {
88
+ const values = call.args.slice(1, 3).map(entry => resolveIdToDataFrameShape(entry.nodeId, dfg, domain));
89
+ if (values.length > 0 && values.every(assert_1.isNotUndefined)) {
90
+ return (0, domain_1.joinDataFrames)(...values);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ /**
96
+ * Gets all origins of a variable in the data flow graph that have already been visited.
97
+ *
98
+ * @param node - The node to get the origins for
99
+ * @param dfg - The data flow graph for resolving the origins
100
+ * @returns The origins nodes of the variable
101
+ */
102
+ function getVariableOrigins(node, dfg) {
103
+ // get each variable origin that has already been visited and whose assignment has already been processed
104
+ return (0, dfg_get_origin_1.getOriginInDfg)(dfg, node)
105
+ ?.filter(origin => origin.type === 0 /* OriginType.ReadVariableOrigin */)
106
+ .map(entry => dfg.idMap?.get(entry.id))
107
+ .filter(assert_1.isNotUndefined)
108
+ .filter(origin => origin.info.dataFrame?.domain !== undefined)
109
+ .filter(origin => !(0, absint_info_1.hasDataFrameInfoMarker)(origin, absint_info_1.DataFrameInfoMarker.Unassigned)) ?? [];
110
+ }
111
+ //# sourceMappingURL=shape-inference.js.map
@@ -6,7 +6,7 @@ import type { MergeableRecord } from '../util/objects';
6
6
  import type { DataflowInformation } from '../dataflow/info';
7
7
  import type { SliceResult } from '../slicing/static/slicer-types';
8
8
  import type { ReconstructionResult } from '../reconstruct/reconstruct';
9
- import type { PerSliceStats, SlicerStats } from './stats/stats';
9
+ import type { PerSliceStats, SlicerStats, SlicerStatsDfShape } from './stats/stats';
10
10
  import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
11
11
  import type { SlicingCriteria } from '../slicing/criterion/parse';
12
12
  import type { RParseRequestFromFile, RParseRequestFromText } from '../r-bridge/retriever';
@@ -57,10 +57,12 @@ export declare class BenchmarkSlicer {
57
57
  private readonly perSliceMeasurements;
58
58
  private readonly deltas;
59
59
  private readonly parserName;
60
+ private config;
60
61
  private stats;
61
62
  private loadedXml;
62
63
  private dataflow;
63
64
  private normalizedAst;
65
+ private controlFlow;
64
66
  private totalStopwatch;
65
67
  private finished;
66
68
  private executor;
@@ -95,8 +97,20 @@ export declare class BenchmarkSlicer {
95
97
  * @returns The per slice stats retrieved for this slicing criteria
96
98
  */
97
99
  slice(...slicingCriteria: SlicingCriteria): Promise<BenchmarkSingleSliceStats>;
100
+ /**
101
+ * Extract the control flow graph using {@link extractCFG}
102
+ */
103
+ extractCFG(): void;
104
+ /**
105
+ * Infer the shape of data frames using abstract interpretation with {@link inferDataFrameShapes}
106
+ *
107
+ * @returns The statistics of the data frame shape inference
108
+ */
109
+ inferDataFrameShapes(): SlicerStatsDfShape;
110
+ private getInferredSize;
98
111
  /** Bridging the gap between the new internal and the old names for the benchmarking */
99
112
  private measureCommonStep;
113
+ private measureSimpleStep;
100
114
  private measureSliceStep;
101
115
  private guardActive;
102
116
  /**