@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.
Files changed (101) hide show
  1. package/README.md +41 -29
  2. package/abstract-interpretation/data-frame/absint-visitor.d.ts +2 -3
  3. package/abstract-interpretation/data-frame/absint-visitor.js +14 -16
  4. package/abstract-interpretation/data-frame/mappers/function-mapper.js +3 -3
  5. package/abstract-interpretation/data-frame/semantics.d.ts +1 -1
  6. package/abstract-interpretation/data-frame/semantics.js +7 -10
  7. package/abstract-interpretation/data-frame/shape-inference.js +2 -8
  8. package/benchmark/slicer.js +7 -5
  9. package/benchmark/summarizer/second-phase/graph.js +1 -1
  10. package/benchmark/summarizer/second-phase/process.js +1 -1
  11. package/cli/benchmark-app.d.ts +1 -0
  12. package/cli/benchmark-app.js +1 -0
  13. package/cli/benchmark-helper-app.d.ts +1 -0
  14. package/cli/benchmark-helper-app.js +4 -3
  15. package/cli/common/options.js +2 -0
  16. package/cli/repl/commands/repl-query.js +1 -1
  17. package/cli/repl/server/connection.js +14 -5
  18. package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
  19. package/control-flow/basic-cfg-guided-visitor.js +0 -6
  20. package/control-flow/cfg-simplification.d.ts +6 -0
  21. package/control-flow/cfg-simplification.js +18 -9
  22. package/control-flow/control-flow-graph.d.ts +2 -8
  23. package/control-flow/control-flow-graph.js +1 -6
  24. package/control-flow/extract-cfg.d.ts +2 -2
  25. package/control-flow/extract-cfg.js +52 -63
  26. package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
  27. package/core/steps/all/static-slicing/00-slice.js +9 -3
  28. package/core/steps/pipeline/default-pipelines.d.ts +74 -74
  29. package/dataflow/environments/built-in.d.ts +2 -2
  30. package/dataflow/environments/built-in.js +13 -12
  31. package/dataflow/graph/dataflowgraph-builder.js +2 -2
  32. package/dataflow/graph/graph.js +1 -1
  33. package/dataflow/graph/invert-dfg.d.ts +2 -0
  34. package/dataflow/graph/invert-dfg.js +17 -0
  35. package/documentation/doc-util/doc-query.js +1 -1
  36. package/documentation/doc-util/doc-search.js +2 -2
  37. package/documentation/print-cfg-wiki.js +3 -4
  38. package/documentation/print-core-wiki.js +2 -2
  39. package/documentation/print-dataflow-graph-wiki.js +7 -0
  40. package/documentation/print-faq-wiki.js +4 -0
  41. package/documentation/print-linter-wiki.js +32 -4
  42. package/documentation/print-linting-and-testing-wiki.js +13 -1
  43. package/documentation/print-onboarding-wiki.js +4 -0
  44. package/documentation/print-query-wiki.js +12 -3
  45. package/linter/linter-executor.js +1 -2
  46. package/linter/linter-format.d.ts +26 -4
  47. package/linter/linter-format.js +25 -6
  48. package/linter/linter-rules.d.ts +40 -12
  49. package/linter/linter-rules.js +3 -1
  50. package/linter/rules/absolute-path.d.ts +4 -7
  51. package/linter/rules/absolute-path.js +9 -6
  52. package/linter/rules/dataframe-access-validation.d.ts +3 -1
  53. package/linter/rules/dataframe-access-validation.js +3 -1
  54. package/linter/rules/dead-code.d.ts +43 -0
  55. package/linter/rules/dead-code.js +50 -0
  56. package/linter/rules/deprecated-functions.d.ts +3 -2
  57. package/linter/rules/deprecated-functions.js +3 -1
  58. package/linter/rules/file-path-validity.d.ts +4 -4
  59. package/linter/rules/file-path-validity.js +8 -6
  60. package/linter/rules/naming-convention.d.ts +4 -3
  61. package/linter/rules/naming-convention.js +3 -1
  62. package/linter/rules/seeded-randomness.d.ts +4 -3
  63. package/linter/rules/seeded-randomness.js +3 -1
  64. package/linter/rules/unused-definition.d.ts +2 -0
  65. package/linter/rules/unused-definition.js +3 -1
  66. package/package.json +1 -1
  67. package/queries/catalog/dependencies-query/dependencies-query-executor.js +6 -1
  68. package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -0
  69. package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
  70. package/queries/catalog/linter-query/linter-query-format.js +1 -1
  71. package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
  72. package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
  73. package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
  74. package/queries/catalog/search-query/search-query-executor.js +1 -1
  75. package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -1
  76. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
  77. package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
  78. package/queries/query-print.d.ts +1 -1
  79. package/queries/query-print.js +0 -1
  80. package/queries/query.d.ts +16 -5
  81. package/queries/query.js +24 -11
  82. package/search/flowr-search-builder.d.ts +6 -6
  83. package/search/flowr-search-executor.d.ts +2 -2
  84. package/search/flowr-search-executor.js +1 -1
  85. package/search/flowr-search.d.ts +13 -8
  86. package/search/flowr-search.js +21 -0
  87. package/search/search-executor/search-enrichers.d.ts +87 -20
  88. package/search/search-executor/search-enrichers.js +44 -5
  89. package/search/search-executor/search-generators.d.ts +4 -4
  90. package/search/search-executor/search-generators.js +12 -7
  91. package/search/search-executor/search-mappers.js +3 -2
  92. package/search/search-executor/search-transformer.d.ts +3 -3
  93. package/search/search-executor/search-transformer.js +2 -2
  94. package/slicing/static/static-slicer.d.ts +4 -2
  95. package/slicing/static/static-slicer.js +10 -4
  96. package/util/collections/arrays.d.ts +2 -0
  97. package/util/collections/arrays.js +9 -0
  98. package/util/mermaid/dfg.js +4 -2
  99. package/util/range.d.ts +1 -0
  100. package/util/range.js +5 -1
  101. 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 = new Set();
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: [...new Set(cfg.returns)],
49
- entryPoints: [...new Set(cfg.entryPoints)],
50
- exitPoints: [...new Set(cfg.exitPoints)],
51
- breaks: [...new Set(cfg.breaks)],
52
- nexts: [...new Set(cfg.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 | CfgMidMarkerVertex | CfgEndMarkerVertex;
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 CfgMidMarkerVertex | CfgEndMarkerVertex;
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.MidMarker || vertex.type === CfgVertexType.EndMarker;
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 Flowr config
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 Flowr config
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: [ifId + '-condition'], end: [ifId + '-exit'] });
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 exitPoint of condition.exitPoints) {
104
- graph.addEdge(ifId + '-condition', exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
105
- }
106
- for (const entryPoint of then.entryPoints) {
107
- graph.addEdge(entryPoint, ifId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: ifId });
108
- }
109
- for (const entryPoint of otherwise?.entryPoints ?? []) {
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
- graph.addEdge(ifId + '-exit', ifId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
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: [whileId + '-condition'], end: [whileId + '-exit'] });
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 exit of condition.exitPoints) {
157
- graph.addEdge(whileId + '-condition', exit, { label: 0 /* CfgEdgeType.Fd */ });
158
- }
159
- for (const entry of body.entryPoints) {
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
- graph.addEdge(whileId + '-exit', whileId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: whileId });
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: [forLoopId + '-head'] });
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
- graph.addVertex({ id: forLoopId + '-head', type: control_flow_graph_1.CfgVertexType.MidMarker, root: forLoopId, kind: 'head' });
187
- for (const exit of variable.exitPoints) {
188
- graph.addEdge(forLoopId + '-head', exit, { label: 0 /* CfgEdgeType.Fd */ });
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
- graph.addEdge(forLoopId + '-exit', forLoopId + '-head', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: forLoopId });
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
- const children = [fnId + '-params', fnId + '-exit'];
214
- graph.addVertex({ id: fnId + '-params', kind: 'parameters', type: control_flow_graph_1.CfgVertexType.MidMarker, root: fnId }, false);
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: [fnId + '-params'], end: [fnId + '-exit'] });
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 (params.length === 0) {
230
- graph.addEdge(fnId + '-params', fnId, { label: 0 /* CfgEdgeType.Fd */ });
230
+ if (paramExits.length === 0) {
231
+ paramExits = [fnId];
231
232
  }
232
- for (const entry of body.entryPoints) {
233
- graph.addEdge(entry, fnId + '-params', { label: 0 /* CfgEdgeType.Fd */ });
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: [callId + '-name'], end: [callId + '-' + exit] });
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 = [callId + '-name'];
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 func-call targets as the call targets contains names and call ids
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
- graph.addVertex({ id: node.info.id, type: control_flow_graph_1.CfgVertexType.Expression, mid: [node.info.id + '-before-value'], end: [node.info.id + '-exit'] });
316
- let currentExitPoint = [node.info.id];
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 currentExitPoint) {
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
- currentExitPoint = value.exitPoints;
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 currentExitPoint) {
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: [access.info.id + '-after-name'], end: [access.info.id + '-exit'] });
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
- for (const exit of name.exitPoints) {
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>, config: FlowrConfigOptions): Readonly<import("../../../../slicing/static/slicer-types").SliceResult>;
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
- function processor(results, input, config) {
7
- return (0, static_slicer_1.staticSlicing)(results.dataflow.graph, results.normalize, input.criterion, input.threshold ?? config.solver.slicer?.threshold);
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',