@eagleoutice/flowr 2.3.0 → 2.4.1

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 (145) hide show
  1. package/README.md +42 -30
  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/stats/size-of.js +3 -3
  10. package/benchmark/summarizer/second-phase/graph.js +1 -1
  11. package/benchmark/summarizer/second-phase/process.js +1 -1
  12. package/cli/benchmark-app.d.ts +1 -0
  13. package/cli/benchmark-app.js +1 -0
  14. package/cli/benchmark-helper-app.d.ts +1 -0
  15. package/cli/benchmark-helper-app.js +4 -3
  16. package/cli/common/options.js +2 -0
  17. package/cli/repl/commands/repl-query.js +1 -1
  18. package/cli/repl/server/connection.js +14 -5
  19. package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
  20. package/control-flow/basic-cfg-guided-visitor.js +0 -6
  21. package/control-flow/cfg-simplification.d.ts +6 -0
  22. package/control-flow/cfg-simplification.js +18 -9
  23. package/control-flow/control-flow-graph.d.ts +2 -8
  24. package/control-flow/control-flow-graph.js +1 -6
  25. package/control-flow/extract-cfg.d.ts +2 -2
  26. package/control-flow/extract-cfg.js +52 -63
  27. package/core/pipeline-executor.js +0 -8
  28. package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
  29. package/core/steps/all/static-slicing/00-slice.js +9 -3
  30. package/core/steps/pipeline/default-pipelines.d.ts +74 -74
  31. package/dataflow/environments/append.js +1 -1
  32. package/dataflow/environments/built-in-config.d.ts +12 -4
  33. package/dataflow/environments/built-in-config.js +23 -82
  34. package/dataflow/environments/built-in.d.ts +40 -6
  35. package/dataflow/environments/built-in.js +119 -23
  36. package/dataflow/environments/clone.d.ts +3 -2
  37. package/dataflow/environments/clone.js +6 -5
  38. package/dataflow/environments/define.js +1 -2
  39. package/dataflow/environments/diff.js +1 -3
  40. package/dataflow/environments/environment.d.ts +18 -24
  41. package/dataflow/environments/environment.js +25 -37
  42. package/dataflow/environments/overwrite.d.ts +1 -1
  43. package/dataflow/environments/overwrite.js +1 -1
  44. package/dataflow/environments/remove.d.ts +2 -2
  45. package/dataflow/environments/remove.js +3 -4
  46. package/dataflow/environments/resolve-by-name.d.ts +3 -3
  47. package/dataflow/environments/resolve-by-name.js +4 -5
  48. package/dataflow/eval/resolve/alias-tracking.d.ts +12 -12
  49. package/dataflow/eval/resolve/alias-tracking.js +12 -12
  50. package/dataflow/eval/resolve/resolve.js +1 -1
  51. package/dataflow/extractor.js +6 -1
  52. package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
  53. package/dataflow/graph/dataflowgraph-builder.js +2 -2
  54. package/dataflow/graph/graph.d.ts +2 -1
  55. package/dataflow/graph/graph.js +6 -2
  56. package/dataflow/graph/invert-dfg.d.ts +2 -0
  57. package/dataflow/graph/invert-dfg.js +17 -0
  58. package/dataflow/info.d.ts +1 -1
  59. package/dataflow/internal/linker.js +9 -9
  60. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +1 -1
  61. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -4
  62. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -5
  63. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -7
  64. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +2 -2
  65. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +1 -1
  66. package/dataflow/processor.d.ts +5 -1
  67. package/documentation/doc-util/doc-env.js +1 -2
  68. package/documentation/doc-util/doc-query.js +1 -1
  69. package/documentation/doc-util/doc-search.js +2 -2
  70. package/documentation/print-cfg-wiki.js +3 -4
  71. package/documentation/print-core-wiki.js +2 -2
  72. package/documentation/print-dataflow-graph-wiki.js +7 -0
  73. package/documentation/print-faq-wiki.js +4 -0
  74. package/documentation/print-linter-wiki.js +32 -4
  75. package/documentation/print-linting-and-testing-wiki.js +13 -1
  76. package/documentation/print-onboarding-wiki.js +4 -0
  77. package/documentation/print-query-wiki.js +12 -3
  78. package/linter/linter-executor.js +1 -2
  79. package/linter/linter-format.d.ts +26 -4
  80. package/linter/linter-format.js +25 -6
  81. package/linter/linter-rules.d.ts +40 -12
  82. package/linter/linter-rules.js +3 -1
  83. package/linter/rules/absolute-path.d.ts +4 -7
  84. package/linter/rules/absolute-path.js +9 -6
  85. package/linter/rules/dataframe-access-validation.d.ts +3 -1
  86. package/linter/rules/dataframe-access-validation.js +3 -1
  87. package/linter/rules/dead-code.d.ts +43 -0
  88. package/linter/rules/dead-code.js +50 -0
  89. package/linter/rules/deprecated-functions.d.ts +3 -2
  90. package/linter/rules/deprecated-functions.js +3 -1
  91. package/linter/rules/file-path-validity.d.ts +4 -4
  92. package/linter/rules/file-path-validity.js +8 -6
  93. package/linter/rules/naming-convention.d.ts +4 -3
  94. package/linter/rules/naming-convention.js +3 -1
  95. package/linter/rules/seeded-randomness.d.ts +4 -3
  96. package/linter/rules/seeded-randomness.js +3 -1
  97. package/linter/rules/unused-definition.d.ts +2 -0
  98. package/linter/rules/unused-definition.js +3 -1
  99. package/package.json +1 -1
  100. package/queries/base-query-format.d.ts +2 -0
  101. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +7 -7
  102. package/queries/catalog/dependencies-query/dependencies-query-executor.js +24 -1
  103. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +9 -5
  104. package/queries/catalog/dependencies-query/function-info/read-functions.js +5 -2
  105. package/queries/catalog/dependencies-query/function-info/write-functions.js +6 -0
  106. package/queries/catalog/linter-query/linter-query-format.js +1 -1
  107. package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
  108. package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
  109. package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
  110. package/queries/catalog/search-query/search-query-executor.js +1 -1
  111. package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
  112. package/queries/catalog/static-slice-query/static-slice-query-executor.js +3 -2
  113. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
  114. package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
  115. package/queries/query-print.d.ts +1 -1
  116. package/queries/query-print.js +0 -1
  117. package/queries/query.d.ts +16 -5
  118. package/queries/query.js +24 -11
  119. package/search/flowr-search-builder.d.ts +6 -6
  120. package/search/flowr-search-executor.d.ts +2 -2
  121. package/search/flowr-search-executor.js +1 -1
  122. package/search/flowr-search.d.ts +13 -8
  123. package/search/flowr-search.js +21 -0
  124. package/search/search-executor/search-enrichers.d.ts +87 -20
  125. package/search/search-executor/search-enrichers.js +44 -5
  126. package/search/search-executor/search-generators.d.ts +4 -4
  127. package/search/search-executor/search-generators.js +12 -7
  128. package/search/search-executor/search-mappers.js +3 -2
  129. package/search/search-executor/search-transformer.d.ts +3 -3
  130. package/search/search-executor/search-transformer.js +2 -2
  131. package/slicing/static/fingerprint.js +1 -2
  132. package/slicing/static/slice-call.d.ts +2 -1
  133. package/slicing/static/slice-call.js +3 -3
  134. package/slicing/static/static-slicer.d.ts +6 -5
  135. package/slicing/static/static-slicer.js +13 -7
  136. package/util/collections/arrays.d.ts +2 -0
  137. package/util/collections/arrays.js +9 -0
  138. package/util/containers.d.ts +1 -0
  139. package/util/containers.js +1 -0
  140. package/util/json.js +1 -4
  141. package/util/mermaid/dfg.js +5 -4
  142. package/util/prefix.d.ts +1 -1
  143. package/util/range.d.ts +1 -0
  144. package/util/range.js +5 -1
  145. package/util/version.js +1 -1
@@ -78,9 +78,9 @@ function getUseAlias(sourceId, dataflow, environment) {
78
78
  * us later, in the {@link trackAliasInEnvironments} function, to get all the
79
79
  * aliases of an identifier.
80
80
  *
81
- * @param sourceIds - node ids to get the definitions for
82
- * @param dataflow - dataflow graph
83
- * @param environment - environment
81
+ * @param sourceIds - node ids to get the definitions for
82
+ * @param dataflow - dataflow graph
83
+ * @param environment - environment
84
84
  * @returns node id of alias
85
85
  */
86
86
  function getAliases(sourceIds, dataflow, environment) {
@@ -110,12 +110,12 @@ function getAliases(sourceIds, dataflow, environment) {
110
110
  * to resolve values. For e.g. in the Dependency Query it is used to resolve calls
111
111
  * like `lapply(c("a", "b", "c"), library, character.only = TRUE)`
112
112
  *
113
- * @param id - The node id or node to resolve
114
- * @param environment - The current environment used for name resolution
115
- * @param graph - The graph to resolve in
116
- * @param idMap - The id map to resolve the node if given as an id
117
- * @param full - Whether to track aliases on resolve
118
- * @param resolve - Variable resolve mode
113
+ * @param id - The node id or node to resolve
114
+ * @param environment - The current environment used for name resolution
115
+ * @param graph - The graph to resolve in
116
+ * @param idMap - The id map to resolve the node if given as an id
117
+ * @param full - Whether to track aliases on resolve
118
+ * @param resolve - Variable resolve mode
119
119
  */
120
120
  function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve }) {
121
121
  if (id === undefined) {
@@ -160,7 +160,7 @@ function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve
160
160
  * @param resolve - Variable resolve mode
161
161
  * @param identifier - Identifier to resolve
162
162
  * @param use - Environment to use
163
- * @param graph - Dataflow graph
163
+ * @param graph - dataflow graph
164
164
  * @param idMap - id map of Dataflow graph
165
165
  * @returns Value of Identifier or Top
166
166
  */
@@ -333,8 +333,8 @@ function trackAliasesInGraph(id, graph, idMap) {
333
333
  *
334
334
  * Resolve an Identifier to a constant, if the identifier is a constant
335
335
  *
336
- * @param name - Identifier to resolve
337
- * @param environment - Environment to use
336
+ * @param name - Identifier to resolve
337
+ * @param environment - Environment to use
338
338
  * @returns Value of Constant or Top
339
339
  */
340
340
  function resolveToConstants(name, environment) {
@@ -59,7 +59,7 @@ function resolveNode(resolve, a, env, graph, map) {
59
59
  else {
60
60
  return r_value_2.Top;
61
61
  }
62
- if (Object.prototype.hasOwnProperty.call(built_in_1.BuiltInEvalHandlerMapper, builtInName)) {
62
+ if (Object.hasOwn(built_in_1.BuiltInEvalHandlerMapper, builtInName)) {
63
63
  const handler = built_in_1.BuiltInEvalHandlerMapper[builtInName];
64
64
  return handler(resolve, a, env, graph, map);
65
65
  }
@@ -20,6 +20,7 @@ const extract_cfg_1 = require("../control-flow/extract-cfg");
20
20
  const edge_1 = require("./graph/edge");
21
21
  const identify_link_to_last_call_relation_1 = require("../queries/catalog/call-context-query/identify-link-to-last-call-relation");
22
22
  const built_in_function_definition_1 = require("./internal/process/functions/call/built-in/built-in-function-definition");
23
+ const built_in_config_1 = require("./environments/built-in-config");
23
24
  /**
24
25
  * The best friend of {@link produceDataFlowGraph} and {@link processDataflowFor}.
25
26
  * Maps every {@link RType} in the normalized AST to a processor.
@@ -89,10 +90,14 @@ function produceDataFlowGraph(parser, request, completeAst, config) {
89
90
  else {
90
91
  firstRequest = request;
91
92
  }
93
+ const builtInsConfig = config.semantics.environment.overwriteBuiltIns;
94
+ const builtIns = (0, built_in_config_1.getBuiltInDefinitions)(builtInsConfig.definitions, builtInsConfig.loadDefaults);
95
+ const env = (0, environment_1.initializeCleanEnvironments)(builtIns.builtInMemory);
92
96
  const dfData = {
93
97
  parser,
94
98
  completeAst,
95
- environment: (0, environment_1.initializeCleanEnvironments)(),
99
+ environment: env,
100
+ builtInEnvironment: env.current.parent,
96
101
  processors: exports.processors,
97
102
  currentRequest: firstRequest,
98
103
  controlDependencies: undefined,
@@ -2,7 +2,7 @@ import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-i
2
2
  import type { AstIdMap } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
3
3
  import type { DataflowFunctionFlowInformation, FunctionArgument } from './graph';
4
4
  import { DataflowGraph } from './graph';
5
- import type { REnvironmentInformation } from '../environments/environment';
5
+ import type { IEnvironment, REnvironmentInformation } from '../environments/environment';
6
6
  import type { DataflowGraphVertexAstLink, DataflowGraphVertexUse, FunctionOriginInformation } from './vertex';
7
7
  import type { ControlDependency } from '../info';
8
8
  import type { LinkTo } from '../../queries/catalog/call-context-query/call-context-query-format';
@@ -29,6 +29,7 @@ export declare class DataflowGraphBuilder extends DataflowGraph {
29
29
  */
30
30
  defineFunction(id: NodeId, exitPoints: readonly NodeId[], subflow: DataflowFunctionFlowInformation, info?: {
31
31
  environment?: REnvironmentInformation;
32
+ builtInEnvironment?: IEnvironment;
32
33
  controlDependencies?: ControlDependency[];
33
34
  }, asRoot?: boolean): this;
34
35
  /**
@@ -46,6 +47,7 @@ export declare class DataflowGraphBuilder extends DataflowGraph {
46
47
  reads?: readonly NodeId[];
47
48
  onlyBuiltIn?: boolean;
48
49
  environment?: REnvironmentInformation;
50
+ builtInEnvironment?: IEnvironment;
49
51
  controlDependencies?: ControlDependency[];
50
52
  origin?: FunctionOriginInformation[];
51
53
  link?: DataflowGraphVertexAstLink;
@@ -180,7 +180,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
180
180
  fromId = from.nodeId;
181
181
  }
182
182
  else {
183
- const result = (0, flowr_search_executor_1.runSearch)(from.query, data);
183
+ const result = (0, flowr_search_executor_1.runSearch)(from.query, data).getElements();
184
184
  (0, assert_1.guard)(result.length === 1, `from query result should yield exactly one node, but yielded ${result.length}`);
185
185
  fromId = result[0].node.info.id;
186
186
  }
@@ -189,7 +189,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
189
189
  toIds = to.target;
190
190
  }
191
191
  else {
192
- const result = (0, flowr_search_executor_1.runSearch)(to.query, data);
192
+ const result = (0, flowr_search_executor_1.runSearch)(to.query, data).getElements();
193
193
  toIds = result.map(r => r.node.info.id);
194
194
  }
195
195
  return this.edgeHelper(fromId, toIds, type);
@@ -160,7 +160,7 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
160
160
  *
161
161
  * @see #edges
162
162
  */
163
- vertices(includeDefinedFunctions: boolean): IterableIterator<[NodeId, Vertex]>;
163
+ vertices(includeDefinedFunctions: boolean): MapIterator<[NodeId, Vertex]>;
164
164
  /**
165
165
  * @returns the ids of all edges in the graph together with their edge information
166
166
  *
@@ -231,5 +231,6 @@ export interface IEnvironmentJson {
231
231
  readonly id: number;
232
232
  parent: IEnvironmentJson;
233
233
  memory: Record<Identifier, IdentifierDefinition[]>;
234
+ builtInEnv: true | undefined;
234
235
  }
235
236
  export {};
@@ -376,7 +376,7 @@ function mergeNodeInfos(current, next) {
376
376
  }
377
377
  else if (current.tag === vertex_1.VertexType.FunctionDefinition) {
378
378
  (0, assert_1.guard)(current.scope === next.scope, 'nodes to be joined for the same id must have the same scope');
379
- (0, assert_1.guard)((0, arrays_1.arrayEqual)(current.exitPoints, next.exitPoints), 'nodes to be joined must have same exist points');
379
+ current.exitPoints = (0, arrays_1.uniqueArrayMerge)(current.exitPoints, next.exitPoints);
380
380
  }
381
381
  return current;
382
382
  }
@@ -394,11 +394,15 @@ function envFromJson(json) {
394
394
  for (const [key, value] of Object.entries(json.memory)) {
395
395
  memory.set(key, value);
396
396
  }
397
- return {
397
+ const obj = {
398
398
  id: json.id,
399
399
  parent: parent,
400
400
  memory
401
401
  };
402
+ if (json.builtInEnv) {
403
+ obj.builtInEnv = true;
404
+ }
405
+ return obj;
402
406
  }
403
407
  function renvFromJson(json) {
404
408
  const current = envFromJson(json.current);
@@ -0,0 +1,2 @@
1
+ import { DataflowGraph } from './graph';
2
+ export declare function invertDfg(graph: DataflowGraph): DataflowGraph;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.invertDfg = invertDfg;
4
+ const graph_1 = require("./graph");
5
+ function invertDfg(graph) {
6
+ const invertedGraph = new graph_1.DataflowGraph(graph.idMap);
7
+ for (const [, v] of graph.vertices(true)) {
8
+ invertedGraph.addVertex(v);
9
+ }
10
+ for (const [from, targets] of graph.edges()) {
11
+ for (const [to, { types }] of targets) {
12
+ invertedGraph.addEdge(to, from, types);
13
+ }
14
+ }
15
+ return invertedGraph;
16
+ }
17
+ //# sourceMappingURL=invert-dfg.js.map
@@ -109,7 +109,7 @@ export interface DataflowInformation extends DataflowCfgInformation {
109
109
  *
110
110
  * @see {@link DataflowInformation}
111
111
  */
112
- export declare function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'completeAst'>): DataflowInformation;
112
+ export declare function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'builtInEnvironment' | 'completeAst'>): DataflowInformation;
113
113
  /**
114
114
  * Checks whether the given control dependencies are exhaustive (i.e. if for every control dependency on a boolean,
115
115
  * the list contains a dependency on the `true` and on the `false` case).
@@ -25,7 +25,7 @@ const built_in_1 = require("../environments/built-in");
25
25
  const prefix_1 = require("../../util/prefix");
26
26
  function findNonLocalReads(graph, ignore) {
27
27
  const ignores = new Set(ignore.map(i => i.nodeId));
28
- const ids = new Set([...graph.vertices(true)]
28
+ const ids = new Set(graph.vertices(true)
29
29
  .filter(([_, info]) => info.tag === vertex_1.VertexType.Use || info.tag === vertex_1.VertexType.FunctionCall)
30
30
  .map(([id, _]) => id));
31
31
  /* find all variable use ids which do not link to a given id */
@@ -74,27 +74,27 @@ function produceNameSharedIdMap(references) {
74
74
  }
75
75
  function linkArgumentsOnCall(args, params, graph) {
76
76
  const nameArgMap = new Map(args.filter(graph_1.isNamedArgument).map(a => [a.name, a]));
77
- const nameParamMap = new Map(params.filter(p => p !== undefined && p.name !== undefined && p.name.content !== undefined).map(p => [p.name.content, p]));
77
+ const nameParamMap = new Map(params.filter(p => p?.name?.content !== undefined).map(p => [p.name.content, p]));
78
78
  const specialDotParameter = params.find(p => p.special);
79
79
  // all parameters matched by name
80
80
  const matchedParameters = new Set();
81
81
  // first map names
82
82
  for (const [name, arg] of nameArgMap) {
83
- const pmatchName = (0, prefix_1.findByPrefixIfUnique)(name, [...nameParamMap.keys()]) ?? name;
83
+ const pmatchName = (0, prefix_1.findByPrefixIfUnique)(name, nameParamMap.keys()) ?? name;
84
84
  const param = nameParamMap.get(pmatchName);
85
- if (param !== undefined && param.name) {
85
+ if (param?.name) {
86
86
  logger_1.dataflowLogger.trace(`mapping named argument "${name}" to parameter "${param.name.content}"`);
87
87
  graph.addEdge(arg.nodeId, param.name.info.id, edge_1.EdgeType.DefinesOnCall);
88
88
  graph.addEdge(param.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
89
89
  matchedParameters.add(name);
90
90
  }
91
- else if (specialDotParameter !== undefined && specialDotParameter.name) {
91
+ else if (specialDotParameter?.name) {
92
92
  logger_1.dataflowLogger.trace(`mapping named argument "${name}" to dot-dot-dot parameter`);
93
93
  graph.addEdge(arg.nodeId, specialDotParameter.name.info.id, edge_1.EdgeType.DefinesOnCall);
94
94
  graph.addEdge(specialDotParameter.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
95
95
  }
96
96
  }
97
- const remainingParameter = params.filter(p => !p || !p.name || !matchedParameters.has(p.name.content));
97
+ const remainingParameter = params.filter(p => !p?.name || !matchedParameters.has(p.name.content));
98
98
  const remainingArguments = args.filter(a => !(0, graph_1.isNamedArgument)(a));
99
99
  for (let i = 0; i < remainingArguments.length; i++) {
100
100
  const arg = remainingArguments[i];
@@ -169,14 +169,14 @@ function linkFunctionCall(graph, id, info, idMap, thisGraph, calledFunctionDefin
169
169
  return;
170
170
  }
171
171
  const readBits = edge_1.EdgeType.Reads | edge_1.EdgeType.Calls;
172
- const functionDefinitionReadIds = [...edges].filter(([_, e]) => (0, edge_1.edgeDoesNotIncludeType)(e.types, edge_1.EdgeType.Argument)
172
+ const functionDefinitionReadIds = edges.entries().filter(([_, e]) => (0, edge_1.edgeDoesNotIncludeType)(e.types, edge_1.EdgeType.Argument)
173
173
  && (0, edge_1.edgeIncludesType)(e.types, readBits)).map(([target, _]) => target);
174
174
  const functionDefs = getAllLinkedFunctionDefinitions(new Set(functionDefinitionReadIds), graph)[0];
175
175
  for (const def of functionDefs.values()) {
176
176
  (0, assert_1.guard)(def.tag === vertex_1.VertexType.FunctionDefinition, () => `expected function definition, but got ${def.tag}`);
177
177
  linkFunctionCallWithSingleTarget(graph, def, info, idMap);
178
178
  }
179
- if (thisGraph.isRoot(id)) {
179
+ if (thisGraph.isRoot(id) && functionDefs.size > 0) {
180
180
  calledFunctionDefinitions.push({ functionCall: id, called: [...functionDefs.values()] });
181
181
  }
182
182
  }
@@ -189,7 +189,7 @@ function linkFunctionCall(graph, id, info, idMap, thisGraph, calledFunctionDefin
189
189
  * @param thisGraph - The graph to search for function calls in
190
190
  */
191
191
  function linkFunctionCalls(graph, idMap, thisGraph) {
192
- const functionCalls = [...thisGraph.vertices(true)]
192
+ const functionCalls = thisGraph.vertices(true)
193
193
  .filter(([_, info]) => info.tag === vertex_1.VertexType.FunctionCall);
194
194
  const calledFunctionDefinitions = [];
195
195
  for (const [id, info] of functionCalls) {
@@ -112,7 +112,7 @@ function processNumberBasedAccess(data, name, args, rootId, config, head) {
112
112
  data.environment.current.memory.set(':=', existing);
113
113
  }
114
114
  if (head.value && outInfo.definitionRootNodes.length > 0) {
115
- (0, built_in_assignment_1.markAsAssignment)(fnCall.information, { type: identifier_1.ReferenceType.Variable, name: head.value.lexeme ?? '', nodeId: head.value.info.id, definedAt: rootId, controlDependencies: [] }, outInfo.definitionRootNodes, rootId, data.flowrConfig);
115
+ (0, built_in_assignment_1.markAsAssignment)(fnCall.information, { type: identifier_1.ReferenceType.Variable, name: head.value.lexeme ?? '', nodeId: head.value.info.id, definedAt: rootId, controlDependencies: [] }, outInfo.definitionRootNodes, rootId, data);
116
116
  }
117
117
  if (data.flowrConfig.solver.pointerTracking) {
118
118
  referenceAccessedIndices(args, data, fnCall, rootId, true);
@@ -10,7 +10,6 @@ import type { ContainerIndicesCollection } from '../../../../../graph/vertex';
10
10
  import type { ForceArguments } from '../common';
11
11
  import type { REnvironmentInformation } from '../../../../../environments/environment';
12
12
  import type { DataflowGraph } from '../../../../../graph/graph';
13
- import type { FlowrConfigOptions } from '../../../../../../config';
14
13
  export interface AssignmentConfiguration extends ForceArguments {
15
14
  readonly superAssignment?: boolean;
16
15
  readonly swapSourceAndTarget?: boolean;
@@ -44,10 +43,10 @@ export interface AssignmentToSymbolParameters<OtherInfo> extends AssignmentConfi
44
43
  * @param nodeToDefine - `x`
45
44
  * @param sourceIds - `v`
46
45
  * @param rootIdOfAssignment - `<-`
47
- * @param config - The flowr config
46
+ * @param data - The dataflow analysis fold backpack
48
47
  * @param assignmentConfig - configuration for the assignment processing
49
48
  */
50
- export declare function markAsAssignment(information: {
49
+ export declare function markAsAssignment<OtherInfo>(information: {
51
50
  environment: REnvironmentInformation;
52
51
  graph: DataflowGraph;
53
- }, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId, config: FlowrConfigOptions, assignmentConfig?: AssignmentConfiguration): void;
52
+ }, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId, data: DataflowProcessorInformation<OtherInfo>, assignmentConfig?: AssignmentConfiguration): void;
@@ -215,11 +215,11 @@ function checkTargetReferenceType(source, sourceInfo) {
215
215
  * @param nodeToDefine - `x`
216
216
  * @param sourceIds - `v`
217
217
  * @param rootIdOfAssignment - `<-`
218
- * @param config - The flowr config
218
+ * @param data - The dataflow analysis fold backpack
219
219
  * @param assignmentConfig - configuration for the assignment processing
220
220
  */
221
- function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, config, assignmentConfig) {
222
- if (config.solver.pointerTracking) {
221
+ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, data, assignmentConfig) {
222
+ if (data.flowrConfig.solver.pointerTracking) {
223
223
  let indicesCollection = undefined;
224
224
  if (sourceIds.length === 1) {
225
225
  // support for tracking indices.
@@ -248,7 +248,7 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
248
248
  }
249
249
  nodeToDefine.indicesCollection ??= indicesCollection;
250
250
  }
251
- information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, config);
251
+ information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, data.flowrConfig);
252
252
  information.graph.setDefinitionOfVertex(nodeToDefine);
253
253
  if (!assignmentConfig?.quoteSource) {
254
254
  for (const sourceId of sourceIds) {
@@ -285,7 +285,7 @@ function processAssignmentToSymbol(config) {
285
285
  information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
286
286
  // install assigned variables in environment
287
287
  for (const write of writeNodes) {
288
- markAsAssignment(information, write, [source.info.id], rootId, data.flowrConfig, config);
288
+ markAsAssignment(information, write, [source.info.id], rootId, data, config);
289
289
  }
290
290
  information.graph.addEdge(rootId, targetArg.entryPoint, edge_1.EdgeType.Returns);
291
291
  if (quoteSource) {
@@ -50,24 +50,24 @@ function linkReadNameToWriteIfPossible(read, environments, listEnvironments, rem
50
50
  }
51
51
  function processNextExpression(currentElement, environment, listEnvironments, remainingRead, nextGraph) {
52
52
  // all inputs that have not been written until now are read!
53
- for (const read of [...currentElement.in, ...currentElement.unknownReferences]) {
53
+ for (const read of currentElement.in.concat(currentElement.unknownReferences)) {
54
54
  linkReadNameToWriteIfPossible(read, environment, listEnvironments, remainingRead, nextGraph);
55
55
  }
56
56
  }
57
57
  function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextGraph, localDefs) {
58
58
  for (const { functionCall, called } of calledEnvs) {
59
- const callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
59
+ let callDependencies = null;
60
60
  for (const calledFn of called) {
61
61
  (0, assert_1.guard)(calledFn.tag === vertex_1.VertexType.FunctionDefinition, 'called function must be a function definition');
62
62
  // only merge the environments they have in common
63
- let environment = calledFn.environment;
63
+ let environment = calledFn.subflow.environment;
64
64
  while (environment.level > inputEnvironment.level) {
65
65
  environment = (0, scoping_1.popLocalEnvironment)(environment);
66
66
  }
67
67
  // update alle definitions to be defined at this function call
68
68
  let current = environment.current;
69
69
  let hasUpdate = false;
70
- while (current !== undefined && current.id !== environment_1.BuiltInEnvironment.id) {
70
+ while (!current?.builtInEnv) {
71
71
  for (const definitions of current.memory.values()) {
72
72
  for (const def of definitions) {
73
73
  if (!(0, built_in_1.isBuiltIn)(def.definedAt)) {
@@ -84,6 +84,9 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
84
84
  if (localDefs.length > 0) {
85
85
  environment = (0, remove_1.removeAll)(localDefs, environment);
86
86
  }
87
+ if (callDependencies === null) {
88
+ callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
89
+ }
87
90
  inputEnvironment = (0, overwrite_1.overwriteEnvironment)(inputEnvironment, environment, callDependencies);
88
91
  }
89
92
  }
@@ -110,7 +113,7 @@ function processExpressionList(name, args, rootId, data) {
110
113
  continue;
111
114
  }
112
115
  // use the current environments for processing
113
- data = { ...data, environment: environment };
116
+ data.environment = environment;
114
117
  const processed = (0, processor_1.processDataflowFor)(expression, data);
115
118
  processedExpressions.push(processed);
116
119
  nextGraph.mergeWith(processed.graph);
@@ -140,7 +143,6 @@ function processExpressionList(name, args, rootId, data) {
140
143
  break;
141
144
  }
142
145
  }
143
- logger_1.dataflowLogger.trace(`expression list exits with ${remainingRead.size} remaining read names`);
144
146
  if (defaultReturnExpr) {
145
147
  exitPoints.push({
146
148
  type: 0 /* ExitPointType.Default */,
@@ -148,7 +150,7 @@ function processExpressionList(name, args, rootId, data) {
148
150
  controlDependencies: data.controlDependencies
149
151
  });
150
152
  }
151
- const ingoing = [...remainingRead.values()].flat();
153
+ const ingoing = [...remainingRead.values().flatMap(v => v)];
152
154
  const rootNode = data.completeAst.idMap.get(rootId);
153
155
  const withGroup = rootNode?.grouping;
154
156
  if (withGroup) {
@@ -107,7 +107,7 @@ function processFunctionDefinition(name, args, rootId, data) {
107
107
  // this is no longer necessary when we update environments to be back to front (e.g., with a list of environments)
108
108
  // this favors the bigger environment
109
109
  function retrieveActiveEnvironment(callerEnvironment, baseEnvironment) {
110
- callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(true);
110
+ callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(undefined, true);
111
111
  let level = callerEnvironment.level ?? 0;
112
112
  if (baseEnvironment.level !== level) {
113
113
  while (baseEnvironment.level < level) {
@@ -212,7 +212,7 @@ function updateNestedFunctionCalls(graph, outEnvironment) {
212
212
  }
213
213
  }
214
214
  function prepareFunctionEnvironment(data) {
215
- let env = (0, environment_1.initializeCleanEnvironments)();
215
+ let env = (0, environment_1.initializeCleanEnvironments)(data.builtInEnvironment.memory);
216
216
  for (let i = 0; i < data.environment.level + 1 /* add another env */; i++) {
217
217
  env = (0, scoping_1.pushLocalEnvironment)(env);
218
218
  }
@@ -31,7 +31,7 @@ function processRm(name, args, rootId, data) {
31
31
  }
32
32
  let env = res.environment;
33
33
  for (const name of names) {
34
- env = (0, remove_1.remove)(name, env);
34
+ env = (0, remove_1.remove)(name, env, data.builtInEnvironment);
35
35
  }
36
36
  return {
37
37
  ...res,
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import type { ControlDependency, DataflowInformation } from './info';
5
5
  import type { NormalizedAst, ParentInformation, RNodeWithParent } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
6
- import type { REnvironmentInformation } from './environments/environment';
6
+ import type { IEnvironment, REnvironmentInformation } from './environments/environment';
7
7
  import type { RParseRequest } from '../r-bridge/retriever';
8
8
  import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
9
9
  import type { KnownParserType, Parser } from '../r-bridge/parser';
@@ -36,6 +36,10 @@ export interface DataflowProcessorInformation<OtherInfo> {
36
36
  * The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
37
37
  */
38
38
  readonly controlDependencies: ControlDependency[] | undefined;
39
+ /**
40
+ * The built-in environment
41
+ */
42
+ readonly builtInEnvironment: IEnvironment;
39
43
  /**
40
44
  * The flowr configuration used for environment seeding, and precision control
41
45
  */
@@ -1,13 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.printEnvironmentToMarkdown = printEnvironmentToMarkdown;
4
- const environment_1 = require("../../dataflow/environments/environment");
5
4
  const dfg_1 = require("../../util/mermaid/dfg");
6
5
  function printEnvironmentToMarkdown(env) {
7
6
  if (env === undefined) {
8
7
  return '?? (error)';
9
8
  }
10
- else if (env.id === environment_1.BuiltInEnvironment.id) {
9
+ else if (env.builtInEnv) {
11
10
  return `_Built-in Environment (${env.memory.size} entries)_`;
12
11
  }
13
12
  const lines = ['| Name | Definitions |', '|------|-------------|'];
@@ -25,7 +25,7 @@ async function showQuery(shell, code, queries, { showCode, collapseResult, colla
25
25
  parser: shell,
26
26
  request: (0, retriever_1.requestFromInput)(code)
27
27
  }, config_1.defaultConfigOptions).allRemainingSteps();
28
- const results = (0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries);
28
+ const results = await Promise.resolve((0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries));
29
29
  const duration = performance.now() - now;
30
30
  const metaInfo = `
31
31
  The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
@@ -53,13 +53,13 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify(search, null, 2))}
53
53
  ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
54
54
 
55
55
  The query returns the following vetices (all references to \`x\` in the code):
56
- ${result.map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
56
+ ${result.getElements().map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
57
57
 
58
58
  ${metaInfo}
59
59
 
60
60
  The returned results are highlighted thick and blue within the dataflow graph:
61
61
 
62
- ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.map(({ node }) => node.info.id)) })}
62
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.getElements().map(({ node }) => node.info.id)) })}
63
63
 
64
64
 
65
65
  ${collapseResult ? '</details>' : ''}
@@ -224,8 +224,7 @@ ${Object.entries(control_flow_graph_1.CfgVertexType).map(([key, value]) => `- \`
224
224
  We use the ${(0, doc_types_1.shortLink)('CfgBasicBlockVertex', types.info)} to represent [basic blocks](#cfg-basic-blocks) and separate
225
225
  expressions (${(0, doc_types_1.shortLink)('CfgExpressionVertex', types.info)}) and statements (${(0, doc_types_1.shortLink)('CfgStatementVertex', types.info)})
226
226
  as control flow units with and without side effects (if you want to, you can see view statements as effectful expressions).
227
- The markers (${(0, doc_types_1.shortLink)('CfgMidMarkerVertex', types.info)} and ${(0, doc_types_1.shortLink)('CfgEndMarkerVertex', types.info)})
228
- indicate specific segments of larger expressions/statements (e.g., an \`if\` which has a condition and its branches).
227
+ The markers (${(0, doc_types_1.shortLink)('CfgEndMarkerVertex', types.info)}) indicate the end of larger expressions/statements.
229
228
 
230
229
  To signal these links, the expressions and statements contain information about the attached markers:
231
230
 
@@ -235,7 +234,7 @@ Similarly, the markers contain a link to their root:
235
234
 
236
235
  ${(0, doc_types_1.printHierarchy)({ info: types.info, root: 'CfgWithRoot', program: types.program, openTop: true })}
237
236
 
238
- In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions, circles for exit markers and double-lined rectangles for mid markers.
237
+ In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions and circles for exit markers.
239
238
  Blocks are visualized as boxes around the contained vertices.
240
239
 
241
240
  ${(0, doc_structure_1.block)({
@@ -554,7 +553,7 @@ Hence, you may rely on the corresponding exit point(s) to identify all exits of
554
553
 
555
554
  ${(0, doc_structure_1.block)({
556
555
  type: 'WARNING',
557
- content: 'Using basic blocks, this works just the same. However please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
556
+ content: 'Using basic blocks, this works just the same. However, please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
558
557
  })}
559
558
 
560
559
  `;
@@ -28,7 +28,6 @@ const built_in_access_1 = require("../dataflow/internal/process/functions/call/b
28
28
  const built_in_for_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-for-loop");
29
29
  const built_in_repeat_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-repeat-loop");
30
30
  const linker_1 = require("../dataflow/internal/linker");
31
- const static_slicer_1 = require("../slicing/static/static-slicer");
32
31
  const info_1 = require("../dataflow/info");
33
32
  const processor_1 = require("../dataflow/processor");
34
33
  const default_pipelines_1 = require("../core/steps/pipeline/default-pipelines");
@@ -42,6 +41,7 @@ const normalize_for_1 = require("../r-bridge/lang-4.x/ast/parser/main/internal/l
42
41
  const doc_issue_1 = require("./doc-util/doc-issue");
43
42
  const pipeline_executor_1 = require("../core/pipeline-executor");
44
43
  const pipeline_1 = require("../core/steps/pipeline/pipeline");
44
+ const static_slicer_1 = require("../slicing/static/static-slicer");
45
45
  const config_1 = require("../config");
46
46
  async function getText(shell) {
47
47
  const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
@@ -373,7 +373,7 @@ Of course, all of these endeavors work not just with the ${(0, doc_types_1.short
373
373
  The slicing is available as an extra step as you can see by inspecting he ${(0, doc_types_1.shortLink)('DEFAULT_SLICING_PIPELINE', info)}.
374
374
  Besides ${(0, doc_types_1.shortLink)('STATIC_SLICE', info)} it contains a ${(0, doc_types_1.shortLink)('NAIVE_RECONSTRUCT', info)} to print the slice as (executable) R code.
375
375
 
376
- Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.staticSlicing.name, info)} function which relies on a modified
376
+ Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.staticSlice.name, info)} function which relies on a modified
377
377
  breadth-first search to collect all nodes which are part of the slice.
378
378
  For more information on how the slicing works, please refer to the [tool demonstration (Section 3.2)](https://doi.org/10.1145/3691620.3695359),
379
379
  or the [original master's thesis (Chapter 4)](https://doi.org/10.18725/OPARU-50107).
@@ -835,6 +835,13 @@ The following sections present details on the different types of vertices and ed
835
835
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', 'const node = graph.idMap.get(id);'), '> ')}
836
836
  > In case you just need the name (\`lexeme\`) of the respective vertex, ${(0, doc_types_1.shortLink)(node_id_1.recoverName.name, vertexType.info)} can help you out:
837
837
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`), '> ')}
838
+ >
839
+ > Please note that not every node in the normalized AST is represented in the dataflow graph.
840
+ > For example, if the node is unreachable in a way that can be detected during the analysis and flowR
841
+ > is configured to ignore dead code. Likewise, empty argument wrappers do not have a corresponding
842
+ > dataflow graph vertex (as they are not relevant for the dataflow graph). It depends on the scenario what to do in such a case.
843
+ > For argument wrappers you can access the dataflow information for their value. For dead code, however, flowR currently contains
844
+ > some core heuristics that remove it which cannot be reversed easily. So please open [an issue](${doc_issue_1.NewIssueUrl}) if you encounter such a case and require the node to be present in the dataflow graph.
838
845
 
839
846
  ${(0, doc_structure_1.section)('Vertices', 2, 'vertices')}
840
847
 
@@ -39,6 +39,10 @@ With \`npm\` you have to pass arguments in a specific way. The \`--\` operator i
39
39
  ${(0, doc_code_1.codeBlock)('shell', 'npm run flowR -- --help')}
40
40
  `)}
41
41
 
42
+ ${qAndA('How to do logging in flowR?', `
43
+ Check out the [Logging Section in the Linting and Testing wiki page](${doc_files_1.FlowrWikiBaseRef}/Linting-and-Testing#logging) for more information on how to do logging in *flowR*.
44
+ `)}
45
+
42
46
  ## 🇷 R FAQ
43
47
 
44
48
  ### 📦 R Packages