@eagleoutice/flowr 2.1.8 → 2.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/benchmark/summarizer/first-phase/process.js +6 -5
  2. package/cli/repl/commands/repl-dataflow.js +5 -2
  3. package/cli/repl/commands/repl-normalize.js +5 -2
  4. package/cli/repl/commands/repl-query.js +2 -2
  5. package/cli/repl/server/messages/message-query.js +1 -1
  6. package/dataflow/environments/default-builtin-config.js +45 -6
  7. package/dataflow/environments/environment.d.ts +46 -8
  8. package/dataflow/environments/environment.js +24 -1
  9. package/dataflow/environments/identifier.d.ts +49 -7
  10. package/dataflow/environments/identifier.js +11 -2
  11. package/dataflow/extractor.js +5 -4
  12. package/dataflow/graph/dataflowgraph-builder.d.ts +6 -0
  13. package/dataflow/graph/dataflowgraph-builder.js +8 -0
  14. package/dataflow/graph/edge.d.ts +10 -4
  15. package/dataflow/graph/edge.js +12 -5
  16. package/dataflow/graph/graph.d.ts +41 -3
  17. package/dataflow/graph/graph.js +39 -34
  18. package/dataflow/graph/vertex.d.ts +66 -7
  19. package/dataflow/graph/vertex.js +15 -0
  20. package/dataflow/info.d.ts +79 -11
  21. package/dataflow/info.js +20 -0
  22. package/dataflow/internal/linker.d.ts +4 -2
  23. package/dataflow/internal/linker.js +12 -5
  24. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +2 -0
  25. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -3
  26. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +16 -0
  27. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +83 -6
  28. package/dataflow/internal/process/functions/call/common.js +1 -1
  29. package/documentation/doc-util/doc-dfg.d.ts +0 -1
  30. package/documentation/doc-util/doc-dfg.js +1 -14
  31. package/documentation/print-capabilities-markdown.js +1 -1
  32. package/documentation/print-dataflow-graph-wiki.js +26 -7
  33. package/documentation/print-linting-and-testing-wiki.js +60 -26
  34. package/documentation/print-query-wiki.js +1 -1
  35. package/package.json +17 -3
  36. package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
  37. package/queries/catalog/call-context-query/call-context-query-format.d.ts +13 -0
  38. package/queries/catalog/call-context-query/call-context-query-format.js +3 -1
  39. package/queries/catalog/call-context-query/cascade-action.d.ts +8 -0
  40. package/queries/catalog/call-context-query/cascade-action.js +13 -0
  41. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +11 -1
  42. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +41 -4
  43. package/queries/catalog/dependencies-query/dependencies-query-format.js +4 -0
  44. package/queries/query.d.ts +4 -4
  45. package/queries/query.js +17 -5
  46. package/r-bridge/lang-4.x/ast/model/model.d.ts +3 -0
  47. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +5 -1
  48. package/r-bridge/lang-4.x/ast/model/processing/node-id.d.ts +6 -1
  49. package/r-bridge/lang-4.x/ast/model/processing/node-id.js +6 -1
  50. package/slicing/static/slice-call.d.ts +7 -2
  51. package/slicing/static/slice-call.js +33 -44
  52. package/slicing/static/static-slicer.d.ts +5 -1
  53. package/slicing/static/static-slicer.js +22 -8
  54. package/slicing/static/visiting-queue.d.ts +4 -4
  55. package/slicing/static/visiting-queue.js +5 -3
  56. package/statistics/output/print-stats.js +2 -1
  57. package/statistics/summarizer/post-process/histogram.js +2 -1
  58. package/statistics/summarizer/post-process/post-process-output.js +2 -1
  59. package/statistics/summarizer/second-phase/process.js +3 -3
  60. package/util/arrays.d.ts +1 -1
  61. package/util/arrays.js +3 -3
  62. package/util/cfg/cfg.js +4 -2
  63. package/util/mermaid/cfg.js +1 -1
  64. package/util/summarizer.js +2 -2
  65. package/util/version.js +1 -1
@@ -1,5 +1,4 @@
1
- import type { DataflowGraphEdge } from './edge';
2
- import { EdgeType } from './edge';
1
+ import type { DataflowGraphEdge, EdgeType } from './edge';
3
2
  import type { DataflowInformation } from '../info';
4
3
  import type { DataflowGraphVertexArgument, DataflowGraphVertexFunctionCall, DataflowGraphVertexInfo } from './vertex';
5
4
  import { EmptyArgument } from '../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
@@ -7,30 +6,56 @@ import type { IdentifierDefinition, IdentifierReference } from '../environments/
7
6
  import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
8
7
  import type { AstIdMap } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
9
8
  import type { LinkTo } from '../../queries/catalog/call-context-query/call-context-query-format';
9
+ /**
10
+ * Describes the information we store per function body.
11
+ * The {@link DataflowFunctionFlowInformation#exitPoints} are stored within the enclosing {@link DataflowGraphVertexFunctionDefinition} vertex.
12
+ */
10
13
  export type DataflowFunctionFlowInformation = Omit<DataflowInformation, 'graph' | 'exitPoints'> & {
11
14
  graph: Set<NodeId>;
12
15
  };
13
16
  /**
17
+ * A reference with a name, e.g. `a` and `b` in the following function call:
18
+ *
14
19
  * ```r
15
20
  * foo(a = 3, b = 2)
16
21
  * ```
22
+ *
23
+ * @see #isNamedArgument
24
+ * @see PositionalFunctionArgument
17
25
  */
18
26
  export interface NamedFunctionArgument extends IdentifierReference {
19
27
  readonly name: string;
20
28
  }
21
29
  /**
30
+ * A reference which does not have a name, like the references to the arguments `3` and `2` in the following:
31
+ *
22
32
  * ```r
23
33
  * foo(3, 2)
24
34
  * ```
35
+ *
36
+ * @see #isPositionalArgument
37
+ * @see NamedFunctionArgument
25
38
  */
26
39
  export interface PositionalFunctionArgument extends Omit<IdentifierReference, 'name'> {
27
40
  readonly name?: undefined;
28
41
  }
29
42
  /** Summarizes either named (`foo(a = 3, b = 2)`), unnamed (`foo(3, 2)`), or empty (`foo(,)`) arguments within a function. */
30
43
  export type FunctionArgument = NamedFunctionArgument | PositionalFunctionArgument | typeof EmptyArgument;
44
+ /**
45
+ * Check if the given argument is a {@link PositionalFunctionArgument}.
46
+ */
31
47
  export declare function isPositionalArgument(arg: FunctionArgument): arg is PositionalFunctionArgument;
48
+ /**
49
+ * Check if the given argument is a {@link NamedFunctionArgument}.
50
+ */
32
51
  export declare function isNamedArgument(arg: FunctionArgument): arg is NamedFunctionArgument;
52
+ /**
53
+ * Returns the reference of a non-empty argument.
54
+ */
33
55
  export declare function getReferenceOfArgument(arg: FunctionArgument): NodeId | undefined;
56
+ /**
57
+ * A reference that is enough to indicate start and end points of an edge within the dataflow graph.
58
+ */
34
59
  type ReferenceForEdge = Pick<IdentifierReference, 'nodeId' | 'controlDependencies'> | IdentifierDefinition;
35
60
  /**
36
61
  * Maps the edges target to the edge information
@@ -41,11 +66,20 @@ export type OutgoingEdges<Edge extends DataflowGraphEdge = DataflowGraphEdge> =
41
66
  * In other words, it maps the source to the edge information.
42
67
  */
43
68
  export type IngoingEdges<Edge extends DataflowGraphEdge = DataflowGraphEdge> = Map<NodeId, Edge>;
69
+ /**
70
+ * The structure of the serialized {@link DataflowGraph}.
71
+ */
44
72
  export interface DataflowGraphJson {
45
73
  readonly rootVertices: NodeId[];
46
74
  readonly vertexInformation: [NodeId, DataflowGraphVertexInfo][];
47
75
  readonly edgeInformation: [NodeId, [NodeId, DataflowGraphEdge][]][];
48
76
  }
77
+ /**
78
+ * An unknown side effect describes something that we cannot handle correctly (in all cases).
79
+ * For example, `eval` will be marked as an unknown side effect as we have no idea of how it will affect the program.
80
+ * Linked side effects are used whenever we know that a call may be affected by another one in a way that we cannot
81
+ * grasp from the dataflow perspective (e.g., an indirect dependency based on the currently active graphic device).
82
+ */
49
83
  export type UnknownSidEffect = NodeId | {
50
84
  id: NodeId;
51
85
  linkTo: LinkTo<RegExp>;
@@ -60,6 +94,11 @@ export type UnknownSidEffect = NodeId | {
60
94
  * However, this does not have to hold during the construction as edges may point from or to vertices which are yet to be constructed.
61
95
  *
62
96
  * All methods return the modified graph to allow for chaining.
97
+ *
98
+ * @see {@link DataflowGraph#addEdge|`addEdge`} - to add an edge to the graph
99
+ * @see {@link DataflowGraph#addVertex|`addVertex`} - to add a vertex to the graph
100
+ * @see {@link DataflowGraph#fromJson|`fromJson`} - to construct a dataflow graph object from a deserialized JSON object.
101
+ * @see {@link emptyGraph} - to create an empty graph (useful in tests)
63
102
  */
64
103
  export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo, Edge extends DataflowGraphEdge = DataflowGraphEdge> {
65
104
  private static DEFAULT_ENVIRONMENT;
@@ -144,7 +183,6 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
144
183
  addEdge(from: ReferenceForEdge, to: ReferenceForEdge, type: EdgeType): this;
145
184
  /** {@inheritDoc} */
146
185
  addEdge(from: NodeId | ReferenceForEdge, to: NodeId | ReferenceForEdge, type: EdgeType): this;
147
- private installEdge;
148
186
  /**
149
187
  * Merges the other graph into *this* one (in-place). The return value is only for convenience.
150
188
  *
@@ -5,7 +5,6 @@ exports.isPositionalArgument = isPositionalArgument;
5
5
  exports.isNamedArgument = isNamedArgument;
6
6
  exports.getReferenceOfArgument = getReferenceOfArgument;
7
7
  const assert_1 = require("../../util/assert");
8
- const edge_1 = require("./edge");
9
8
  const diff_1 = require("./diff");
10
9
  const vertex_1 = require("./vertex");
11
10
  const arrays_1 = require("../../util/arrays");
@@ -16,23 +15,27 @@ const clone_1 = require("../environments/clone");
16
15
  const json_1 = require("../../util/json");
17
16
  const built_in_1 = require("../environments/built-in");
18
17
  const logger_1 = require("../logger");
18
+ /**
19
+ * Check if the given argument is a {@link PositionalFunctionArgument}.
20
+ */
19
21
  function isPositionalArgument(arg) {
20
22
  return arg !== r_function_call_1.EmptyArgument && arg.name === undefined;
21
23
  }
24
+ /**
25
+ * Check if the given argument is a {@link NamedFunctionArgument}.
26
+ */
22
27
  function isNamedArgument(arg) {
23
28
  return arg !== r_function_call_1.EmptyArgument && arg.name !== undefined;
24
29
  }
30
+ /**
31
+ * Returns the reference of a non-empty argument.
32
+ */
25
33
  function getReferenceOfArgument(arg) {
26
34
  if (arg !== r_function_call_1.EmptyArgument) {
27
- return arg.nodeId;
35
+ return arg?.nodeId;
28
36
  }
29
37
  return undefined;
30
38
  }
31
- function extractEdgeIds(from, to) {
32
- const fromId = typeof from === 'object' ? from.nodeId : from;
33
- const toId = typeof to === 'object' ? to.nodeId : to;
34
- return { fromId, toId };
35
- }
36
39
  /**
37
40
  * The dataflow graph holds the dataflow information found within the given AST.
38
41
  * We differentiate the directed edges in {@link EdgeType} and the vertices indicated by {@link DataflowGraphVertexArgument}
@@ -43,6 +46,11 @@ function extractEdgeIds(from, to) {
43
46
  * However, this does not have to hold during the construction as edges may point from or to vertices which are yet to be constructed.
44
47
  *
45
48
  * All methods return the modified graph to allow for chaining.
49
+ *
50
+ * @see {@link DataflowGraph#addEdge|`addEdge`} - to add an edge to the graph
51
+ * @see {@link DataflowGraph#addVertex|`addVertex`} - to add a vertex to the graph
52
+ * @see {@link DataflowGraph#fromJson|`fromJson`} - to construct a dataflow graph object from a deserialized JSON object.
53
+ * @see {@link emptyGraph} - to create an empty graph (useful in tests)
46
54
  */
47
55
  class DataflowGraph {
48
56
  static DEFAULT_ENVIRONMENT = undefined;
@@ -185,13 +193,10 @@ class DataflowGraph {
185
193
  return this;
186
194
  }
187
195
  /**
188
- * Will insert a new edge into the graph,
189
- * if the direction of the edge is of no importance (`same-read-read` or `same-def-def`), source
190
- * and target will be sorted so that `from` has the lower, and `to` the higher id (default ordering).
191
196
  * Please note that this will never make edges to {@link BuiltIn} as they are not part of the graph.
192
197
  */
193
198
  addEdge(from, to, type) {
194
- const { fromId, toId } = extractEdgeIds(from, to);
199
+ const [fromId, toId] = extractEdgeIds(from, to);
195
200
  if (fromId === toId || toId === built_in_1.BuiltIn) {
196
201
  return this;
197
202
  }
@@ -206,7 +211,6 @@ class DataflowGraph {
206
211
  else {
207
212
  existingFrom.set(toId, edge);
208
213
  }
209
- this.installEdge(type, toId, fromId, edge);
210
214
  }
211
215
  else {
212
216
  // adding the type
@@ -214,21 +218,6 @@ class DataflowGraph {
214
218
  }
215
219
  return this;
216
220
  }
217
- installEdge(type, toId, fromId, edge) {
218
- if (type === edge_1.EdgeType.DefinesOnCall) {
219
- const otherEdge = {
220
- ...edge,
221
- types: edge_1.EdgeType.DefinedByOnCall
222
- };
223
- const existingTo = this.edgeInformation.get(toId);
224
- if (existingTo === undefined) {
225
- this.edgeInformation.set(toId, new Map([[fromId, otherEdge]]));
226
- }
227
- else {
228
- existingTo.set(fromId, otherEdge);
229
- }
230
- }
231
- }
232
221
  /**
233
222
  * Merges the other graph into *this* one (in-place). The return value is only for convenience.
234
223
  *
@@ -269,7 +258,7 @@ class DataflowGraph {
269
258
  existing.set(target, edge);
270
259
  }
271
260
  else {
272
- get.types = get.types | edge.types;
261
+ get.types |= edge.types;
273
262
  }
274
263
  }
275
264
  }
@@ -304,8 +293,17 @@ class DataflowGraph {
304
293
  const vertex = this.getVertex(from, true);
305
294
  (0, assert_1.guard)(vertex !== undefined, () => `node must be defined for ${from} to add control dependency`);
306
295
  vertex.controlDependencies ??= [];
307
- if (to && vertex.controlDependencies.every(({ id, when: cond }) => id !== to && when !== cond)) {
308
- vertex.controlDependencies.push({ id: to, when });
296
+ if (to) {
297
+ let hasControlDependency = false;
298
+ for (const { id, when: cond } of vertex.controlDependencies) {
299
+ if (id === to && when !== cond) {
300
+ hasControlDependency = true;
301
+ break;
302
+ }
303
+ }
304
+ if (!hasControlDependency) {
305
+ vertex.controlDependencies.push({ id: to, when });
306
+ }
309
307
  }
310
308
  return this;
311
309
  }
@@ -334,8 +332,8 @@ class DataflowGraph {
334
332
  exports.DataflowGraph = DataflowGraph;
335
333
  function mergeNodeInfos(current, next) {
336
334
  if (current.tag !== next.tag) {
337
- logger_1.dataflowLogger.warn(`nodes to be joined for the same id should have the same tag, but ${JSON.stringify(current, json_1.jsonReplacer)} vs. ${JSON.stringify(next, json_1.jsonReplacer)} -- we are currently not handling cases in which vertices may be either! Keeping current.`);
338
- return { ...current };
335
+ logger_1.dataflowLogger.warn(() => `nodes to be joined for the same id should have the same tag, but ${JSON.stringify(current, json_1.jsonReplacer)} vs. ${JSON.stringify(next, json_1.jsonReplacer)} -- we are currently not handling cases in which vertices may be either! Keeping current.`);
336
+ return current;
339
337
  }
340
338
  if (current.tag === vertex_1.VertexType.VariableDefinition) {
341
339
  (0, assert_1.guard)(current.scope === next.scope, 'nodes to be joined for the same id must have the same scope');
@@ -347,7 +345,14 @@ function mergeNodeInfos(current, next) {
347
345
  (0, assert_1.guard)(current.scope === next.scope, 'nodes to be joined for the same id must have the same scope');
348
346
  (0, assert_1.guard)((0, arrays_1.arrayEqual)(current.exitPoints, next.exitPoints), 'nodes to be joined must have same exist points');
349
347
  }
350
- // make a copy
351
- return { ...current };
348
+ return current;
349
+ }
350
+ /**
351
+ * Returns the ids of the dataflow vertices referenced by a {@link ReferenceForEdge}.
352
+ */
353
+ function extractEdgeIds(from, to) {
354
+ const fromId = typeof from === 'object' ? from.nodeId : from;
355
+ const toId = typeof to === 'object' ? to.nodeId : to;
356
+ return [fromId, toId];
352
357
  }
353
358
  //# sourceMappingURL=graph.js.map
@@ -3,7 +3,6 @@ import type { DataflowFunctionFlowInformation, FunctionArgument } from './graph'
3
3
  import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
4
4
  import type { REnvironmentInformation } from '../environments/environment';
5
5
  import type { ControlDependency } from '../info';
6
- export type DataflowGraphVertices<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo> = Map<NodeId, Vertex>;
7
6
  export declare enum VertexType {
8
7
  Value = "value",
9
8
  Use = "use",
@@ -12,7 +11,7 @@ export declare enum VertexType {
12
11
  FunctionDefinition = "function-definition"
13
12
  }
14
13
  /**
15
- * Arguments required to construct a vertex in the dataflow graph.
14
+ * Arguments required to construct a vertex in the {@link DataflowGraph|dataflow graph}.
16
15
  *
17
16
  * @see DataflowGraphVertexUse
18
17
  * @see DataflowGraphVertexVariableDefinition
@@ -24,7 +23,9 @@ interface DataflowGraphVertexBase extends MergeableRecord {
24
23
  */
25
24
  readonly tag: VertexType;
26
25
  /**
27
- * The id of the node (the id assigned by the {@link ParentInformation} decoration)
26
+ * The id of the node (the id assigned by the {@link ParentInformation} decoration).
27
+ * This unanimously identifies the vertex in the {@link DataflowGraph|dataflow graph}
28
+ * as well as the corresponding {@link NormalizedAst|normalized AST}.
28
29
  */
29
30
  id: NodeId;
30
31
  /**
@@ -32,19 +33,40 @@ interface DataflowGraphVertexBase extends MergeableRecord {
32
33
  */
33
34
  environment?: REnvironmentInformation | undefined;
34
35
  /**
35
- * See {@link IdentifierReference}
36
+ * @see {@link ControlDependency} - the collection of control dependencies which have an influence on whether the vertex is executed.
36
37
  */
37
38
  controlDependencies: ControlDependency[] | undefined;
38
39
  }
39
40
  /**
40
41
  * Marker vertex for a value in the dataflow of the program.
42
+ * This does not contain the _value_ of the referenced constant
43
+ * as this is available with the {@link DataflowGraphVertexBase#id|id} in the {@link NormalizedAst|normalized AST}
44
+ * (or more specifically the {@link AstIdMap}).
45
+ *
46
+ * If you have a {@link DataflowGraph|dataflow graph} named `graph`
47
+ * with an {@link AstIdMap} and a value vertex object with name `value` the following Code should work:
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const node = graph.idMap.get(value.id)
52
+ * ```
53
+ *
54
+ * This then returns the corresponding node in the {@link NormalizedAst|normalized AST}, for example,
55
+ * an {@link RNumber} or {@link RString}.
56
+ *
57
+ * This works similarly for {@link IdentifierReference|identifier references}
58
+ * for which you can use the {@link IdentifierReference#nodeId|`nodeId`}.
59
+ *
60
+ * @see {@link isValueVertex} - to check if a vertex is a value vertex
41
61
  */
42
62
  export interface DataflowGraphVertexValue extends DataflowGraphVertexBase {
43
63
  readonly tag: VertexType.Value;
44
64
  readonly environment?: undefined;
45
65
  }
46
66
  /**
47
- * Arguments required to construct a vertex which represents the usage of a variable in the dataflow graph.
67
+ * Arguments required to construct a vertex which represents the usage of a variable in the {@link DataflowGraph|dataflow graph}.
68
+ *
69
+ * @see {@link isUseVertex} - to check if a vertex is a use vertex
48
70
  */
49
71
  export interface DataflowGraphVertexUse extends DataflowGraphVertexBase {
50
72
  readonly tag: VertexType.Use;
@@ -52,7 +74,9 @@ export interface DataflowGraphVertexUse extends DataflowGraphVertexBase {
52
74
  readonly environment?: undefined;
53
75
  }
54
76
  /**
55
- * Arguments required to construct a vertex which represents the usage of a variable in the dataflow graph.
77
+ * Arguments required to construct a vertex which represents the usage of a variable in the {@link DataflowGraph|dataflow graph}.
78
+ *
79
+ * @see {@link isFunctionCallVertex} - to check if a vertex is a function call vertex
56
80
  */
57
81
  export interface DataflowGraphVertexFunctionCall extends DataflowGraphVertexBase {
58
82
  readonly tag: VertexType.FunctionCall;
@@ -71,13 +95,20 @@ export interface DataflowGraphVertexFunctionCall extends DataflowGraphVertexBase
71
95
  environment: REnvironmentInformation | undefined;
72
96
  }
73
97
  /**
74
- * Arguments required to construct a vertex which represents the definition of a variable in the dataflow graph.
98
+ * Arguments required to construct a vertex which represents the definition of a variable in the {@link DataflowGraph|dataflow graph}.
99
+ *
100
+ * @see {@link isVariableDefinitionVertex} - to check if a vertex is a variable definition vertex
75
101
  */
76
102
  export interface DataflowGraphVertexVariableDefinition extends DataflowGraphVertexBase {
77
103
  readonly tag: VertexType.VariableDefinition;
78
104
  /** Does not require an environment, those are attached to the call */
79
105
  readonly environment?: undefined;
80
106
  }
107
+ /**
108
+ * Arguments required to construct a vertex which represents the definition of a function in the {@link DataflowGraph|dataflow graph}.
109
+ *
110
+ * @see {@link isFunctionDefinitionVertex} - to check if a vertex is a function definition vertex
111
+ */
81
112
  export interface DataflowGraphVertexFunctionDefinition extends DataflowGraphVertexBase {
82
113
  readonly tag: VertexType.FunctionDefinition;
83
114
  /**
@@ -93,11 +124,39 @@ export interface DataflowGraphVertexFunctionDefinition extends DataflowGraphVert
93
124
  exitPoints: readonly NodeId[];
94
125
  environment?: REnvironmentInformation;
95
126
  }
127
+ /**
128
+ * What is to be passed to construct a vertex in the {@link DataflowGraph|dataflow graph}
129
+ */
96
130
  export type DataflowGraphVertexArgument = DataflowGraphVertexUse | DataflowGraphVertexVariableDefinition | DataflowGraphVertexFunctionDefinition | DataflowGraphVertexFunctionCall | DataflowGraphVertexValue;
131
+ /**
132
+ * This is the union type of all possible vertices that appear within a {@link DataflowGraph|dataflow graph},
133
+ * they can be constructed passing a {@link DataflowGraphVertexArgument} to the graph.
134
+ *
135
+ * See {@link DataflowGraphVertices} for an id-based mapping.
136
+ */
97
137
  export type DataflowGraphVertexInfo = Required<DataflowGraphVertexArgument>;
138
+ /**
139
+ * A mapping of {@link NodeId}s to {@link DataflowGraphVertexInfo|vertices}.
140
+ */
141
+ export type DataflowGraphVertices<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo> = Map<NodeId, Vertex>;
142
+ /**
143
+ * Check if the given vertex is a {@link DataflowGraphVertexValue|value vertex}.
144
+ */
98
145
  export declare function isValueVertex(vertex: DataflowGraphVertexBase): vertex is DataflowGraphVertexValue;
146
+ /**
147
+ * Check if the given vertex is a {@link DataflowGraphVertexUse|use vertex}.
148
+ */
99
149
  export declare function isUseVertex(vertex: DataflowGraphVertexBase): vertex is DataflowGraphVertexUse;
150
+ /**
151
+ * Check if the given vertex is a {@link DataflowGraphVertexFunctionCall|function call vertex}.
152
+ */
100
153
  export declare function isFunctionCallVertex(vertex: DataflowGraphVertexBase): vertex is DataflowGraphVertexFunctionCall;
154
+ /**
155
+ * Check if the given vertex is a {@link DataflowGraphVertexVariableDefinition|variable definition vertex}.
156
+ */
101
157
  export declare function isVariableDefinitionVertex(vertex: DataflowGraphVertexBase): vertex is DataflowGraphVertexVariableDefinition;
158
+ /**
159
+ * Check if the given vertex is a {@link DataflowGraphVertexFunctionDefinition|function definition vertex}.
160
+ */
102
161
  export declare function isFunctionDefinitionVertex(vertex: DataflowGraphVertexBase): vertex is DataflowGraphVertexFunctionDefinition;
103
162
  export {};
@@ -14,18 +14,33 @@ var VertexType;
14
14
  VertexType["VariableDefinition"] = "variable-definition";
15
15
  VertexType["FunctionDefinition"] = "function-definition";
16
16
  })(VertexType || (exports.VertexType = VertexType = {}));
17
+ /**
18
+ * Check if the given vertex is a {@link DataflowGraphVertexValue|value vertex}.
19
+ */
17
20
  function isValueVertex(vertex) {
18
21
  return vertex.tag === VertexType.Value;
19
22
  }
23
+ /**
24
+ * Check if the given vertex is a {@link DataflowGraphVertexUse|use vertex}.
25
+ */
20
26
  function isUseVertex(vertex) {
21
27
  return vertex.tag === VertexType.Use;
22
28
  }
29
+ /**
30
+ * Check if the given vertex is a {@link DataflowGraphVertexFunctionCall|function call vertex}.
31
+ */
23
32
  function isFunctionCallVertex(vertex) {
24
33
  return vertex.tag === VertexType.FunctionCall;
25
34
  }
35
+ /**
36
+ * Check if the given vertex is a {@link DataflowGraphVertexVariableDefinition|variable definition vertex}.
37
+ */
26
38
  function isVariableDefinitionVertex(vertex) {
27
39
  return vertex.tag === VertexType.VariableDefinition;
28
40
  }
41
+ /**
42
+ * Check if the given vertex is a {@link DataflowGraphVertexFunctionDefinition|function definition vertex}.
43
+ */
29
44
  function isFunctionDefinitionVertex(vertex) {
30
45
  return vertex.tag === VertexType.FunctionDefinition;
31
46
  }
@@ -4,6 +4,24 @@ import type { IdentifierReference } from './environments/identifier';
4
4
  import type { REnvironmentInformation } from './environments/environment';
5
5
  import { DataflowGraph } from './graph/graph';
6
6
  import type { GenericDifferenceInformation, WriteableDifferenceReport } from '../util/diff';
7
+ /**
8
+ * A control dependency links a vertex to the control flow element which
9
+ * may have an influence on its execution.
10
+ * Within `if(p) a else b`, `a` and `b` have a control dependency on the `if` (which in turn decides based on `p`).
11
+ *
12
+ * @see {@link happensInEveryBranch} - to check whether a list of control dependencies is exhaustive
13
+ */
14
+ export interface ControlDependency {
15
+ /** The id of the node that causes the control dependency to be active (e.g., the condition of an if) */
16
+ readonly id: NodeId;
17
+ /** when does this control dependency trigger (if the condition is true or false)? */
18
+ readonly when?: boolean;
19
+ }
20
+ /**
21
+ * Classifies the type of exit point encountered.
22
+ *
23
+ * @see {@link ExitPoint}
24
+ */
7
25
  export declare const enum ExitPointType {
8
26
  /** The exit point is the implicit (last executed expression of a function/block) */
9
27
  Default = 0,
@@ -14,20 +32,31 @@ export declare const enum ExitPointType {
14
32
  /** The exit point is an explicit `next` call (or an alias of it) */
15
33
  Next = 3
16
34
  }
17
- export interface ControlDependency {
18
- /** The id of the node that causes the control dependency to be active (e.g., the condition of an if) */
19
- readonly id: NodeId;
20
- /** when does this control dependency trigger (if the condition is true or false)? */
21
- readonly when?: boolean;
22
- }
35
+ /**
36
+ * An exit point describes the position which ends the current control flow structure.
37
+ * This may be as innocent as the last expression or explicit with a `return`/`break`/`next`.
38
+ *
39
+ * @see {@link ExitPointType} - for the different types of exit points
40
+ * @see {@link addNonDefaultExitPoints} - to easily modify lists of exit points
41
+ * @see {@link alwaysExits} - to check whether a list of control dependencies always triggers an exit
42
+ * @see {@link filterOutLoopExitPoints} - to remove loop exit points from a list
43
+ */
23
44
  export interface ExitPoint {
24
45
  /** What kind of exit point is this one? May be used to filter for exit points of specific causes. */
25
46
  readonly type: ExitPointType;
26
47
  /** The id of the node which causes the exit point! */
27
48
  readonly nodeId: NodeId;
28
- /** Control dependencies which influence if the exit point triggers (e.g., if the `return` is contained within an `if` statement) */
49
+ /**
50
+ * Control dependencies which influence if the exit point triggers
51
+ * (e.g., if the `return` is contained within an `if` statement).
52
+ *
53
+ * @see {@link happensInEveryBranch} - to check whether control dependencies are exhaustive
54
+ */
29
55
  readonly controlDependencies: ControlDependency[] | undefined;
30
56
  }
57
+ /**
58
+ * Adds all non-default exit points to the existing list.
59
+ */
31
60
  export declare function addNonDefaultExitPoints(existing: ExitPoint[], add: readonly ExitPoint[]): void;
32
61
  /** The control flow information for the current DataflowInformation. */
33
62
  export interface DataflowCfgInformation {
@@ -37,24 +66,63 @@ export interface DataflowCfgInformation {
37
66
  exitPoints: readonly ExitPoint[];
38
67
  }
39
68
  /**
40
- * The dataflow information is continuously updated during the dataflow analysis
69
+ * The dataflow information is one of the fundamental structures we have in the dataflow analysis.
70
+ * It is continuously updated during the dataflow analysis
41
71
  * and holds its current state for the respective subtree processed.
72
+ * Each processor during the dataflow analysis may use the information from its children
73
+ * to produce a new state of the dataflow information.
74
+ *
75
+ * You may initialize a new dataflow information with {@link initializeCleanDataflowInformation}.
76
+ *
77
+ * @see {@link DataflowCfgInformation} - the control flow aspects
42
78
  */
43
79
  export interface DataflowInformation extends DataflowCfgInformation {
44
- /** References that have not been identified as read or write and will be so on higher */
80
+ /**
81
+ * References that have not been identified as read or write and will be so on higher processors.
82
+ *
83
+ * For example, when we analyze the `x` vertex in `x <- 3`, we will first create an unknown reference for `x`
84
+ * as we have not yet seen the assignment!
85
+ *
86
+ * @see {@link IdentifierReference} - a reference on a variable, parameter, function call, ...
87
+ */
45
88
  unknownReferences: readonly IdentifierReference[];
46
- /** References which are read */
89
+ /**
90
+ * References which are read within the current subtree.
91
+ *
92
+ * @see {@link IdentifierReference} - a reference on a variable, parameter, function call, ...
93
+ * */
47
94
  in: readonly IdentifierReference[];
48
- /** References which are written to */
95
+ /**
96
+ * References which are written to within the current subtree
97
+ *
98
+ * @see {@link IdentifierReference} - a reference on a variable, parameter, function call, ...
99
+ */
49
100
  out: readonly IdentifierReference[];
50
101
  /** Current environments used for name resolution, probably updated on the next expression-list processing */
51
102
  environment: REnvironmentInformation;
52
103
  /** The current constructed dataflow graph */
53
104
  graph: DataflowGraph;
54
105
  }
106
+ /**
107
+ * Initializes an empty {@link DataflowInformation} object with the given entry point and data.
108
+ * This is to be used as a "starting point" when processing leaf nodes during the dataflow extraction.
109
+ *
110
+ * @see {@link DataflowInformation}
111
+ */
55
112
  export declare function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'completeAst'>): DataflowInformation;
113
+ /**
114
+ * Checks whether the given control dependencies are exhaustive (i.e. if for every control dependency on a boolean,
115
+ * the list contains a dependency on the `true` and on the `false` case).
116
+ */
56
117
  export declare function happensInEveryBranch(controlDependencies: readonly ControlDependency[] | undefined): boolean;
118
+ /**
119
+ * Checks whether the given dataflow information always exits (i.e., if there is a non-default exit point in every branch).
120
+ * @see {@link ExitPoint} - for the different types of exit points
121
+ */
57
122
  export declare function alwaysExits(data: DataflowInformation): boolean;
123
+ /**
124
+ * Filters out exit points which end their cascade within a loop.
125
+ */
58
126
  export declare function filterOutLoopExitPoints(exitPoints: readonly ExitPoint[]): readonly ExitPoint[];
59
127
  export declare function diffControlDependency<Report extends WriteableDifferenceReport>(a: ControlDependency | undefined, b: ControlDependency | undefined, info: GenericDifferenceInformation<Report>): void;
60
128
  export declare function diffControlDependencies<Report extends WriteableDifferenceReport>(a: ControlDependency[] | undefined, b: ControlDependency[] | undefined, info: GenericDifferenceInformation<Report>): void;
package/dataflow/info.js CHANGED
@@ -8,9 +8,18 @@ exports.filterOutLoopExitPoints = filterOutLoopExitPoints;
8
8
  exports.diffControlDependency = diffControlDependency;
9
9
  exports.diffControlDependencies = diffControlDependencies;
10
10
  const graph_1 = require("./graph/graph");
11
+ /**
12
+ * Adds all non-default exit points to the existing list.
13
+ */
11
14
  function addNonDefaultExitPoints(existing, add) {
12
15
  existing.push(...add.filter(({ type }) => type !== 0 /* ExitPointType.Default */));
13
16
  }
17
+ /**
18
+ * Initializes an empty {@link DataflowInformation} object with the given entry point and data.
19
+ * This is to be used as a "starting point" when processing leaf nodes during the dataflow extraction.
20
+ *
21
+ * @see {@link DataflowInformation}
22
+ */
14
23
  function initializeCleanDataflowInformation(entryPoint, data) {
15
24
  return {
16
25
  unknownReferences: [],
@@ -22,6 +31,10 @@ function initializeCleanDataflowInformation(entryPoint, data) {
22
31
  exitPoints: [{ nodeId: entryPoint, type: 0 /* ExitPointType.Default */, controlDependencies: undefined }]
23
32
  };
24
33
  }
34
+ /**
35
+ * Checks whether the given control dependencies are exhaustive (i.e. if for every control dependency on a boolean,
36
+ * the list contains a dependency on the `true` and on the `false` case).
37
+ */
25
38
  function happensInEveryBranch(controlDependencies) {
26
39
  if (controlDependencies === undefined) {
27
40
  /* the cds are unconstrained */
@@ -43,9 +56,16 @@ function happensInEveryBranch(controlDependencies) {
43
56
  }
44
57
  return trues.every(id => falseSet.has(id));
45
58
  }
59
+ /**
60
+ * Checks whether the given dataflow information always exits (i.e., if there is a non-default exit point in every branch).
61
+ * @see {@link ExitPoint} - for the different types of exit points
62
+ */
46
63
  function alwaysExits(data) {
47
64
  return data.exitPoints?.some(e => e.type !== 0 /* ExitPointType.Default */ && happensInEveryBranch(e.controlDependencies)) ?? false;
48
65
  }
66
+ /**
67
+ * Filters out exit points which end their cascade within a loop.
68
+ */
49
69
  function filterOutLoopExitPoints(exitPoints) {
50
70
  return exitPoints.filter(({ type }) => type === 1 /* ExitPointType.Return */ || type === 0 /* ExitPointType.Default */);
51
71
  }
@@ -23,8 +23,10 @@ export declare function linkFunctionCalls(graph: DataflowGraph, idMap: AstIdMap,
23
23
  functionCall: NodeId;
24
24
  called: readonly DataflowGraphVertexInfo[];
25
25
  }[];
26
- /** convenience function returning all known call targets */
27
- export declare function getAllFunctionCallTargets(call: NodeId, graph: DataflowGraph): NodeId[];
26
+ /**
27
+ * convenience function returning all known call targets, as well as the name source which defines them
28
+ */
29
+ export declare function getAllFunctionCallTargets(call: NodeId, graph: DataflowGraph, environment?: REnvironmentInformation): NodeId[];
28
30
  export declare function getAllLinkedFunctionDefinitions(functionDefinitionReadIds: ReadonlySet<NodeId>, dataflowGraph: DataflowGraph): Set<DataflowGraphVertexInfo>;
29
31
  /**
30
32
  * This method links a set of read variables to definitions in an environment.