@eagleoutice/flowr 2.3.0 → 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 +41 -29
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +2 -3
- package/abstract-interpretation/data-frame/absint-visitor.js +14 -16
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +3 -3
- package/abstract-interpretation/data-frame/semantics.d.ts +1 -1
- package/abstract-interpretation/data-frame/semantics.js +7 -10
- package/abstract-interpretation/data-frame/shape-inference.js +2 -8
- package/benchmark/slicer.js +7 -5
- package/benchmark/summarizer/second-phase/graph.js +1 -1
- package/benchmark/summarizer/second-phase/process.js +1 -1
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +1 -0
- package/cli/benchmark-helper-app.d.ts +1 -0
- package/cli/benchmark-helper-app.js +4 -3
- package/cli/common/options.js +2 -0
- package/cli/repl/commands/repl-query.js +1 -1
- package/cli/repl/server/connection.js +14 -5
- 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 +2 -8
- package/control-flow/control-flow-graph.js +1 -6
- package/control-flow/extract-cfg.d.ts +2 -2
- package/control-flow/extract-cfg.js +52 -63
- 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 +2 -2
- package/dataflow/environments/built-in.js +13 -12
- 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/documentation/doc-util/doc-query.js +1 -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-linter-wiki.js +32 -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 +12 -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 +40 -12
- package/linter/linter-rules.js +3 -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 +3 -1
- package/linter/rules/dataframe-access-validation.js +3 -1
- 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 +4 -3
- package/linter/rules/naming-convention.js +3 -1
- 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 +1 -1
- 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/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 +16 -5
- package/queries/query.js +24 -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/mermaid/dfg.js +4 -2
- package/util/range.d.ts +1 -0
- package/util/range.js +5 -1
- package/util/version.js +1 -1
|
@@ -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,9 @@ 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;
|
|
71
65
|
export declare function getVertexRootId(vertex: CfgSimpleVertex): NodeId;
|
|
72
66
|
interface CfgFlowDependencyEdge extends MergeableRecord {
|
|
73
67
|
label: CfgEdgeType.Fd;
|
|
@@ -9,8 +9,6 @@ exports.emptyControlFlowInformation = emptyControlFlowInformation;
|
|
|
9
9
|
const assert_1 = require("../util/assert");
|
|
10
10
|
var CfgVertexType;
|
|
11
11
|
(function (CfgVertexType) {
|
|
12
|
-
/** 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) */
|
|
13
|
-
CfgVertexType["MidMarker"] = "mid";
|
|
14
12
|
/** The explicit exit-nodes to ensure the hammock property */
|
|
15
13
|
CfgVertexType["EndMarker"] = "end";
|
|
16
14
|
/** something like an if, assignment, ... even though in the classical sense of R they are still expressions */
|
|
@@ -37,16 +35,13 @@ function equalVertex(a, b) {
|
|
|
37
35
|
else if (a.type === CfgVertexType.Block && b.type === CfgVertexType.Block) {
|
|
38
36
|
return a.elems.length === b.elems.length && a.elems.every((e, i) => e.id === b.elems[i].id);
|
|
39
37
|
}
|
|
40
|
-
else if (a.type === CfgVertexType.MidMarker && b.type === CfgVertexType.MidMarker) {
|
|
41
|
-
return a.kind === b.kind && a.root === b.root;
|
|
42
|
-
}
|
|
43
38
|
else if (a.type === CfgVertexType.EndMarker && b.type === CfgVertexType.EndMarker) {
|
|
44
39
|
return a.root === b.root;
|
|
45
40
|
}
|
|
46
41
|
return true;
|
|
47
42
|
}
|
|
48
43
|
function isMarkerVertex(vertex) {
|
|
49
|
-
return vertex.type === CfgVertexType.
|
|
44
|
+
return vertex.type === CfgVertexType.EndMarker;
|
|
50
45
|
}
|
|
51
46
|
function getVertexRootId(vertex) {
|
|
52
47
|
return isMarkerVertex(vertex) ? vertex.root : vertex.id;
|
|
@@ -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
|
*
|
|
@@ -52,12 +52,12 @@ function dataflowCfgFolds(dataflowGraph) {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
* Given a normalized AST this approximates the control flow graph of the program.
|
|
55
|
+
* Given a normalized AST, this approximates the control flow graph of the program.
|
|
56
56
|
* This view is different from the computation of the dataflow graph and may differ,
|
|
57
57
|
* especially because it focuses on intra-procedural analysis.
|
|
58
58
|
*
|
|
59
59
|
* @param ast - the normalized AST
|
|
60
|
-
* @param config - the
|
|
60
|
+
* @param config - the flowR config
|
|
61
61
|
* @param graph - additional dataflow facts to consider by the control flow extraction
|
|
62
62
|
* @param simplifications - a list of simplification passes to apply to the control flow graph
|
|
63
63
|
*
|
|
@@ -92,22 +92,20 @@ function identifyMayStatementType(node) {
|
|
|
92
92
|
function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
93
93
|
const ifId = ifNode.info.id;
|
|
94
94
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
95
|
-
graph.addVertex({ id: ifId, type: identifyMayStatementType(ifNode), mid:
|
|
96
|
-
graph.addVertex({ id: ifId + '-condition', kind: 'condition', type: control_flow_graph_1.CfgVertexType.MidMarker, root: ifId });
|
|
95
|
+
graph.addVertex({ id: ifId, type: identifyMayStatementType(ifNode), mid: condition.exitPoints, end: [ifId + '-exit'] });
|
|
97
96
|
graph.addVertex({ id: ifId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: ifId });
|
|
98
97
|
graph.mergeWith(condition.graph);
|
|
99
98
|
graph.mergeWith(then.graph);
|
|
100
99
|
if (otherwise) {
|
|
101
100
|
graph.mergeWith(otherwise.graph);
|
|
102
101
|
}
|
|
103
|
-
for (const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
graph.addEdge(entryPoint, ifId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
|
|
102
|
+
for (const e of condition.exitPoints) {
|
|
103
|
+
for (const entryPoint of then.entryPoints) {
|
|
104
|
+
graph.addEdge(entryPoint, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: ifId });
|
|
105
|
+
}
|
|
106
|
+
for (const entryPoint of otherwise?.entryPoints ?? []) {
|
|
107
|
+
graph.addEdge(entryPoint, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
|
|
108
|
+
}
|
|
111
109
|
}
|
|
112
110
|
for (const entryPoint of condition.entryPoints) {
|
|
113
111
|
graph.addEdge(entryPoint, ifId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
@@ -116,7 +114,9 @@ function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
|
116
114
|
graph.addEdge(ifId + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
117
115
|
}
|
|
118
116
|
if (!otherwise) {
|
|
119
|
-
|
|
117
|
+
for (const e of condition.exitPoints) {
|
|
118
|
+
graph.addEdge(ifId + '-exit', e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
|
|
119
|
+
}
|
|
120
120
|
}
|
|
121
121
|
return {
|
|
122
122
|
graph,
|
|
@@ -146,18 +146,16 @@ function cfgRepeat(repeat, body) {
|
|
|
146
146
|
function cfgWhile(whileLoop, condition, body) {
|
|
147
147
|
const whileId = whileLoop.info.id;
|
|
148
148
|
const graph = condition.graph;
|
|
149
|
-
graph.addVertex({ id: whileId, type: identifyMayStatementType(whileLoop), mid:
|
|
150
|
-
graph.addVertex({ id: whileId + '-condition', kind: 'condition', type: control_flow_graph_1.CfgVertexType.MidMarker, root: whileId });
|
|
149
|
+
graph.addVertex({ id: whileId, type: identifyMayStatementType(whileLoop), mid: condition.exitPoints, end: [whileId + '-exit'] });
|
|
151
150
|
graph.addVertex({ id: whileId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: whileId });
|
|
152
151
|
graph.mergeWith(body.graph);
|
|
153
152
|
for (const entry of condition.entryPoints) {
|
|
154
153
|
graph.addEdge(entry, whileId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
155
154
|
}
|
|
156
|
-
for (const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
graph.addEdge(entry, whileId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: whileId });
|
|
155
|
+
for (const e of condition.exitPoints) {
|
|
156
|
+
for (const entry of body.entryPoints) {
|
|
157
|
+
graph.addEdge(entry, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: whileId });
|
|
158
|
+
}
|
|
161
159
|
}
|
|
162
160
|
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
163
161
|
graph.addEdge(whileId, next, { label: 0 /* CfgEdgeType.Fd */ });
|
|
@@ -166,13 +164,19 @@ function cfgWhile(whileLoop, condition, body) {
|
|
|
166
164
|
graph.addEdge(whileId + '-exit', breakPoint, { label: 0 /* CfgEdgeType.Fd */ });
|
|
167
165
|
}
|
|
168
166
|
// while can break on the condition as well
|
|
169
|
-
|
|
167
|
+
for (const e of condition.exitPoints) {
|
|
168
|
+
graph.addEdge(whileId + '-exit', e, {
|
|
169
|
+
label: 1 /* CfgEdgeType.Cd */,
|
|
170
|
+
when: convert_values_1.RFalse,
|
|
171
|
+
caused: whileId
|
|
172
|
+
});
|
|
173
|
+
}
|
|
170
174
|
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [whileId + '-exit'], entryPoints: [whileId] };
|
|
171
175
|
}
|
|
172
176
|
function cfgFor(forLoop, variable, vector, body) {
|
|
173
177
|
const forLoopId = forLoop.info.id;
|
|
174
178
|
const graph = variable.graph;
|
|
175
|
-
graph.addVertex({ id: forLoopId, type: identifyMayStatementType(forLoop), end: [forLoopId + '-exit'], mid:
|
|
179
|
+
graph.addVertex({ id: forLoopId, type: identifyMayStatementType(forLoop), end: [forLoopId + '-exit'], mid: variable.exitPoints });
|
|
176
180
|
graph.mergeWith(vector.graph);
|
|
177
181
|
graph.mergeWith(body.graph);
|
|
178
182
|
for (const entry of vector.entryPoints) {
|
|
@@ -183,12 +187,10 @@ function cfgFor(forLoop, variable, vector, body) {
|
|
|
183
187
|
graph.addEdge(entry, exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
184
188
|
}
|
|
185
189
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
for (const entry of body.entryPoints) {
|
|
191
|
-
graph.addEdge(entry, forLoopId + '-head', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: forLoopId });
|
|
190
|
+
for (const e of variable.exitPoints) {
|
|
191
|
+
for (const entry of body.entryPoints) {
|
|
192
|
+
graph.addEdge(entry, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: forLoopId });
|
|
193
|
+
}
|
|
192
194
|
}
|
|
193
195
|
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
194
196
|
graph.addEdge(forLoopId, next, { label: 0 /* CfgEdgeType.Fd */ });
|
|
@@ -203,17 +205,19 @@ function cfgFor(forLoop, variable, vector, body) {
|
|
|
203
205
|
type: control_flow_graph_1.CfgVertexType.EndMarker,
|
|
204
206
|
root: forLoopId
|
|
205
207
|
});
|
|
206
|
-
|
|
208
|
+
for (const e of variable.exitPoints) {
|
|
209
|
+
graph.addEdge(forLoopId + '-exit', e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: forLoopId });
|
|
210
|
+
}
|
|
207
211
|
}
|
|
208
212
|
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [forLoopId + '-exit'] : [], entryPoints: [forLoopId] };
|
|
209
213
|
}
|
|
210
214
|
function cfgFunctionDefinition(fn, params, body) {
|
|
211
215
|
const fnId = fn.info.id;
|
|
212
216
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
213
|
-
|
|
214
|
-
|
|
217
|
+
let paramExits = params.flatMap(e => e.exitPoints);
|
|
218
|
+
const children = [...paramExits, fnId + '-exit'];
|
|
215
219
|
graph.addVertex({ id: fnId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: fnId }, false);
|
|
216
|
-
graph.addVertex({ id: fnId, children, type: identifyMayStatementType(fn), mid:
|
|
220
|
+
graph.addVertex({ id: fnId, children, type: identifyMayStatementType(fn), mid: paramExits, end: [fnId + '-exit'] });
|
|
217
221
|
graph.mergeWith(body.graph, true);
|
|
218
222
|
children.push(...body.graph.rootIds());
|
|
219
223
|
for (const param of params) {
|
|
@@ -222,15 +226,14 @@ function cfgFunctionDefinition(fn, params, body) {
|
|
|
222
226
|
for (const entry of param.entryPoints) {
|
|
223
227
|
graph.addEdge(entry, fnId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
224
228
|
}
|
|
225
|
-
for (const exit of param.exitPoints) {
|
|
226
|
-
graph.addEdge(fnId + '-params', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
227
|
-
}
|
|
228
229
|
}
|
|
229
|
-
if (
|
|
230
|
-
|
|
230
|
+
if (paramExits.length === 0) {
|
|
231
|
+
paramExits = [fnId];
|
|
231
232
|
}
|
|
232
|
-
for (const
|
|
233
|
-
|
|
233
|
+
for (const e of paramExits) {
|
|
234
|
+
for (const entry of body.entryPoints) {
|
|
235
|
+
graph.addEdge(entry, e, { label: 0 /* CfgEdgeType.Fd */ });
|
|
236
|
+
}
|
|
234
237
|
}
|
|
235
238
|
// breaks and nexts should be illegal but safe is safe, I guess
|
|
236
239
|
for (const next of body.returns.concat(body.breaks, body.nexts, body.exitPoints)) {
|
|
@@ -242,16 +245,12 @@ function cfgFunctionCall(call, name, args, exit = 'exit') {
|
|
|
242
245
|
const callId = call.info.id;
|
|
243
246
|
const graph = name.graph;
|
|
244
247
|
const info = { graph, breaks: [...name.breaks], nexts: [...name.nexts], returns: [...name.returns], exitPoints: [callId + '-' + exit], entryPoints: [callId] };
|
|
245
|
-
graph.addVertex({ id: callId, type: identifyMayStatementType(call), mid:
|
|
248
|
+
graph.addVertex({ id: callId, type: identifyMayStatementType(call), mid: name.exitPoints, end: [callId + '-' + exit] });
|
|
246
249
|
for (const entryPoint of name.entryPoints) {
|
|
247
250
|
graph.addEdge(entryPoint, callId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
248
251
|
}
|
|
249
|
-
graph.addVertex({ id: callId + '-name', kind: 'name', type: control_flow_graph_1.CfgVertexType.MidMarker, root: callId });
|
|
250
|
-
for (const exitPoint of name.exitPoints) {
|
|
251
|
-
graph.addEdge(callId + '-name', exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
|
|
252
|
-
}
|
|
253
252
|
graph.addVertex({ id: callId + '-' + exit, type: control_flow_graph_1.CfgVertexType.EndMarker, root: callId });
|
|
254
|
-
let lastArgExits =
|
|
253
|
+
let lastArgExits = name.exitPoints;
|
|
255
254
|
for (const arg of args) {
|
|
256
255
|
if (arg === r_function_call_1.EmptyArgument) {
|
|
257
256
|
continue;
|
|
@@ -283,7 +282,7 @@ function cfgFunctionCallWithDataflow(graph) {
|
|
|
283
282
|
const callVertex = baseCfg.graph.getVertex(call.info.id);
|
|
284
283
|
(0, assert_1.guard)(callVertex !== undefined, 'cfgFunctionCallWithDataflow: call vertex not found');
|
|
285
284
|
for (const target of targets) {
|
|
286
|
-
// we have to filter out non
|
|
285
|
+
// we have to filter out non-func-call targets as the call targets contains names and call ids
|
|
287
286
|
if ((0, vertex_1.isFunctionDefinitionVertex)(graph.getVertex(target))) {
|
|
288
287
|
callVertex.callTargets ??= new Set();
|
|
289
288
|
callVertex.callTargets.add(target);
|
|
@@ -312,8 +311,8 @@ function cfgFunctionCallWithDataflow(graph) {
|
|
|
312
311
|
function cfgArgumentOrParameter(node, name, value) {
|
|
313
312
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
314
313
|
const info = { graph, breaks: [], nexts: [], returns: [], exitPoints: [node.info.id + '-exit'], entryPoints: [node.info.id] };
|
|
315
|
-
|
|
316
|
-
|
|
314
|
+
let currentExitPoints = name?.exitPoints ?? [node.info.id];
|
|
315
|
+
graph.addVertex({ id: node.info.id, type: control_flow_graph_1.CfgVertexType.Expression, mid: currentExitPoints, end: [node.info.id + '-exit'] });
|
|
317
316
|
if (name) {
|
|
318
317
|
graph.mergeWith(name.graph);
|
|
319
318
|
info.breaks = info.breaks.concat(name.breaks);
|
|
@@ -322,27 +321,21 @@ function cfgArgumentOrParameter(node, name, value) {
|
|
|
322
321
|
for (const entry of name.entryPoints) {
|
|
323
322
|
graph.addEdge(entry, node.info.id, { label: 0 /* CfgEdgeType.Fd */ });
|
|
324
323
|
}
|
|
325
|
-
currentExitPoint = name.exitPoints;
|
|
326
324
|
}
|
|
327
|
-
graph.addVertex({ id: node.info.id + '-before-value', kind: 'before-value', type: control_flow_graph_1.CfgVertexType.MidMarker, root: node.info.id });
|
|
328
|
-
for (const exitPoints of currentExitPoint) {
|
|
329
|
-
graph.addEdge(node.info.id + '-before-value', exitPoints, { label: 0 /* CfgEdgeType.Fd */ });
|
|
330
|
-
}
|
|
331
|
-
currentExitPoint = [node.info.id + '-before-value'];
|
|
332
325
|
if (value) {
|
|
333
326
|
graph.mergeWith(value.graph);
|
|
334
327
|
info.breaks = info.breaks.concat(value.breaks);
|
|
335
328
|
info.nexts = info.nexts.concat(value.nexts);
|
|
336
329
|
info.returns = info.returns.concat(value.returns);
|
|
337
|
-
for (const exitPoint of
|
|
330
|
+
for (const exitPoint of currentExitPoints) {
|
|
338
331
|
for (const entry of value.entryPoints) {
|
|
339
332
|
graph.addEdge(entry, exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
|
|
340
333
|
}
|
|
341
334
|
}
|
|
342
|
-
|
|
335
|
+
currentExitPoints = value.exitPoints;
|
|
343
336
|
}
|
|
344
337
|
graph.addVertex({ id: node.info.id + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: node.info.id });
|
|
345
|
-
for (const exit of
|
|
338
|
+
for (const exit of currentExitPoints) {
|
|
346
339
|
graph.addEdge(node.info.id + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
347
340
|
}
|
|
348
341
|
return info;
|
|
@@ -368,16 +361,12 @@ function cfgBinaryOp(binOp, lhs, rhs) {
|
|
|
368
361
|
function cfgAccess(access, name, accessors) {
|
|
369
362
|
const result = { ...name };
|
|
370
363
|
const graph = result.graph;
|
|
371
|
-
graph.addVertex({ id: access.info.id, type: control_flow_graph_1.CfgVertexType.Expression, mid:
|
|
364
|
+
graph.addVertex({ id: access.info.id, type: control_flow_graph_1.CfgVertexType.Expression, mid: name.exitPoints, end: [access.info.id + '-exit'] });
|
|
372
365
|
result.entryPoints = [access.info.id];
|
|
373
366
|
for (const entry of name.entryPoints) {
|
|
374
367
|
graph.addEdge(entry, access.info.id, { label: 0 /* CfgEdgeType.Fd */ });
|
|
375
368
|
}
|
|
376
|
-
|
|
377
|
-
graph.addEdge(access.info.id + '-after-name', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
378
|
-
}
|
|
379
|
-
graph.addVertex({ id: access.info.id + '-after-name', kind: 'after-name', type: control_flow_graph_1.CfgVertexType.MidMarker, root: access.info.id });
|
|
380
|
-
result.exitPoints = [access.info.id + '-after-name'];
|
|
369
|
+
result.exitPoints = name.exitPoints;
|
|
381
370
|
for (const accessor of accessors) {
|
|
382
371
|
if (accessor === r_function_call_1.EmptyArgument) {
|
|
383
372
|
continue;
|
|
@@ -9,11 +9,17 @@ export interface SliceRequiredInput {
|
|
|
9
9
|
readonly criterion: SlicingCriteria;
|
|
10
10
|
/** How many re-visits of the same node are ok? */
|
|
11
11
|
readonly threshold?: number;
|
|
12
|
+
/** The direction to slice in. Defaults to backward slicing if unset. */
|
|
13
|
+
readonly direction?: SliceDirection;
|
|
14
|
+
}
|
|
15
|
+
export declare enum SliceDirection {
|
|
16
|
+
Backward = "backward",
|
|
17
|
+
Forward = "forward"
|
|
12
18
|
}
|
|
13
19
|
declare function processor(results: {
|
|
14
20
|
dataflow?: DataflowInformation;
|
|
15
21
|
normalize?: NormalizedAst;
|
|
16
|
-
}, input: Partial<SliceRequiredInput>,
|
|
22
|
+
}, input: Partial<SliceRequiredInput>, _config: FlowrConfigOptions): Readonly<import("../../../../slicing/static/slicer-types").SliceResult>;
|
|
17
23
|
export declare const STATIC_SLICE: {
|
|
18
24
|
readonly name: "slice";
|
|
19
25
|
readonly humanReadableName: "static slice";
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.STATIC_SLICE = void 0;
|
|
3
|
+
exports.STATIC_SLICE = exports.SliceDirection = void 0;
|
|
4
4
|
const print_1 = require("../../../print/print");
|
|
5
5
|
const static_slicer_1 = require("../../../../slicing/static/static-slicer");
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
var SliceDirection;
|
|
7
|
+
(function (SliceDirection) {
|
|
8
|
+
SliceDirection["Backward"] = "backward";
|
|
9
|
+
SliceDirection["Forward"] = "forward";
|
|
10
|
+
})(SliceDirection || (exports.SliceDirection = SliceDirection = {}));
|
|
11
|
+
function processor(results, input, _config) {
|
|
12
|
+
const direction = input.direction ?? SliceDirection.Backward;
|
|
13
|
+
return (0, static_slicer_1.staticSlice)(results.dataflow.graph, results.normalize, input.criterion, direction, input.threshold);
|
|
8
14
|
}
|
|
9
15
|
exports.STATIC_SLICE = {
|
|
10
16
|
name: 'slice',
|