@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.
- package/README.md +48 -20
- package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
- package/abstract-interpretation/data-frame/absint-info.js +31 -0
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +58 -0
- package/abstract-interpretation/data-frame/absint-visitor.js +171 -0
- package/abstract-interpretation/data-frame/domain.d.ts +107 -0
- package/abstract-interpretation/data-frame/domain.js +315 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
- package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
- package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
- package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
- package/abstract-interpretation/data-frame/resolve-args.js +118 -0
- package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
- package/abstract-interpretation/data-frame/semantics.js +363 -0
- package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
- package/abstract-interpretation/data-frame/shape-inference.js +111 -0
- package/benchmark/slicer.d.ts +15 -1
- package/benchmark/slicer.js +137 -0
- package/benchmark/stats/print.js +123 -45
- package/benchmark/stats/size-of.d.ts +7 -0
- package/benchmark/stats/size-of.js +1 -0
- package/benchmark/stats/stats.d.ts +30 -1
- package/benchmark/stats/stats.js +4 -2
- package/benchmark/summarizer/data.d.ts +33 -2
- package/benchmark/summarizer/first-phase/input.js +5 -1
- package/benchmark/summarizer/first-phase/process.js +47 -1
- package/benchmark/summarizer/second-phase/graph.js +1 -1
- package/benchmark/summarizer/second-phase/process.js +102 -4
- package/cli/benchmark-app.d.ts +2 -0
- package/cli/benchmark-app.js +2 -0
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +10 -3
- package/cli/common/options.js +4 -0
- package/cli/repl/commands/repl-query.js +1 -1
- package/cli/repl/server/connection.js +14 -5
- package/config.d.ts +31 -0
- package/config.js +21 -1
- package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
- package/control-flow/basic-cfg-guided-visitor.js +0 -6
- package/control-flow/cfg-simplification.d.ts +6 -0
- package/control-flow/cfg-simplification.js +18 -9
- package/control-flow/control-flow-graph.d.ts +3 -8
- package/control-flow/control-flow-graph.js +5 -6
- package/control-flow/dfg-cfg-guided-visitor.js +1 -1
- package/control-flow/extract-cfg.d.ts +2 -2
- package/control-flow/extract-cfg.js +52 -63
- package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
- package/control-flow/semantic-cfg-guided-visitor.js +1 -1
- package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
- package/core/steps/all/static-slicing/00-slice.js +9 -3
- package/core/steps/pipeline/default-pipelines.d.ts +74 -74
- package/dataflow/environments/built-in.d.ts +7 -5
- package/dataflow/environments/built-in.js +16 -13
- package/dataflow/eval/resolve/alias-tracking.js +2 -2
- package/dataflow/eval/resolve/resolve.d.ts +53 -9
- package/dataflow/eval/resolve/resolve.js +132 -38
- package/dataflow/graph/dataflowgraph-builder.js +2 -2
- package/dataflow/graph/graph.js +1 -1
- package/dataflow/graph/invert-dfg.d.ts +2 -0
- package/dataflow/graph/invert-dfg.js +17 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +4 -0
- package/documentation/doc-util/doc-query.js +11 -1
- package/documentation/doc-util/doc-search.js +2 -2
- package/documentation/print-cfg-wiki.js +3 -4
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-dataflow-graph-wiki.js +7 -0
- package/documentation/print-faq-wiki.js +4 -0
- package/documentation/print-interface-wiki.js +11 -0
- package/documentation/print-linter-wiki.js +36 -4
- package/documentation/print-linting-and-testing-wiki.js +13 -1
- package/documentation/print-onboarding-wiki.js +4 -0
- package/documentation/print-query-wiki.js +29 -3
- package/linter/linter-executor.js +1 -2
- package/linter/linter-format.d.ts +26 -4
- package/linter/linter-format.js +25 -6
- package/linter/linter-rules.d.ts +63 -12
- package/linter/linter-rules.js +5 -1
- package/linter/rules/absolute-path.d.ts +4 -7
- package/linter/rules/absolute-path.js +9 -6
- package/linter/rules/dataframe-access-validation.d.ts +55 -0
- package/linter/rules/dataframe-access-validation.js +118 -0
- package/linter/rules/dead-code.d.ts +43 -0
- package/linter/rules/dead-code.js +50 -0
- package/linter/rules/deprecated-functions.d.ts +3 -2
- package/linter/rules/deprecated-functions.js +3 -1
- package/linter/rules/file-path-validity.d.ts +4 -4
- package/linter/rules/file-path-validity.js +8 -6
- package/linter/rules/naming-convention.d.ts +5 -4
- package/linter/rules/naming-convention.js +8 -2
- package/linter/rules/seeded-randomness.d.ts +4 -3
- package/linter/rules/seeded-randomness.js +3 -1
- package/linter/rules/unused-definition.d.ts +2 -0
- package/linter/rules/unused-definition.js +3 -1
- package/package.json +2 -2
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +6 -1
- package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
- package/queries/catalog/linter-query/linter-query-format.js +1 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
- package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
- package/queries/catalog/search-query/search-query-executor.js +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -1
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
- package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
- package/queries/query-print.d.ts +1 -1
- package/queries/query-print.js +0 -1
- package/queries/query.d.ts +77 -6
- package/queries/query.js +26 -11
- package/search/flowr-search-builder.d.ts +6 -6
- package/search/flowr-search-executor.d.ts +2 -2
- package/search/flowr-search-executor.js +1 -1
- package/search/flowr-search.d.ts +13 -8
- package/search/flowr-search.js +21 -0
- package/search/search-executor/search-enrichers.d.ts +87 -20
- package/search/search-executor/search-enrichers.js +44 -5
- package/search/search-executor/search-generators.d.ts +4 -4
- package/search/search-executor/search-generators.js +12 -7
- package/search/search-executor/search-mappers.js +3 -2
- package/search/search-executor/search-transformer.d.ts +3 -3
- package/search/search-executor/search-transformer.js +2 -2
- package/slicing/static/static-slicer.d.ts +4 -2
- package/slicing/static/static-slicer.js +10 -4
- package/util/collections/arrays.d.ts +2 -0
- package/util/collections/arrays.js +9 -0
- package/util/files.d.ts +8 -2
- package/util/files.js +22 -4
- package/util/mermaid/dfg.js +4 -2
- package/util/r-value.d.ts +23 -0
- package/util/r-value.js +113 -0
- package/util/range.d.ts +1 -0
- package/util/range.js +5 -1
- package/util/version.js +1 -1
- package/util/cfg/cfg.d.ts +0 -0
- package/util/cfg/cfg.js +0 -2
|
@@ -9,6 +9,8 @@ const defaultmap_1 = require("../../../util/collections/defaultmap");
|
|
|
9
9
|
const summarizer_1 = require("../../../util/summarizer");
|
|
10
10
|
const assert_1 = require("../../../util/assert");
|
|
11
11
|
const stats_1 = require("../../stats/stats");
|
|
12
|
+
const semantics_1 = require("../../../abstract-interpretation/data-frame/semantics");
|
|
13
|
+
const arrays_1 = require("../../../util/collections/arrays");
|
|
12
14
|
function summarizeAllSummarizedStats(stats) {
|
|
13
15
|
const commonMeasurements = new defaultmap_1.DefaultMap(() => []);
|
|
14
16
|
const perSliceMeasurements = new defaultmap_1.DefaultMap(() => []);
|
|
@@ -19,11 +21,14 @@ function summarizeAllSummarizedStats(stats) {
|
|
|
19
21
|
const normalizeTimesPerToken = [];
|
|
20
22
|
const dataflowTimesPerToken = [];
|
|
21
23
|
const totalCommonTimesPerToken = [];
|
|
24
|
+
const controlFlowTimePerToken = [];
|
|
25
|
+
const dataFrameShapeTimePerToken = [];
|
|
22
26
|
const memory = new defaultmap_1.DefaultMap(() => []);
|
|
23
27
|
const reductions = [];
|
|
24
28
|
const reductionsNoFluff = [];
|
|
25
29
|
const inputs = [];
|
|
26
30
|
const dataflows = [];
|
|
31
|
+
const dataFrameShapes = [];
|
|
27
32
|
let failedToRepParse = 0;
|
|
28
33
|
let timesHitThreshold = 0;
|
|
29
34
|
let totalSlices = 0;
|
|
@@ -41,6 +46,12 @@ function summarizeAllSummarizedStats(stats) {
|
|
|
41
46
|
normalizeTimesPerToken.push(stat.normalizeTimePerToken);
|
|
42
47
|
dataflowTimesPerToken.push(stat.dataflowTimePerToken);
|
|
43
48
|
totalCommonTimesPerToken.push(stat.totalCommonTimePerToken);
|
|
49
|
+
if (stat.controlFlowTimePerToken !== undefined) {
|
|
50
|
+
controlFlowTimePerToken.push(stat.controlFlowTimePerToken);
|
|
51
|
+
}
|
|
52
|
+
if (stat.dataFrameShapeTimePerToken !== undefined) {
|
|
53
|
+
dataFrameShapeTimePerToken.push(stat.dataFrameShapeTimePerToken);
|
|
54
|
+
}
|
|
44
55
|
for (const [k, v] of stat.memory) {
|
|
45
56
|
memory.get(k).push(v);
|
|
46
57
|
}
|
|
@@ -48,6 +59,9 @@ function summarizeAllSummarizedStats(stats) {
|
|
|
48
59
|
reductionsNoFluff.push(stat.perSliceMeasurements.reductionNoFluff);
|
|
49
60
|
inputs.push(stat.input);
|
|
50
61
|
dataflows.push(stat.dataflow);
|
|
62
|
+
if (stat.dataFrameShape !== undefined) {
|
|
63
|
+
dataFrameShapes.push(stat.dataFrameShape);
|
|
64
|
+
}
|
|
51
65
|
failedToRepParse += stat.perSliceMeasurements.failedToRepParse;
|
|
52
66
|
totalSlices += stat.perSliceMeasurements.numberOfSlices;
|
|
53
67
|
timesHitThreshold += stat.perSliceMeasurements.timesHitThreshold;
|
|
@@ -64,6 +78,8 @@ function summarizeAllSummarizedStats(stats) {
|
|
|
64
78
|
normalizeTimePerToken: (0, process_1.summarizeTimePerToken)(normalizeTimesPerToken),
|
|
65
79
|
dataflowTimePerToken: (0, process_1.summarizeTimePerToken)(dataflowTimesPerToken),
|
|
66
80
|
totalCommonTimePerToken: (0, process_1.summarizeTimePerToken)(totalCommonTimesPerToken),
|
|
81
|
+
controlFlowTimePerToken: controlFlowTimePerToken.length > 0 ? (0, process_1.summarizeTimePerToken)(controlFlowTimePerToken) : undefined,
|
|
82
|
+
dataFrameShapeTimePerToken: dataFrameShapeTimePerToken.length > 0 ? (0, process_1.summarizeTimePerToken)(dataFrameShapeTimePerToken) : undefined,
|
|
67
83
|
failedToRepParse,
|
|
68
84
|
timesHitThreshold,
|
|
69
85
|
reduction: (0, process_1.summarizeSummarizedReductions)(reductions),
|
|
@@ -89,7 +105,43 @@ function summarizeAllSummarizedStats(stats) {
|
|
|
89
105
|
storedVertexIndices: (0, summarizer_1.summarizeMeasurement)(dataflows.map(d => d.storedVertexIndices)),
|
|
90
106
|
storedEnvIndices: (0, summarizer_1.summarizeMeasurement)(dataflows.map(d => d.storedEnvIndices)),
|
|
91
107
|
overwrittenIndices: (0, summarizer_1.summarizeMeasurement)(dataflows.map(d => d.overwrittenIndices)),
|
|
92
|
-
}
|
|
108
|
+
},
|
|
109
|
+
dataFrameShape: stats.some(s => s.dataFrameShape !== undefined) ? {
|
|
110
|
+
numberOfDataFrameFiles: (0, arrays_1.arraySum)(stats.map(s => s.dataFrameShape?.numberOfDataFrameFiles).filter(assert_1.isNotUndefined)),
|
|
111
|
+
numberOfNonDataFrameFiles: (0, arrays_1.arraySum)(stats.map(s => s.dataFrameShape?.numberOfNonDataFrameFiles).filter(assert_1.isNotUndefined)),
|
|
112
|
+
numberOfResultConstraints: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultConstraints).filter(assert_1.isNotUndefined)),
|
|
113
|
+
numberOfResultingValues: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultingValues).filter(assert_1.isNotUndefined)),
|
|
114
|
+
numberOfResultingTop: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultingTop).filter(assert_1.isNotUndefined)),
|
|
115
|
+
numberOfResultingBottom: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultingBottom).filter(assert_1.isNotUndefined)),
|
|
116
|
+
numberOfEmptyNodes: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfEmptyNodes).filter(assert_1.isNotUndefined)),
|
|
117
|
+
numberOfOperationNodes: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfOperationNodes).filter(assert_1.isNotUndefined)),
|
|
118
|
+
numberOfValueNodes: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfValueNodes).filter(assert_1.isNotUndefined)),
|
|
119
|
+
sizeOfInfo: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.sizeOfInfo).filter(assert_1.isNotUndefined)),
|
|
120
|
+
numberOfEntriesPerNode: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfEntriesPerNode).filter(assert_1.isNotUndefined)),
|
|
121
|
+
numberOfOperations: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfOperations).filter(assert_1.isNotUndefined)),
|
|
122
|
+
numberOfTotalValues: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfTotalValues).filter(assert_1.isNotUndefined)),
|
|
123
|
+
numberOfTotalTop: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfTotalTop).filter(assert_1.isNotUndefined)),
|
|
124
|
+
numberOfTotalBottom: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfTotalBottom).filter(assert_1.isNotUndefined)),
|
|
125
|
+
inferredColNames: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.inferredColNames).filter(assert_1.isNotUndefined)),
|
|
126
|
+
numberOfColNamesValues: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColNamesValues).filter(assert_1.isNotUndefined)),
|
|
127
|
+
numberOfColNamesTop: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColNamesTop).filter(assert_1.isNotUndefined)),
|
|
128
|
+
numberOfColNamesBottom: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColNamesBottom).filter(assert_1.isNotUndefined)),
|
|
129
|
+
inferredColCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.inferredColCount).filter(assert_1.isNotUndefined)),
|
|
130
|
+
numberOfColCountExact: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountExact).filter(assert_1.isNotUndefined)),
|
|
131
|
+
numberOfColCountValues: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountValues).filter(assert_1.isNotUndefined)),
|
|
132
|
+
numberOfColCountTop: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountTop).filter(assert_1.isNotUndefined)),
|
|
133
|
+
numberOfColCountInfinite: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountInfinite).filter(assert_1.isNotUndefined)),
|
|
134
|
+
numberOfColCountBottom: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountBottom).filter(assert_1.isNotUndefined)),
|
|
135
|
+
approxRangeColCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.approxRangeColCount).filter(assert_1.isNotUndefined)),
|
|
136
|
+
inferredRowCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.inferredRowCount).filter(assert_1.isNotUndefined)),
|
|
137
|
+
numberOfRowCountExact: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountExact).filter(assert_1.isNotUndefined)),
|
|
138
|
+
numberOfRowCountValues: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountValues).filter(assert_1.isNotUndefined)),
|
|
139
|
+
numberOfRowCountTop: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountTop).filter(assert_1.isNotUndefined)),
|
|
140
|
+
numberOfRowCountInfinite: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountInfinite).filter(assert_1.isNotUndefined)),
|
|
141
|
+
numberOfRowCountBottom: (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountBottom).filter(assert_1.isNotUndefined)),
|
|
142
|
+
approxRangeRowCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.approxRangeRowCount).filter(assert_1.isNotUndefined)),
|
|
143
|
+
perOperationNumber: new Map(semantics_1.DataFrameOperationNames.map(n => [n, (0, summarizer_1.summarizeMeasurement)(stats.map(s => s.dataFrameShape?.perOperationNumber.get(n) ?? 0))]))
|
|
144
|
+
} : undefined
|
|
93
145
|
};
|
|
94
146
|
}
|
|
95
147
|
function summarizeAllUltimateStats(stats) {
|
|
@@ -100,7 +152,7 @@ function summarizeAllUltimateStats(stats) {
|
|
|
100
152
|
failedToRepParse: Math.max(...stats.map(s => s.failedToRepParse)),
|
|
101
153
|
timesHitThreshold: Math.max(...stats.map(s => s.timesHitThreshold)),
|
|
102
154
|
// average out / summarize other measurements
|
|
103
|
-
commonMeasurements: new Map(stats_1.CommonSlicerMeasurements.map(m => [m, (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.commonMeasurements.get(m)))])),
|
|
155
|
+
commonMeasurements: new Map(stats_1.CommonSlicerMeasurements.filter(m => stats.some(s => s.commonMeasurements.has(m))).map(m => [m, (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.commonMeasurements.get(m)))])),
|
|
104
156
|
perSliceMeasurements: new Map(stats_1.PerSliceMeasurements.map(m => [m, (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.perSliceMeasurements.get(m)))])),
|
|
105
157
|
sliceTimePerToken: (0, process_1.summarizeSummarizedTimePerToken)(stats.map(s => s.sliceTimePerToken)),
|
|
106
158
|
reconstructTimePerToken: (0, process_1.summarizeSummarizedTimePerToken)(stats.map(s => s.reconstructTimePerToken)),
|
|
@@ -109,6 +161,8 @@ function summarizeAllUltimateStats(stats) {
|
|
|
109
161
|
normalizeTimePerToken: (0, process_1.summarizeSummarizedTimePerToken)(stats.map(s => s.normalizeTimePerToken)),
|
|
110
162
|
dataflowTimePerToken: (0, process_1.summarizeSummarizedTimePerToken)(stats.map(s => s.dataflowTimePerToken)),
|
|
111
163
|
totalCommonTimePerToken: (0, process_1.summarizeSummarizedTimePerToken)(stats.map(s => s.totalCommonTimePerToken)),
|
|
164
|
+
controlFlowTimePerToken: stats.some(s => s.controlFlowTimePerToken !== undefined) ? (0, process_1.summarizeSummarizedTimePerToken)(stats.map(s => s.controlFlowTimePerToken).filter(assert_1.isNotUndefined)) : undefined,
|
|
165
|
+
dataFrameShapeTimePerToken: stats.some(s => s.dataFrameShapeTimePerToken !== undefined) ? (0, process_1.summarizeSummarizedTimePerToken)(stats.map(s => s.dataFrameShapeTimePerToken).filter(assert_1.isNotUndefined)) : undefined,
|
|
112
166
|
reduction: (0, process_1.summarizeSummarizedReductions)(stats.map(s => s.reduction)),
|
|
113
167
|
reductionNoFluff: (0, process_1.summarizeSummarizedReductions)(stats.map(s => s.reductionNoFluff)),
|
|
114
168
|
input: {
|
|
@@ -132,7 +186,43 @@ function summarizeAllUltimateStats(stats) {
|
|
|
132
186
|
storedVertexIndices: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataflow.storedVertexIndices)),
|
|
133
187
|
storedEnvIndices: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataflow.storedEnvIndices)),
|
|
134
188
|
overwrittenIndices: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataflow.overwrittenIndices)),
|
|
135
|
-
}
|
|
189
|
+
},
|
|
190
|
+
dataFrameShape: stats.some(s => s.dataFrameShape !== undefined) ? {
|
|
191
|
+
numberOfDataFrameFiles: (0, arrays_1.arraySum)(stats.map(s => s.dataFrameShape?.numberOfDataFrameFiles).filter(assert_1.isNotUndefined)),
|
|
192
|
+
numberOfNonDataFrameFiles: (0, arrays_1.arraySum)(stats.map(s => s.dataFrameShape?.numberOfNonDataFrameFiles).filter(assert_1.isNotUndefined)),
|
|
193
|
+
numberOfResultConstraints: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultConstraints).filter(assert_1.isNotUndefined)),
|
|
194
|
+
numberOfResultingValues: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultingValues).filter(assert_1.isNotUndefined)),
|
|
195
|
+
numberOfResultingTop: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultingTop).filter(assert_1.isNotUndefined)),
|
|
196
|
+
numberOfResultingBottom: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfResultingBottom).filter(assert_1.isNotUndefined)),
|
|
197
|
+
numberOfEmptyNodes: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfEmptyNodes).filter(assert_1.isNotUndefined)),
|
|
198
|
+
numberOfOperationNodes: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfOperationNodes).filter(assert_1.isNotUndefined)),
|
|
199
|
+
numberOfValueNodes: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfValueNodes).filter(assert_1.isNotUndefined)),
|
|
200
|
+
sizeOfInfo: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.sizeOfInfo).filter(assert_1.isNotUndefined)),
|
|
201
|
+
numberOfEntriesPerNode: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfEntriesPerNode).filter(assert_1.isNotUndefined)),
|
|
202
|
+
numberOfOperations: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfOperations).filter(assert_1.isNotUndefined)),
|
|
203
|
+
numberOfTotalValues: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfTotalValues).filter(assert_1.isNotUndefined)),
|
|
204
|
+
numberOfTotalTop: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfTotalTop).filter(assert_1.isNotUndefined)),
|
|
205
|
+
numberOfTotalBottom: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfTotalBottom).filter(assert_1.isNotUndefined)),
|
|
206
|
+
inferredColNames: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.inferredColNames).filter(assert_1.isNotUndefined)),
|
|
207
|
+
numberOfColNamesValues: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColNamesValues).filter(assert_1.isNotUndefined)),
|
|
208
|
+
numberOfColNamesTop: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColNamesTop).filter(assert_1.isNotUndefined)),
|
|
209
|
+
numberOfColNamesBottom: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColNamesBottom).filter(assert_1.isNotUndefined)),
|
|
210
|
+
inferredColCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.inferredColCount).filter(assert_1.isNotUndefined)),
|
|
211
|
+
numberOfColCountExact: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountExact).filter(assert_1.isNotUndefined)),
|
|
212
|
+
numberOfColCountValues: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountValues).filter(assert_1.isNotUndefined)),
|
|
213
|
+
numberOfColCountTop: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountTop).filter(assert_1.isNotUndefined)),
|
|
214
|
+
numberOfColCountInfinite: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountInfinite).filter(assert_1.isNotUndefined)),
|
|
215
|
+
numberOfColCountBottom: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfColCountBottom).filter(assert_1.isNotUndefined)),
|
|
216
|
+
approxRangeColCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.approxRangeColCount).filter(assert_1.isNotUndefined)),
|
|
217
|
+
inferredRowCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.inferredRowCount).filter(assert_1.isNotUndefined)),
|
|
218
|
+
numberOfRowCountExact: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountExact).filter(assert_1.isNotUndefined)),
|
|
219
|
+
numberOfRowCountValues: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountValues).filter(assert_1.isNotUndefined)),
|
|
220
|
+
numberOfRowCountTop: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountTop).filter(assert_1.isNotUndefined)),
|
|
221
|
+
numberOfRowCountInfinite: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountInfinite).filter(assert_1.isNotUndefined)),
|
|
222
|
+
numberOfRowCountBottom: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.numberOfRowCountBottom).filter(assert_1.isNotUndefined)),
|
|
223
|
+
approxRangeRowCount: (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.approxRangeRowCount).filter(assert_1.isNotUndefined)),
|
|
224
|
+
perOperationNumber: new Map(semantics_1.DataFrameOperationNames.map(n => [n, (0, process_1.summarizeSummarizedMeasurement)(stats.map(s => s.dataFrameShape?.perOperationNumber.get(n)).filter(assert_1.isNotUndefined))]))
|
|
225
|
+
} : undefined
|
|
136
226
|
};
|
|
137
227
|
}
|
|
138
228
|
function processNextSummary(line, allSummarized) {
|
|
@@ -152,7 +242,11 @@ function processNextSummary(line, allSummarized) {
|
|
|
152
242
|
...got.summarize.perSliceMeasurements,
|
|
153
243
|
// restore maps
|
|
154
244
|
measurements: new Map(got.summarize.perSliceMeasurements.measurements),
|
|
155
|
-
}
|
|
245
|
+
},
|
|
246
|
+
dataFrameShape: got.summarize.dataFrameShape !== undefined ? {
|
|
247
|
+
...got.summarize.dataFrameShape,
|
|
248
|
+
perOperationNumber: new Map(got.summarize.dataFrameShape.perOperationNumber)
|
|
249
|
+
} : undefined
|
|
156
250
|
}
|
|
157
251
|
};
|
|
158
252
|
allSummarized.push(got.summarize);
|
|
@@ -164,6 +258,10 @@ function processNextUltimateSummary(line, allSummarized) {
|
|
|
164
258
|
// restore maps
|
|
165
259
|
commonMeasurements: new Map(got.commonMeasurements),
|
|
166
260
|
perSliceMeasurements: new Map(got.perSliceMeasurements),
|
|
261
|
+
dataFrameShape: got.dataFrameShape !== undefined ? {
|
|
262
|
+
...got.dataFrameShape,
|
|
263
|
+
perOperationNumber: new Map(got.dataFrameShape.perOperationNumber)
|
|
264
|
+
} : undefined
|
|
167
265
|
};
|
|
168
266
|
allSummarized.push(got);
|
|
169
267
|
}
|
package/cli/benchmark-app.d.ts
CHANGED
|
@@ -10,9 +10,11 @@ export interface BenchmarkCliOptions {
|
|
|
10
10
|
runs?: number;
|
|
11
11
|
seed?: string;
|
|
12
12
|
parser: KnownParserName;
|
|
13
|
+
'dataframe-shape-inference': boolean;
|
|
13
14
|
'enable-pointer-tracking': boolean;
|
|
14
15
|
'max-file-slices': number;
|
|
15
16
|
threshold?: number;
|
|
16
17
|
'per-file-time-limit'?: number;
|
|
17
18
|
'sampling-strategy': string;
|
|
19
|
+
cfg?: boolean;
|
|
18
20
|
}
|
package/cli/benchmark-app.js
CHANGED
|
@@ -69,11 +69,13 @@ async function benchmark() {
|
|
|
69
69
|
'--output', path_1.default.join(options.output, path_1.default.relative(f.baseDir, `${f.request.content}.json`)),
|
|
70
70
|
'--slice', options.slice, ...verboseAdd,
|
|
71
71
|
'--parser', options.parser,
|
|
72
|
+
...(options['dataframe-shape-inference'] ? ['--dataframe-shape-inference'] : []),
|
|
72
73
|
...(options['enable-pointer-tracking'] ? ['--enable-pointer-tracking'] : []),
|
|
73
74
|
'--max-slices', `${options['max-file-slices']}`,
|
|
74
75
|
...(options.threshold ? ['--threshold', `${options.threshold}`] : []),
|
|
75
76
|
'--sampling-strategy', options['sampling-strategy'],
|
|
76
77
|
...(options.seed ? ['--seed', options.seed] : []),
|
|
78
|
+
...(options.cfg ? ['--cfg'] : []),
|
|
77
79
|
]);
|
|
78
80
|
const runs = options.runs ?? 1;
|
|
79
81
|
for (let i = 1; i <= runs; i++) {
|
|
@@ -8,8 +8,10 @@ export interface SingleBenchmarkCliOptions {
|
|
|
8
8
|
slice: string;
|
|
9
9
|
output?: string;
|
|
10
10
|
parser: KnownParserName;
|
|
11
|
+
'dataframe-shape-inference': boolean;
|
|
11
12
|
'enable-pointer-tracking': boolean;
|
|
12
13
|
'max-slices': number;
|
|
14
|
+
'cfg': boolean;
|
|
13
15
|
threshold?: number;
|
|
14
16
|
'sampling-strategy': string;
|
|
15
17
|
seed?: string;
|
|
@@ -34,13 +34,12 @@ async function benchmark() {
|
|
|
34
34
|
const prefix = `[${options.input}${options['file-id'] !== undefined ? ` (file ${options['file-id']}, run ${options['run-num']})` : ''}]`;
|
|
35
35
|
console.log(`${prefix} Appending output to ${options.output}`);
|
|
36
36
|
const directory = path_1.default.parse(options.output).dir;
|
|
37
|
-
// ensure the directory exists if path contains one
|
|
37
|
+
// ensure the directory exists if the path contains one
|
|
38
38
|
if (directory !== '') {
|
|
39
39
|
fs_1.default.mkdirSync(directory, { recursive: true });
|
|
40
40
|
}
|
|
41
41
|
// Enable pointer analysis if requested, otherwise disable it
|
|
42
|
-
const config = (0, config_1.getConfig)()
|
|
43
|
-
(0, config_1.amendConfig)(config, c => {
|
|
42
|
+
const config = (0, config_1.amendConfig)((0, config_1.getConfig)(), c => {
|
|
44
43
|
c.solver.pointerTracking = options['enable-pointer-tracking'];
|
|
45
44
|
return c;
|
|
46
45
|
});
|
|
@@ -70,6 +69,14 @@ async function benchmark() {
|
|
|
70
69
|
(0, assert_1.guard)(count >= 0, `Number of slices exceeded limit of ${maxSlices} with ${-count} slices, skipping in count`);
|
|
71
70
|
(0, assert_1.guard)(count > 0, `No possible slices found for ${options.input}, skipping in count`);
|
|
72
71
|
}
|
|
72
|
+
if (options['cfg'] || options['dataframe-shape-inference']) {
|
|
73
|
+
slicer.extractCFG();
|
|
74
|
+
}
|
|
75
|
+
if (options['dataframe-shape-inference']) {
|
|
76
|
+
console.log(`${prefix} Performing shape inference for data frames`);
|
|
77
|
+
slicer.inferDataFrameShapes();
|
|
78
|
+
console.log(`${prefix} Completed data frame shape inference`);
|
|
79
|
+
}
|
|
73
80
|
const { stats } = slicer.finish();
|
|
74
81
|
const output = {
|
|
75
82
|
filename: options.input,
|
package/cli/common/options.js
CHANGED
|
@@ -22,11 +22,13 @@ exports.benchmarkOptions = [
|
|
|
22
22
|
{ 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}' },
|
|
23
23
|
{ name: 'output', alias: 'o', type: String, description: `Folder to write all the measurements to in a per-file-basis (defaults to {italic benchmark-${StartTimeString}})`, defaultValue: `benchmark-${StartTimeString}`, typeLabel: '{underline folder}' },
|
|
24
24
|
{ name: 'parser', type: String, description: 'The parser to use for the benchmark', defaultValue: 'r-shell', typeLabel: '{underline parser}' },
|
|
25
|
+
{ name: 'dataframe-shape-inference', type: Boolean, description: 'Infer the shape of data frames using abstract interpretation (includes control flow graph extraction)', defaultValue: false },
|
|
25
26
|
{ name: 'enable-pointer-tracking', type: Boolean, description: 'Run dataflow analysis with pointer tracking', defaultValue: false },
|
|
26
27
|
{ name: 'max-file-slices', type: Number, description: 'If file has more than passed number of slices, the file is not processed', defaultValue: -1, typeLabel: '{underline number}' },
|
|
27
28
|
{ name: 'threshold', alias: 't', type: Number, description: 'How many re-visits of the same node are ok?', defaultValue: undefined, typeLabel: '{underline number}' },
|
|
28
29
|
{ name: 'per-file-time-limit', type: Number, description: 'Time limit in milliseconds to process single file (disabled by default)', defaultValue: undefined, typeLabel: '{underline number}' },
|
|
29
30
|
{ name: 'sampling-strategy', type: String, description: 'Which strategy to use, when sampling is enabled', defaultValue: 'random', typeLabel: '{underline random/equidistant}' },
|
|
31
|
+
{ name: 'cfg', alias: 'c', type: Boolean, description: 'Extract the control flow graph of the file (benchmark it too)' }
|
|
30
32
|
];
|
|
31
33
|
exports.benchmarkHelperOptions = [
|
|
32
34
|
{ name: 'verbose', alias: 'v', type: Boolean, description: 'Run with verbose logging [do not use for the real benchmark as this affects the time measurements, but only to find errors]' },
|
|
@@ -35,8 +37,10 @@ exports.benchmarkHelperOptions = [
|
|
|
35
37
|
{ 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' },
|
|
36
38
|
{ name: 'run-num', alias: 'r', type: Number, description: 'The n-th time that the file with the given file-id is being benchmarked' },
|
|
37
39
|
{ 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}' },
|
|
40
|
+
{ name: 'cfg', alias: 'c', type: Boolean, description: 'Extract the control flow graph of the file (benchmark it too)' },
|
|
38
41
|
{ name: 'output', alias: 'o', type: String, description: 'File to write the measurements to (appends a single line in JSON format)', typeLabel: '{underline file}' },
|
|
39
42
|
{ name: 'parser', type: String, description: 'The parser to use for the benchmark', defaultValue: 'r-shell', typeLabel: '{underline parser}' },
|
|
43
|
+
{ name: 'dataframe-shape-inference', type: Boolean, description: 'Infer the shape of data frames using abstract interpretation (includes control flow graph extraction)', defaultValue: false },
|
|
40
44
|
{ name: 'enable-pointer-tracking', type: Boolean, description: 'Run dataflow analysis with pointer tracking', defaultValue: false },
|
|
41
45
|
{ name: 'max-slices', type: Number, description: 'If file has more than passed number of slices, the file is not processed', defaultValue: -1, typeLabel: '{underline number}' },
|
|
42
46
|
{ name: 'threshold', alias: 't', type: Number, description: 'How many re-visits of the same node are ok?', defaultValue: undefined, typeLabel: '{underline number}' },
|
|
@@ -59,7 +59,7 @@ async function processQueryArgs(line, parser, output, config) {
|
|
|
59
59
|
}
|
|
60
60
|
const processed = await getDataflow(config, parser, args.join(' '));
|
|
61
61
|
return {
|
|
62
|
-
query: (0, query_1.executeQueries)({ dataflow: processed.dataflow, ast: processed.normalize, config: config }, parsedQuery),
|
|
62
|
+
query: await Promise.resolve((0, query_1.executeQueries)({ dataflow: processed.dataflow, ast: processed.normalize, config: config }, parsedQuery)),
|
|
63
63
|
processed
|
|
64
64
|
};
|
|
65
65
|
}
|
|
@@ -348,11 +348,20 @@ class FlowRServerConnection {
|
|
|
348
348
|
const { dataflow: dfg, normalize: ast } = fileInformation.pipeline.getResults(true);
|
|
349
349
|
(0, assert_1.guard)(dfg !== undefined, `Dataflow graph must be present (request: ${request.filetoken})`);
|
|
350
350
|
(0, assert_1.guard)(ast !== undefined, `AST must be present (request: ${request.filetoken})`);
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
351
|
+
void Promise.resolve((0, query_1.executeQueries)({ dataflow: dfg, ast, config: this.config }, request.query)).then(results => {
|
|
352
|
+
(0, send_1.sendMessage)(this.socket, {
|
|
353
|
+
type: 'response-query',
|
|
354
|
+
id: request.id,
|
|
355
|
+
results
|
|
356
|
+
});
|
|
357
|
+
}).catch(e => {
|
|
358
|
+
this.logger.error(`[${this.name}] Error while executing query: ${String(e)}`);
|
|
359
|
+
(0, send_1.sendMessage)(this.socket, {
|
|
360
|
+
id: request.id,
|
|
361
|
+
type: 'error',
|
|
362
|
+
fatal: false,
|
|
363
|
+
reason: `Error while executing query: ${String(e)}`
|
|
364
|
+
});
|
|
356
365
|
});
|
|
357
366
|
}
|
|
358
367
|
}
|
package/config.d.ts
CHANGED
|
@@ -145,6 +145,37 @@ export interface FlowrConfigOptions extends MergeableRecord {
|
|
|
145
145
|
readonly threshold?: number;
|
|
146
146
|
};
|
|
147
147
|
};
|
|
148
|
+
/**
|
|
149
|
+
* Configuration options for abstract interpretation
|
|
150
|
+
*/
|
|
151
|
+
readonly abstractInterpretation: {
|
|
152
|
+
/**
|
|
153
|
+
* The configuration of the shape inference for data frames
|
|
154
|
+
*/
|
|
155
|
+
readonly dataFrame: {
|
|
156
|
+
/**
|
|
157
|
+
* The maximum number of columns names to infer for data frames before over-approximating the column names to top
|
|
158
|
+
*/
|
|
159
|
+
readonly maxColNames: number;
|
|
160
|
+
/**
|
|
161
|
+
* The threshold for the number of visitations of a node at which widening should be performed to ensure the termination of the fixpoint iteration
|
|
162
|
+
*/
|
|
163
|
+
readonly wideningThreshold: number;
|
|
164
|
+
/**
|
|
165
|
+
* Configuration options for reading data frame shapes from loaded external data files, such as CSV files
|
|
166
|
+
*/
|
|
167
|
+
readonly readLoadedData: {
|
|
168
|
+
/**
|
|
169
|
+
* Whether data frame shapes should be extracted from loaded external data files, such as CSV files
|
|
170
|
+
*/
|
|
171
|
+
readonly readExternalFiles: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* The maximum number of lines to read when extracting data frame shapes from loaded files, such as CSV files
|
|
174
|
+
*/
|
|
175
|
+
readonly maxReadLines: number;
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
};
|
|
148
179
|
}
|
|
149
180
|
export interface TreeSitterEngineConfig extends MergeableRecord {
|
|
150
181
|
readonly type: 'tree-sitter';
|
package/config.js
CHANGED
|
@@ -81,6 +81,16 @@ exports.defaultConfigOptions = {
|
|
|
81
81
|
slicer: {
|
|
82
82
|
threshold: 50
|
|
83
83
|
}
|
|
84
|
+
},
|
|
85
|
+
abstractInterpretation: {
|
|
86
|
+
dataFrame: {
|
|
87
|
+
maxColNames: 50,
|
|
88
|
+
wideningThreshold: 4,
|
|
89
|
+
readLoadedData: {
|
|
90
|
+
readExternalFiles: true,
|
|
91
|
+
maxReadLines: 1e6
|
|
92
|
+
}
|
|
93
|
+
}
|
|
84
94
|
}
|
|
85
95
|
};
|
|
86
96
|
exports.flowrConfigFileSchema = joi_1.default.object({
|
|
@@ -120,7 +130,17 @@ exports.flowrConfigFileSchema = joi_1.default.object({
|
|
|
120
130
|
slicer: joi_1.default.object({
|
|
121
131
|
threshold: joi_1.default.number().optional().description('The maximum number of iterations to perform on a single function call during slicing.')
|
|
122
132
|
}).optional().description('The configuration for the slicer.')
|
|
123
|
-
}).description('How to resolve constants, constraints, cells, ...')
|
|
133
|
+
}).description('How to resolve constants, constraints, cells, ...'),
|
|
134
|
+
abstractInterpretation: joi_1.default.object({
|
|
135
|
+
dataFrame: joi_1.default.object({
|
|
136
|
+
maxColNames: joi_1.default.number().min(0).description('The maximum number of columns names to infer for data frames before over-approximating the column names to top.'),
|
|
137
|
+
wideningThreshold: joi_1.default.number().min(1).description('The threshold for the number of visitations of a node at which widening should be performed to ensure the termination of the fixpoint iteration.'),
|
|
138
|
+
readLoadedData: joi_1.default.object({
|
|
139
|
+
readExternalFiles: joi_1.default.boolean().description('Whether data frame shapes should be extracted from loaded external files, such as CSV files.'),
|
|
140
|
+
maxReadLines: joi_1.default.number().min(1).description('The maximum number of lines to read when extracting data frame shapes from loaded files, such as CSV files.')
|
|
141
|
+
}).description('Configuration options for reading data frame shapes from loaded external data files, such as CSV files.')
|
|
142
|
+
}).description('The configuration of the shape inference for data frames.')
|
|
143
|
+
}).description('The configuration options for abstract interpretation.')
|
|
124
144
|
}).description('The configuration file format for flowR.');
|
|
125
145
|
function parseConfig(jsonString) {
|
|
126
146
|
try {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CfgBasicBlockVertex, CfgEndMarkerVertex, CfgExpressionVertex,
|
|
1
|
+
import type { CfgBasicBlockVertex, CfgEndMarkerVertex, CfgExpressionVertex, CfgSimpleVertex, CfgStatementVertex, ControlFlowInformation } from './control-flow-graph';
|
|
2
2
|
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
3
|
export interface BasicCfgGuidedVisitorConfiguration<ControlFlow extends ControlFlowInformation = ControlFlowInformation> {
|
|
4
4
|
readonly controlFlow: ControlFlow;
|
|
@@ -34,6 +34,5 @@ export declare class BasicCfgGuidedVisitor<ControlFlow extends ControlFlowInform
|
|
|
34
34
|
protected onBasicBlockNode(node: CfgBasicBlockVertex): void;
|
|
35
35
|
protected onStatementNode(_node: CfgStatementVertex): void;
|
|
36
36
|
protected onExpressionNode(_node: CfgExpressionVertex): void;
|
|
37
|
-
protected onMidMarkerNode(_node: CfgMidMarkerVertex): void;
|
|
38
37
|
protected onEndMarkerNode(_node: CfgEndMarkerVertex): void;
|
|
39
38
|
}
|
|
@@ -72,9 +72,6 @@ class BasicCfgGuidedVisitor {
|
|
|
72
72
|
case control_flow_graph_1.CfgVertexType.Expression:
|
|
73
73
|
this.onExpressionNode(vertex);
|
|
74
74
|
break;
|
|
75
|
-
case control_flow_graph_1.CfgVertexType.MidMarker:
|
|
76
|
-
this.onMidMarkerNode(vertex);
|
|
77
|
-
break;
|
|
78
75
|
case control_flow_graph_1.CfgVertexType.EndMarker:
|
|
79
76
|
this.onEndMarkerNode(vertex);
|
|
80
77
|
break;
|
|
@@ -103,9 +100,6 @@ class BasicCfgGuidedVisitor {
|
|
|
103
100
|
onExpressionNode(_node) {
|
|
104
101
|
/* does nothing by default */
|
|
105
102
|
}
|
|
106
|
-
onMidMarkerNode(_node) {
|
|
107
|
-
/* does nothing by default */
|
|
108
|
-
}
|
|
109
103
|
onEndMarkerNode(_node) {
|
|
110
104
|
/* does nothing by default */
|
|
111
105
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ControlFlowInformation } from './control-flow-graph';
|
|
2
2
|
import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
3
3
|
import type { DataflowGraph } from '../dataflow/graph/graph';
|
|
4
|
+
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
4
5
|
import { cfgAnalyzeDeadCode } from './cfg-dead-code';
|
|
5
6
|
import type { FlowrConfigOptions } from '../config';
|
|
6
7
|
export interface CfgPassInfo {
|
|
@@ -28,4 +29,9 @@ export declare function simplifyControlFlowInformation(cfg: ControlFlowInformati
|
|
|
28
29
|
declare function cfgRemoveDeadCode(cfg: ControlFlowInformation, _info?: CfgPassInfo): ControlFlowInformation;
|
|
29
30
|
declare function uniqueControlFlowSets(cfg: ControlFlowInformation, _info?: CfgPassInfo): ControlFlowInformation;
|
|
30
31
|
declare function toBasicBlocks(cfg: ControlFlowInformation, _info?: CfgPassInfo): ControlFlowInformation;
|
|
32
|
+
/**
|
|
33
|
+
* Uses {@link visitCfgInOrder} to find all nodes that are reachable from the control flow graph's {@link ControlFlowInformation.entryPoints} and returns them as a set.
|
|
34
|
+
* @param cfg - The control flow graph whose reachable nodes to find.
|
|
35
|
+
*/
|
|
36
|
+
export declare function cfgFindAllReachable(cfg: ControlFlowInformation): Set<NodeId>;
|
|
31
37
|
export {};
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DefaultCfgSimplificationOrder = exports.CfgSimplificationPasses = void 0;
|
|
4
4
|
exports.simplifyControlFlowInformation = simplifyControlFlowInformation;
|
|
5
|
+
exports.cfgFindAllReachable = cfgFindAllReachable;
|
|
5
6
|
const cfg_to_basic_blocks_1 = require("./cfg-to-basic-blocks");
|
|
6
7
|
const simple_visitor_1 = require("./simple-visitor");
|
|
7
8
|
const cfg_dead_code_1 = require("./cfg-dead-code");
|
|
@@ -32,10 +33,7 @@ function simplifyControlFlowInformation(cfg, info, passes = exports.DefaultCfgSi
|
|
|
32
33
|
*/
|
|
33
34
|
function cfgRemoveDeadCode(cfg, _info) {
|
|
34
35
|
// remove every root level node and accompanying vertices that can not be reached from the entry points
|
|
35
|
-
const reachable =
|
|
36
|
-
(0, simple_visitor_1.visitCfgInOrder)(cfg.graph, cfg.entryPoints, node => {
|
|
37
|
-
reachable.add(node);
|
|
38
|
-
});
|
|
36
|
+
const reachable = cfgFindAllReachable(cfg);
|
|
39
37
|
for (const id of cfg.graph.rootIds()) {
|
|
40
38
|
if (!reachable.has(id)) {
|
|
41
39
|
cfg.graph.removeVertex(id);
|
|
@@ -45,15 +43,26 @@ function cfgRemoveDeadCode(cfg, _info) {
|
|
|
45
43
|
}
|
|
46
44
|
function uniqueControlFlowSets(cfg, _info) {
|
|
47
45
|
return {
|
|
48
|
-
returns:
|
|
49
|
-
entryPoints:
|
|
50
|
-
exitPoints:
|
|
51
|
-
breaks:
|
|
52
|
-
nexts:
|
|
46
|
+
returns: Array.from(new Set(cfg.returns)),
|
|
47
|
+
entryPoints: Array.from(new Set(cfg.entryPoints)),
|
|
48
|
+
exitPoints: Array.from(new Set(cfg.exitPoints)),
|
|
49
|
+
breaks: Array.from(new Set(cfg.breaks)),
|
|
50
|
+
nexts: Array.from(new Set(cfg.nexts)),
|
|
53
51
|
graph: cfg.graph
|
|
54
52
|
};
|
|
55
53
|
}
|
|
56
54
|
function toBasicBlocks(cfg, _info) {
|
|
57
55
|
return (0, cfg_to_basic_blocks_1.convertCfgToBasicBlocks)(cfg);
|
|
58
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Uses {@link visitCfgInOrder} to find all nodes that are reachable from the control flow graph's {@link ControlFlowInformation.entryPoints} and returns them as a set.
|
|
59
|
+
* @param cfg - The control flow graph whose reachable nodes to find.
|
|
60
|
+
*/
|
|
61
|
+
function cfgFindAllReachable(cfg) {
|
|
62
|
+
const reachable = new Set();
|
|
63
|
+
(0, simple_visitor_1.visitCfgInOrder)(cfg.graph, cfg.entryPoints, node => {
|
|
64
|
+
reachable.add(node);
|
|
65
|
+
});
|
|
66
|
+
return reachable;
|
|
67
|
+
}
|
|
59
68
|
//# sourceMappingURL=cfg-simplification.js.map
|
|
@@ -2,8 +2,6 @@ import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
|
2
2
|
import type { MergeableRecord } from '../util/objects';
|
|
3
3
|
import type { RFalse, RTrue } from '../r-bridge/lang-4.x/convert-values';
|
|
4
4
|
export declare enum CfgVertexType {
|
|
5
|
-
/** Marks a break point in a construct (e.g., between the name and the value of an argument, or the formals and the body of a function) */
|
|
6
|
-
MidMarker = "mid",
|
|
7
5
|
/** The explicit exit-nodes to ensure the hammock property */
|
|
8
6
|
EndMarker = "end",
|
|
9
7
|
/** something like an if, assignment, ... even though in the classical sense of R they are still expressions */
|
|
@@ -50,10 +48,6 @@ export interface CfgWithRoot extends CfgBaseVertex {
|
|
|
50
48
|
/** the vertex for which this is a marker */
|
|
51
49
|
root: NodeId;
|
|
52
50
|
}
|
|
53
|
-
export interface CfgMidMarkerVertex extends CfgWithRoot {
|
|
54
|
-
type: CfgVertexType.MidMarker;
|
|
55
|
-
kind: string;
|
|
56
|
-
}
|
|
57
51
|
export interface CfgEndMarkerVertex extends CfgWithRoot {
|
|
58
52
|
type: CfgVertexType.EndMarker;
|
|
59
53
|
}
|
|
@@ -65,9 +59,10 @@ export interface CfgBasicBlockVertex extends CfgBaseVertex {
|
|
|
65
59
|
/**
|
|
66
60
|
* A vertex in the {@link ControlFlowGraph}.
|
|
67
61
|
*/
|
|
68
|
-
export type CfgSimpleVertex = CfgStatementVertex | CfgExpressionVertex | CfgBasicBlockVertex |
|
|
62
|
+
export type CfgSimpleVertex = CfgStatementVertex | CfgExpressionVertex | CfgBasicBlockVertex | CfgEndMarkerVertex;
|
|
69
63
|
export declare function equalVertex(a: CfgSimpleVertex, b: CfgSimpleVertex): boolean;
|
|
70
|
-
export declare function isMarkerVertex(vertex: CfgSimpleVertex): vertex is
|
|
64
|
+
export declare function isMarkerVertex(vertex: CfgSimpleVertex): vertex is CfgEndMarkerVertex;
|
|
65
|
+
export declare function getVertexRootId(vertex: CfgSimpleVertex): NodeId;
|
|
71
66
|
interface CfgFlowDependencyEdge extends MergeableRecord {
|
|
72
67
|
label: CfgEdgeType.Fd;
|
|
73
68
|
}
|
|
@@ -4,12 +4,11 @@ exports.ControlFlowGraph = exports.CfgVertexType = void 0;
|
|
|
4
4
|
exports.edgeTypeToString = edgeTypeToString;
|
|
5
5
|
exports.equalVertex = equalVertex;
|
|
6
6
|
exports.isMarkerVertex = isMarkerVertex;
|
|
7
|
+
exports.getVertexRootId = getVertexRootId;
|
|
7
8
|
exports.emptyControlFlowInformation = emptyControlFlowInformation;
|
|
8
9
|
const assert_1 = require("../util/assert");
|
|
9
10
|
var CfgVertexType;
|
|
10
11
|
(function (CfgVertexType) {
|
|
11
|
-
/** Marks a break point in a construct (e.g., between the name and the value of an argument, or the formals and the body of a function) */
|
|
12
|
-
CfgVertexType["MidMarker"] = "mid";
|
|
13
12
|
/** The explicit exit-nodes to ensure the hammock property */
|
|
14
13
|
CfgVertexType["EndMarker"] = "end";
|
|
15
14
|
/** something like an if, assignment, ... even though in the classical sense of R they are still expressions */
|
|
@@ -36,16 +35,16 @@ function equalVertex(a, b) {
|
|
|
36
35
|
else if (a.type === CfgVertexType.Block && b.type === CfgVertexType.Block) {
|
|
37
36
|
return a.elems.length === b.elems.length && a.elems.every((e, i) => e.id === b.elems[i].id);
|
|
38
37
|
}
|
|
39
|
-
else if (a.type === CfgVertexType.MidMarker && b.type === CfgVertexType.MidMarker) {
|
|
40
|
-
return a.kind === b.kind && a.root === b.root;
|
|
41
|
-
}
|
|
42
38
|
else if (a.type === CfgVertexType.EndMarker && b.type === CfgVertexType.EndMarker) {
|
|
43
39
|
return a.root === b.root;
|
|
44
40
|
}
|
|
45
41
|
return true;
|
|
46
42
|
}
|
|
47
43
|
function isMarkerVertex(vertex) {
|
|
48
|
-
return vertex.type === CfgVertexType.
|
|
44
|
+
return vertex.type === CfgVertexType.EndMarker;
|
|
45
|
+
}
|
|
46
|
+
function getVertexRootId(vertex) {
|
|
47
|
+
return isMarkerVertex(vertex) ? vertex.root : vertex.id;
|
|
49
48
|
}
|
|
50
49
|
/**
|
|
51
50
|
* This class represents the control flow graph of an R program.
|
|
@@ -36,7 +36,7 @@ class DataflowAwareCfgGuidedVisitor extends basic_cfg_guided_visitor_1.BasicCfgG
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
visitDataflowNode(node) {
|
|
39
|
-
const dfgVertex = this.getDataflowGraph((0, control_flow_graph_1.
|
|
39
|
+
const dfgVertex = this.getDataflowGraph((0, control_flow_graph_1.getVertexRootId)(node));
|
|
40
40
|
if (!dfgVertex) {
|
|
41
41
|
this.visitUnknown(node);
|
|
42
42
|
return;
|
|
@@ -5,12 +5,12 @@ import type { ControlFlowInformation } from './control-flow-graph';
|
|
|
5
5
|
import type { CfgSimplificationPassName } from './cfg-simplification';
|
|
6
6
|
import type { FlowrConfigOptions } from '../config';
|
|
7
7
|
/**
|
|
8
|
-
* Given a normalized AST this approximates the control flow graph of the program.
|
|
8
|
+
* Given a normalized AST, this approximates the control flow graph of the program.
|
|
9
9
|
* This view is different from the computation of the dataflow graph and may differ,
|
|
10
10
|
* especially because it focuses on intra-procedural analysis.
|
|
11
11
|
*
|
|
12
12
|
* @param ast - the normalized AST
|
|
13
|
-
* @param config - the
|
|
13
|
+
* @param config - the flowR config
|
|
14
14
|
* @param graph - additional dataflow facts to consider by the control flow extraction
|
|
15
15
|
* @param simplifications - a list of simplification passes to apply to the control flow graph
|
|
16
16
|
*
|