@eagleoutice/flowr 2.2.10 → 2.2.12

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 (132) hide show
  1. package/README.md +4 -4
  2. package/benchmark/slicer.d.ts +49 -22
  3. package/benchmark/slicer.js +88 -28
  4. package/benchmark/stats/print.js +16 -10
  5. package/benchmark/stats/size-of.js +18 -1
  6. package/benchmark/stats/stats.d.ts +3 -0
  7. package/benchmark/summarizer/second-phase/process.js +8 -2
  8. package/cli/benchmark-app.d.ts +5 -0
  9. package/cli/benchmark-app.js +49 -6
  10. package/cli/benchmark-helper-app.d.ts +4 -0
  11. package/cli/benchmark-helper-app.js +20 -4
  12. package/cli/common/options.js +13 -4
  13. package/cli/repl/commands/repl-commands.js +2 -0
  14. package/cli/repl/commands/repl-dataflow.d.ts +2 -0
  15. package/cli/repl/commands/repl-dataflow.js +35 -1
  16. package/cli/repl/server/compact.d.ts +2 -2
  17. package/cli/repl/server/compact.js +3 -3
  18. package/cli/repl/server/messages/message-analysis.d.ts +2 -2
  19. package/cli/repl/server/messages/message-analysis.js +2 -2
  20. package/config.d.ts +27 -2
  21. package/config.js +30 -4
  22. package/dataflow/environments/built-in-config.d.ts +5 -2
  23. package/dataflow/environments/built-in-config.js +8 -2
  24. package/dataflow/environments/built-in.d.ts +8 -1
  25. package/dataflow/environments/built-in.js +8 -1
  26. package/dataflow/environments/clone.d.ts +5 -0
  27. package/dataflow/environments/clone.js +5 -0
  28. package/dataflow/environments/default-builtin-config.js +96 -10
  29. package/dataflow/environments/define.d.ts +5 -1
  30. package/dataflow/environments/define.js +36 -10
  31. package/dataflow/environments/environment.js +4 -2
  32. package/dataflow/environments/overwrite.js +4 -0
  33. package/dataflow/environments/remove.d.ts +6 -0
  34. package/dataflow/environments/remove.js +24 -0
  35. package/dataflow/environments/resolve-by-name.js +1 -1
  36. package/dataflow/extractor.d.ts +1 -1
  37. package/dataflow/extractor.js +8 -6
  38. package/dataflow/graph/dataflowgraph-builder.d.ts +76 -6
  39. package/dataflow/graph/dataflowgraph-builder.js +102 -6
  40. package/dataflow/graph/edge.js +4 -1
  41. package/dataflow/graph/graph.d.ts +12 -1
  42. package/dataflow/graph/graph.js +37 -0
  43. package/dataflow/graph/vertex.d.ts +42 -2
  44. package/dataflow/graph/vertex.js +32 -0
  45. package/dataflow/internal/linker.js +3 -1
  46. package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +3 -0
  47. package/dataflow/internal/process/functions/call/argument/unpack-argument.js +4 -10
  48. package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -0
  49. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +55 -45
  50. package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +6 -4
  51. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +27 -8
  52. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +37 -7
  53. package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +10 -0
  54. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +140 -0
  55. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +4 -3
  56. package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
  57. package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +21 -3
  58. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +3 -0
  59. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +83 -29
  60. package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +7 -0
  61. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +41 -0
  62. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +20 -6
  63. package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +15 -0
  64. package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +75 -0
  65. package/dataflow/internal/process/functions/call/common.d.ts +1 -1
  66. package/dataflow/internal/process/functions/call/common.js +4 -2
  67. package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -0
  68. package/dataflow/internal/process/functions/call/named-call-handling.js +9 -5
  69. package/dataflow/internal/process/process-named-call.d.ts +3 -0
  70. package/dataflow/internal/process/process-named-call.js +3 -0
  71. package/dataflow/processor.d.ts +7 -7
  72. package/documentation/data/server/doc-data-server-messages.js +2 -2
  73. package/documentation/doc-util/doc-cfg.d.ts +11 -2
  74. package/documentation/doc-util/doc-cfg.js +35 -6
  75. package/documentation/doc-util/doc-code.js +10 -2
  76. package/documentation/print-capabilities-markdown.js +1 -1
  77. package/documentation/print-cfg-wiki.d.ts +1 -0
  78. package/documentation/print-cfg-wiki.js +84 -0
  79. package/documentation/print-core-wiki.js +2 -2
  80. package/documentation/print-interface-wiki.js +4 -0
  81. package/documentation/print-query-wiki.js +22 -3
  82. package/package.json +4 -3
  83. package/queries/catalog/call-context-query/call-context-query-executor.js +13 -0
  84. package/queries/catalog/call-context-query/call-context-query-format.d.ts +4 -0
  85. package/queries/catalog/call-context-query/call-context-query-format.js +1 -0
  86. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
  87. package/queries/catalog/dependencies-query/dependencies-query-executor.js +13 -5
  88. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -25
  89. package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -145
  90. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +24 -0
  91. package/queries/catalog/dependencies-query/function-info/function-info.js +10 -0
  92. package/queries/catalog/dependencies-query/function-info/library-functions.d.ts +2 -0
  93. package/queries/catalog/dependencies-query/function-info/library-functions.js +18 -0
  94. package/queries/catalog/dependencies-query/function-info/read-functions.d.ts +2 -0
  95. package/queries/catalog/dependencies-query/function-info/read-functions.js +101 -0
  96. package/queries/catalog/dependencies-query/function-info/source-functions.d.ts +2 -0
  97. package/queries/catalog/dependencies-query/function-info/source-functions.js +11 -0
  98. package/queries/catalog/dependencies-query/function-info/write-functions.d.ts +2 -0
  99. package/queries/catalog/dependencies-query/function-info/write-functions.js +87 -0
  100. package/queries/catalog/location-map-query/location-map-query-executor.d.ts +1 -1
  101. package/queries/catalog/location-map-query/location-map-query-executor.js +38 -3
  102. package/queries/catalog/location-map-query/location-map-query-format.d.ts +10 -1
  103. package/queries/catalog/location-map-query/location-map-query-format.js +5 -1
  104. package/queries/catalog/project-query/project-query-executor.d.ts +3 -0
  105. package/queries/catalog/project-query/project-query-executor.js +17 -0
  106. package/queries/catalog/project-query/project-query-format.d.ts +67 -0
  107. package/queries/catalog/project-query/project-query-format.js +26 -0
  108. package/queries/query.d.ts +60 -1
  109. package/queries/query.js +3 -1
  110. package/r-bridge/data/data.d.ts +2 -2
  111. package/r-bridge/data/data.js +2 -2
  112. package/slicing/static/fingerprint.js +8 -1
  113. package/slicing/static/slice-call.d.ts +1 -1
  114. package/slicing/static/slice-call.js +5 -16
  115. package/slicing/static/slicer-types.d.ts +2 -0
  116. package/slicing/static/static-slicer.d.ts +4 -2
  117. package/slicing/static/static-slicer.js +24 -18
  118. package/slicing/static/visiting-queue.d.ts +7 -1
  119. package/slicing/static/visiting-queue.js +20 -6
  120. package/util/arrays.d.ts +23 -0
  121. package/util/arrays.js +41 -0
  122. package/util/cfg/visitor.d.ts +1 -1
  123. package/util/cfg/visitor.js +2 -2
  124. package/util/{list-access.d.ts → containers.d.ts} +24 -4
  125. package/util/{list-access.js → containers.js} +42 -12
  126. package/util/mermaid/ast.js +12 -1
  127. package/util/mermaid/cfg.js +2 -2
  128. package/util/parallel.d.ts +2 -1
  129. package/util/parallel.js +11 -2
  130. package/util/prefix.d.ts +13 -0
  131. package/util/prefix.js +34 -0
  132. package/util/version.js +1 -1
@@ -55,6 +55,8 @@ function getReferenceOfArgument(arg) {
55
55
  class DataflowGraph {
56
56
  static DEFAULT_ENVIRONMENT = undefined;
57
57
  _idMap;
58
+ /** all file paths included in this dfg */
59
+ _sourced = [];
58
60
  /*
59
61
  * Set of vertices which have sideEffects that we do not know anything about.
60
62
  * As a (temporary) solution until we have FD edges, a side effect may also store known target links
@@ -113,6 +115,13 @@ class DataflowGraph {
113
115
  get idMap() {
114
116
  return this._idMap;
115
117
  }
118
+ get sourced() {
119
+ return this._sourced;
120
+ }
121
+ /** Mark this file as being part of the dfg */
122
+ addFile(source) {
123
+ this._sourced.push(source);
124
+ }
116
125
  /**
117
126
  * Retrieves the set of vertices which have side effects that we do not know anything about.
118
127
  */
@@ -235,6 +244,7 @@ class DataflowGraph {
235
244
  this.rootVertices.add(root);
236
245
  }
237
246
  }
247
+ this.sourced.push(...otherGraph.sourced);
238
248
  for (const unknown of otherGraph.unknownSideEffects) {
239
249
  this._unknownSideEffects.add(unknown);
240
250
  }
@@ -325,7 +335,15 @@ class DataflowGraph {
325
335
  const graph = new DataflowGraph(undefined);
326
336
  graph.rootVertices = new Set(data.rootVertices);
327
337
  graph.vertexInformation = new Map(data.vertexInformation);
338
+ for (const [, vertex] of graph.vertexInformation) {
339
+ if (vertex.environment) {
340
+ vertex.environment = renvFromJson(vertex.environment);
341
+ }
342
+ }
328
343
  graph.edgeInformation = new Map(data.edgeInformation.map(([id, edges]) => [id, new Map(edges)]));
344
+ if (data.sourced) {
345
+ graph._sourced = data.sourced;
346
+ }
329
347
  return graph;
330
348
  }
331
349
  }
@@ -355,4 +373,23 @@ function extractEdgeIds(from, to) {
355
373
  const toId = typeof to === 'object' ? to.nodeId : to;
356
374
  return [fromId, toId];
357
375
  }
376
+ function envFromJson(json) {
377
+ const parent = json.parent ? envFromJson(json.parent) : undefined;
378
+ const memory = new Map();
379
+ for (const [key, value] of Object.entries(json.memory)) {
380
+ memory.set(key, value);
381
+ }
382
+ return {
383
+ id: json.id,
384
+ parent: parent,
385
+ memory
386
+ };
387
+ }
388
+ function renvFromJson(json) {
389
+ const current = envFromJson(json.current);
390
+ return {
391
+ current,
392
+ level: json.level
393
+ };
394
+ }
358
395
  //# sourceMappingURL=graph.js.map
@@ -14,6 +14,36 @@ export declare const ValidVertexTypes: Set<string>;
14
14
  export declare const ValidVertexTypeReverse: {
15
15
  [k: string]: string;
16
16
  };
17
+ /**
18
+ * Identifier for arguments e.g. for `3` in `c(2, 3, 5)` the identifier would be
19
+ * ```ts
20
+ * {
21
+ * index: 2
22
+ * }
23
+ * ```
24
+ */
25
+ export interface UnnamedArgumentId {
26
+ readonly index: number;
27
+ }
28
+ /**
29
+ * Identifier for named arguments e.g. for `age` in `list(name = 'John', age = 8)`
30
+ * the indentifier would be
31
+ * ```ts
32
+ * {
33
+ * index: 2,
34
+ * lexeme: 'age'
35
+ * }
36
+ * ```
37
+ */
38
+ export interface NamedArgumentId {
39
+ /**
40
+ * Index may be undefined, when no index information is available.
41
+ */
42
+ readonly index: number | undefined;
43
+ readonly lexeme: string;
44
+ }
45
+ export declare function isNamedArgumentId(identifier: IndexIdentifier): identifier is NamedArgumentId;
46
+ export type IndexIdentifier = UnnamedArgumentId | NamedArgumentId;
17
47
  /**
18
48
  * A single index of a container, which is not a container itself.
19
49
  *
@@ -21,9 +51,9 @@ export declare const ValidVertexTypeReverse: {
21
51
  */
22
52
  export interface ContainerLeafIndex {
23
53
  /**
24
- * Distinctive lexeme of index e.g. 'name' for `list(name = 'John')`
54
+ * Distinctive identifier of index, see {@link IndexIdentifier}.
25
55
  */
26
- readonly lexeme: string;
56
+ readonly identifier: IndexIdentifier;
27
57
  /**
28
58
  * NodeId of index in graph.
29
59
  */
@@ -48,6 +78,16 @@ export declare function isParentContainerIndex(index: ContainerIndex): index is
48
78
  * A single index of a container.
49
79
  */
50
80
  export type ContainerIndex = ContainerLeafIndex | ContainerParentIndex;
81
+ /**
82
+ * Checks whether {@link index} is accessed by {@link accessLexeme}.
83
+ *
84
+ * @param index - The {@link ContainerIndex}, which is accessed
85
+ * @param accessLexeme - The access lexeme
86
+ * @param isIndexBasedAccess - Whether the index of the {@link ContainerIndex} is accessed i.e. the position in the container and not e.g. the name of the index
87
+ * @returns true, when {@link accessLexeme} accesses the {@link index}, false otherwise
88
+ */
89
+ export declare function isAccessed(index: ContainerIndex, accessLexeme: string, isIndexBasedAccess: boolean): boolean;
90
+ export declare function isSameIndex(a: ContainerIndex, b: ContainerIndex): boolean;
51
91
  /**
52
92
  * List of indices of a single statement like `list(a=3, b=2)`
53
93
  */
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ValidVertexTypeReverse = exports.ValidVertexTypes = exports.VertexType = void 0;
4
+ exports.isNamedArgumentId = isNamedArgumentId;
4
5
  exports.isParentContainerIndex = isParentContainerIndex;
6
+ exports.isAccessed = isAccessed;
7
+ exports.isSameIndex = isSameIndex;
5
8
  exports.isValueVertex = isValueVertex;
6
9
  exports.isUseVertex = isUseVertex;
7
10
  exports.isFunctionCallVertex = isFunctionCallVertex;
@@ -17,9 +20,38 @@ var VertexType;
17
20
  })(VertexType || (exports.VertexType = VertexType = {}));
18
21
  exports.ValidVertexTypes = new Set(Object.values(VertexType));
19
22
  exports.ValidVertexTypeReverse = Object.fromEntries(Object.entries(VertexType).map(([k, v]) => [v, k]));
23
+ function isNamedArgumentId(identifier) {
24
+ return 'lexeme' in identifier;
25
+ }
20
26
  function isParentContainerIndex(index) {
21
27
  return 'subIndices' in index;
22
28
  }
29
+ /**
30
+ * Checks whether {@link index} is accessed by {@link accessLexeme}.
31
+ *
32
+ * @param index - The {@link ContainerIndex}, which is accessed
33
+ * @param accessLexeme - The access lexeme
34
+ * @param isIndexBasedAccess - Whether the index of the {@link ContainerIndex} is accessed i.e. the position in the container and not e.g. the name of the index
35
+ * @returns true, when {@link accessLexeme} accesses the {@link index}, false otherwise
36
+ */
37
+ function isAccessed(index, accessLexeme, isIndexBasedAccess) {
38
+ if (isIndexBasedAccess) {
39
+ return index.identifier.index === Number(accessLexeme);
40
+ }
41
+ if (isNamedArgumentId(index.identifier)) {
42
+ return index.identifier.lexeme === accessLexeme;
43
+ }
44
+ return false;
45
+ }
46
+ function isSameIndex(a, b) {
47
+ if (isNamedArgumentId(a.identifier) && isNamedArgumentId(b.identifier)) {
48
+ return a.identifier.lexeme === b.identifier.lexeme;
49
+ }
50
+ if (a.identifier.index === undefined || b.identifier.index === undefined) {
51
+ return false;
52
+ }
53
+ return a.identifier.index === b.identifier.index;
54
+ }
23
55
  /**
24
56
  * Check if the given vertex is a {@link DataflowGraphVertexValue|value vertex}.
25
57
  */
@@ -23,6 +23,7 @@ const vertex_1 = require("../graph/vertex");
23
23
  const resolve_by_name_1 = require("../environments/resolve-by-name");
24
24
  const built_in_1 = require("../environments/built-in");
25
25
  const static_slicer_1 = require("../../slicing/static/static-slicer");
26
+ const prefix_1 = require("../../util/prefix");
26
27
  function findNonLocalReads(graph, ignore) {
27
28
  const ignores = new Set(ignore.map(i => i.nodeId));
28
29
  const ids = new Set([...graph.vertices(true)]
@@ -80,7 +81,8 @@ function linkArgumentsOnCall(args, params, graph) {
80
81
  const matchedParameters = new Set();
81
82
  // first map names
82
83
  for (const [name, arg] of nameArgMap) {
83
- const param = nameParamMap.get(name);
84
+ const pmatchName = (0, prefix_1.findByPrefixIfUnique)(name, [...nameParamMap.keys()]) ?? name;
85
+ const param = nameParamMap.get(pmatchName);
84
86
  if (param !== undefined) {
85
87
  logger_1.dataflowLogger.trace(`mapping named argument "${name}" to parameter "${param.name.content}"`);
86
88
  graph.addEdge(arg.nodeId, param.name.info.id, edge_1.EdgeType.DefinesOnCall);
@@ -1,3 +1,6 @@
1
1
  import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
2
2
  import type { RNode } from '../../../../../../r-bridge/lang-4.x/ast/model/model';
3
+ /**
4
+ * Retrieve the value from an argument, if it is not empty.
5
+ */
3
6
  export declare function unpackArgument<OtherInfo>(arg: RFunctionArgument<OtherInfo>, noNameOnly?: boolean): RNode<OtherInfo> | undefined;
@@ -1,17 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.unpackArgument = unpackArgument;
4
- const log_1 = require("../../../../../../util/log");
5
4
  const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
5
+ /**
6
+ * Retrieve the value from an argument, if it is not empty.
7
+ */
6
8
  function unpackArgument(arg, noNameOnly = true) {
7
- if (arg === r_function_call_1.EmptyArgument) {
8
- log_1.log.trace('Argument is empty, skipping');
9
- return undefined;
10
- }
11
- else if (noNameOnly && arg.name !== undefined) {
12
- log_1.log.trace(`Argument ${JSON.stringify(arg)} is not unnamed, skipping`);
13
- return undefined;
14
- }
15
- return arg.value;
9
+ return arg === r_function_call_1.EmptyArgument || (noNameOnly && arg.name) ? undefined : arg.value;
16
10
  }
17
11
  //# sourceMappingURL=unpack-argument.js.map
@@ -19,3 +19,4 @@ import type { ForceArguments } from '../common';
19
19
  export declare function processAccess<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
20
20
  treatIndicesAsString: boolean;
21
21
  } & ForceArguments): DataflowInformation;
22
+ export declare function symbolArgumentsToStrings<OtherInfo>(args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], firstIndexInclusive?: number, lastIndexInclusive?: number): RFunctionArgument<OtherInfo & ParentInformation>[];
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.processAccess = processAccess;
4
+ exports.symbolArgumentsToStrings = symbolArgumentsToStrings;
4
5
  const known_call_handling_1 = require("../known-call-handling");
5
6
  const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
6
7
  const logger_1 = require("../../../../../logger");
@@ -11,7 +12,7 @@ const built_in_1 = require("../../../../../environments/built-in");
11
12
  const built_in_assignment_1 = require("./built-in-assignment");
12
13
  const identifier_1 = require("../../../../../environments/identifier");
13
14
  const vertex_1 = require("../../../../../graph/vertex");
14
- const list_access_1 = require("../../../../../../util/list-access");
15
+ const containers_1 = require("../../../../../../util/containers");
15
16
  const config_1 = require("../../../../../../config");
16
17
  function tableAssignmentProcessor(name, args, rootId, data, outInfo) {
17
18
  outInfo.definitionRootNodes.push(rootId);
@@ -101,6 +102,7 @@ function processNumberBasedAccess(data, name, args, rootId, config, head) {
101
102
  definedAt: built_in_1.BuiltIn,
102
103
  controlDependencies: undefined,
103
104
  processor: (name, args, rootId, data) => tableAssignmentProcessor(name, args, rootId, data, outInfo),
105
+ config: {},
104
106
  name: ':=',
105
107
  nodeId: built_in_1.BuiltIn,
106
108
  }]);
@@ -112,21 +114,15 @@ function processNumberBasedAccess(data, name, args, rootId, config, head) {
112
114
  if (head.value && outInfo.definitionRootNodes.length > 0) {
113
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);
114
116
  }
117
+ if ((0, config_1.getConfig)().solver.pointerTracking) {
118
+ referenceAccessedIndices(args, data, fnCall, rootId, true);
119
+ }
115
120
  return fnCall;
116
121
  }
117
- /**
118
- * Processes different types of string-based access operations.
119
- *
120
- * Example:
121
- * ```r
122
- * a$foo
123
- * a@foo
124
- * ```
125
- */
126
- function processStringBasedAccess(args, data, name, rootId, config) {
122
+ function symbolArgumentsToStrings(args, firstIndexInclusive = 1, lastIndexInclusive = args.length - 1) {
127
123
  const newArgs = [...args];
128
124
  // if the argument is a symbol, we convert it to a string for this perspective
129
- for (let i = 1; i < newArgs.length; i++) {
125
+ for (let i = firstIndexInclusive; i <= lastIndexInclusive; i++) {
130
126
  const arg = newArgs[i];
131
127
  if (arg !== r_function_call_1.EmptyArgument && arg.value?.type === type_1.RType.Symbol) {
132
128
  newArgs[i] = {
@@ -144,47 +140,61 @@ function processStringBasedAccess(args, data, name, rootId, config) {
144
140
  };
145
141
  }
146
142
  }
143
+ return newArgs;
144
+ }
145
+ /**
146
+ * Processes different types of string-based access operations.
147
+ *
148
+ * Example:
149
+ * ```r
150
+ * a$foo
151
+ * a@foo
152
+ * ```
153
+ */
154
+ function processStringBasedAccess(args, data, name, rootId, config) {
155
+ const newArgs = symbolArgumentsToStrings(args);
147
156
  const fnCall = (0, known_call_handling_1.processKnownFunctionCall)({ name, args: newArgs, rootId, data, forceArgs: config.forceArgs });
157
+ if ((0, config_1.getConfig)().solver.pointerTracking) {
158
+ referenceAccessedIndices(newArgs, data, fnCall, rootId, false);
159
+ }
160
+ return fnCall;
161
+ }
162
+ function referenceAccessedIndices(newArgs, data, fnCall, rootId, isIndexBasedAccess) {
148
163
  // Resolve access on the way up the fold
149
- const nonEmptyArgs = newArgs.filter(arg => arg !== r_function_call_1.EmptyArgument);
150
- const accessedArg = nonEmptyArgs.find(arg => arg.info.role === "accessed" /* RoleInParent.Accessed */);
151
- const accessArg = nonEmptyArgs.find(arg => arg.info.role === "index-access" /* RoleInParent.IndexAccess */);
164
+ const { accessedArg, accessArg } = (0, containers_1.getAccessOperands)(newArgs);
152
165
  if (accessedArg === undefined || accessArg === undefined) {
153
- return fnCall;
166
+ return;
154
167
  }
155
- if ((0, config_1.getConfig)().solver.pointerTracking) {
156
- let accessedIndicesCollection;
157
- // If the accessedArg is a symbol, it's either a simple access or the base case of a nested access
158
- if (accessedArg.value?.type === type_1.RType.Symbol) {
159
- accessedIndicesCollection = (0, list_access_1.resolveSingleIndex)(accessedArg, accessArg, data.environment);
168
+ let accessedIndicesCollection;
169
+ // If the accessedArg is a symbol, it's either a simple access or the base case of a nested access
170
+ if (accessedArg.value?.type === type_1.RType.Symbol) {
171
+ accessedIndicesCollection = (0, containers_1.resolveSingleIndex)(accessedArg, accessArg, data.environment, isIndexBasedAccess);
172
+ }
173
+ else {
174
+ // Higher access call
175
+ const underlyingAccessId = accessedArg.value?.info.id ?? -1;
176
+ const vertex = fnCall.information.graph.getVertex(underlyingAccessId);
177
+ const subIndices = vertex?.indicesCollection
178
+ ?.flatMap(indices => indices.indices)
179
+ ?.flatMap(index => index?.subIndices ?? []);
180
+ if (subIndices) {
181
+ accessedIndicesCollection = (0, containers_1.filterIndices)(subIndices, accessArg, isIndexBasedAccess);
160
182
  }
161
- else {
162
- // Higher access call
163
- const underlyingAccessId = accessedArg.value?.info.id ?? -1;
164
- const vertex = fnCall.information.graph.getVertex(underlyingAccessId);
165
- const subIndices = vertex?.indicesCollection
166
- ?.flatMap(indices => indices.indices)
167
- ?.flatMap(index => index?.subIndices ?? []);
168
- if (subIndices) {
169
- accessedIndicesCollection = (0, list_access_1.filterIndices)(subIndices, accessArg);
170
- }
183
+ }
184
+ // Add indices to vertex afterward
185
+ if (accessedIndicesCollection) {
186
+ const vertex = fnCall.information.graph.getVertex(rootId);
187
+ if (vertex) {
188
+ vertex.indicesCollection = accessedIndicesCollection;
171
189
  }
172
- // Add indices to vertex afterward
173
- if (accessedIndicesCollection) {
174
- const vertex = fnCall.information.graph.getVertex(rootId);
175
- if (vertex) {
176
- vertex.indicesCollection = accessedIndicesCollection;
177
- }
178
- // When access has no access as parent, it's the top most
179
- const rootNode = data.completeAst.idMap.get(rootId);
180
- const parentNode = data.completeAst.idMap.get(rootNode?.info.parent ?? -1);
181
- if (parentNode?.type !== type_1.RType.Access) {
182
- // Only reference indices in top most access
183
- referenceIndices(accessedIndicesCollection, fnCall, name.info.id);
184
- }
190
+ // When access has no access as parent, it's the top most
191
+ const rootNode = data.completeAst.idMap.get(rootId);
192
+ const parentNode = data.completeAst.idMap.get(rootNode?.info.parent ?? -1);
193
+ if (parentNode?.type !== type_1.RType.Access) {
194
+ // Only reference indices in top most access
195
+ referenceIndices(accessedIndicesCollection, fnCall, rootId);
185
196
  }
186
197
  }
187
- return fnCall;
188
198
  }
189
199
  /**
190
200
  * Creates edges of type {@link EdgeType.Reads} to the accessed Indices and their sub-indices starting from
@@ -10,9 +10,11 @@ export interface BuiltInApplyConfiguration extends MergeableRecord {
10
10
  readonly indexOfFunction?: number;
11
11
  /** does the argument have a name that it can be given by as well? */
12
12
  readonly nameOfFunctionArgument?: string;
13
- /**
14
- * Should we unquote the function if it is given as a string?
15
- */
13
+ /** Should we unquote the function if it is given as a string? */
16
14
  readonly unquoteFunction?: boolean;
15
+ /** Should the function be resolved in the global environment? */
16
+ readonly resolveInEnvironment: 'global' | 'local';
17
+ /** Should the value of the function be resolved? */
18
+ readonly resolveValue?: boolean;
17
19
  }
18
- export declare function processApply<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, { indexOfFunction, nameOfFunctionArgument, unquoteFunction }: BuiltInApplyConfiguration): DataflowInformation;
20
+ export declare function processApply<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, { indexOfFunction, nameOfFunctionArgument, unquoteFunction, resolveInEnvironment, resolveValue }: BuiltInApplyConfiguration): DataflowInformation;
@@ -8,7 +8,8 @@ const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
8
8
  const vertex_1 = require("../../../../../graph/vertex");
9
9
  const edge_1 = require("../../../../../graph/edge");
10
10
  const identifier_1 = require("../../../../../environments/identifier");
11
- function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFunctionArgument, unquoteFunction }) {
11
+ const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
12
+ function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFunctionArgument, unquoteFunction, resolveInEnvironment, resolveValue }) {
12
13
  /* as the length is one-based and the argument filter mapping is zero-based, we do not have to subtract 1 */
13
14
  const forceArgsMask = new Array(indexOfFunction).fill(false);
14
15
  forceArgsMask.push(true);
@@ -33,8 +34,8 @@ function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFun
33
34
  logger_1.dataflowLogger.warn(`Expected symbol as argument at index ${index}, but got ${JSON.stringify(arg)} instead.`);
34
35
  return information;
35
36
  }
36
- let functionId;
37
- let functionName;
37
+ let functionId = undefined;
38
+ let functionName = undefined;
38
39
  const val = arg.value;
39
40
  if (unquoteFunction && val.type === type_1.RType.String) {
40
41
  functionId = val.info.id;
@@ -42,9 +43,17 @@ function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFun
42
43
  }
43
44
  else if (val.type === type_1.RType.Symbol) {
44
45
  functionId = val.info.id;
45
- functionName = val.content;
46
+ if (resolveValue) {
47
+ const resolved = (0, resolve_by_name_1.resolveValueOfVariable)(val.content, data.environment);
48
+ if (resolved?.length === 1 && typeof resolved[0] === 'string') {
49
+ functionName = resolved[0];
50
+ }
51
+ }
52
+ else {
53
+ functionName = val.content;
54
+ }
46
55
  }
47
- else {
56
+ if (functionName === undefined || functionId === undefined) {
48
57
  logger_1.dataflowLogger.warn(`Expected symbol or string as function argument at index ${index}, but got ${JSON.stringify(val)} instead.`);
49
58
  return information;
50
59
  }
@@ -68,8 +77,8 @@ function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFun
68
77
  id: functionId,
69
78
  name: functionName,
70
79
  args: allOtherArguments,
71
- environment: data.environment,
72
- onlyBuiltin: false,
80
+ environment: resolveInEnvironment === 'global' ? undefined : data.environment,
81
+ onlyBuiltin: resolveInEnvironment === 'global',
73
82
  cds: data.controlDependencies
74
83
  });
75
84
  for (const arg of processedArguments) {
@@ -77,6 +86,16 @@ function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFun
77
86
  information.graph.addEdge(functionId, arg.entryPoint, edge_1.EdgeType.Argument);
78
87
  }
79
88
  }
80
- return information;
89
+ if (resolveInEnvironment === 'global') {
90
+ // remove from open ingoing references
91
+ return {
92
+ ...information,
93
+ in: information.in.filter(ref => ref.nodeId !== functionId),
94
+ unknownReferences: information.unknownReferences.filter(ref => ref.nodeId !== functionId)
95
+ };
96
+ }
97
+ else {
98
+ return information;
99
+ }
81
100
  }
82
101
  //# sourceMappingURL=built-in-apply.js.map
@@ -17,8 +17,10 @@ const vertex_1 = require("../../../../../graph/vertex");
17
17
  const define_1 = require("../../../../../environments/define");
18
18
  const edge_1 = require("../../../../../graph/edge");
19
19
  const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
20
- const list_access_1 = require("../../../../../../util/list-access");
20
+ const containers_1 = require("../../../../../../util/containers");
21
21
  const config_1 = require("../../../../../../config");
22
+ const built_in_replacement_1 = require("./built-in-replacement");
23
+ const named_call_handling_1 = require("../named-call-handling");
22
24
  function toReplacementSymbol(target, prefix, superAssignment) {
23
25
  return {
24
26
  type: type_1.RType.Symbol,
@@ -45,6 +47,26 @@ function findRootAccess(node) {
45
47
  return undefined;
46
48
  }
47
49
  }
50
+ function tryReplacementPassingIndices(functionName, data, name, args, indices) {
51
+ const resolved = (0, resolve_by_name_1.resolveByName)(functionName.content, data.environment, identifier_1.ReferenceType.Function) ?? [];
52
+ // yield for unsupported pass along!
53
+ if (resolved.length !== 1 || resolved[0].type !== identifier_1.ReferenceType.BuiltInFunction) {
54
+ return (0, process_named_call_1.processAsNamedCall)(functionName, data, name, args);
55
+ }
56
+ const info = (0, built_in_replacement_1.processReplacementFunction)({
57
+ type: type_1.RType.Symbol,
58
+ info: functionName.info,
59
+ content: name,
60
+ lexeme: functionName.lexeme,
61
+ location: functionName.location,
62
+ namespace: undefined
63
+ }, (0, make_argument_1.wrapArgumentsUnnamed)(args, data.completeAst.idMap), functionName.info.id, data, {
64
+ ...(resolved[0].config ?? {}),
65
+ activeIndices: indices
66
+ });
67
+ (0, named_call_handling_1.markAsOnlyBuiltIn)(info.graph, functionName.info.id);
68
+ return info;
69
+ }
48
70
  /**
49
71
  * Processes an assignment, i.e., `<target> <- <source>`.
50
72
  * Handling it as a function call \`&lt;-\` `(<target>, <source>)`.
@@ -75,14 +97,14 @@ args, rootId, data, config) {
75
97
  }
76
98
  else if (config.canBeReplacement && type === type_1.RType.FunctionCall && named) {
77
99
  /* as replacement functions take precedence over the lhs fn-call (i.e., `names(x) <- ...` is independent from the definition of `names`), we do not have to process the call */
78
- logger_1.dataflowLogger.debug(`Assignment ${name.content} has a function call as target => replacement function ${target.lexeme}`);
100
+ logger_1.dataflowLogger.debug(`Assignment ${name.content} has a function call as target ==> replacement function ${target.lexeme}`);
79
101
  const replacement = toReplacementSymbol(target, target.functionName.content, config.superAssignment ?? false);
80
- return (0, process_named_call_1.processAsNamedCall)(replacement, data, replacement.content, [...target.arguments, source]);
102
+ return tryReplacementPassingIndices(replacement, data, replacement.content, [...target.arguments, source], config.indicesCollection);
81
103
  }
82
104
  else if (config.canBeReplacement && type === type_1.RType.Access) {
83
- logger_1.dataflowLogger.debug(`Assignment ${name.content} has an access as target => replacement function ${target.lexeme}`);
105
+ logger_1.dataflowLogger.debug(`Assignment ${name.content} has an access-type node as target ==> replacement function ${target.lexeme}`);
84
106
  const replacement = toReplacementSymbol(target, target.operator, config.superAssignment ?? false);
85
- return (0, process_named_call_1.processAsNamedCall)(replacement, data, replacement.content, [(0, make_argument_1.toUnnamedArgument)(target.accessed, data.completeAst.idMap), ...target.access, source]);
107
+ return tryReplacementPassingIndices(replacement, data, replacement.content, [(0, make_argument_1.toUnnamedArgument)(target.accessed, data.completeAst.idMap), ...target.access, source], config.indicesCollection);
86
108
  }
87
109
  else if (type === type_1.RType.Access) {
88
110
  const rootArg = findRootAccess(target);
@@ -191,16 +213,24 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
191
213
  if ((0, config_1.getConfig)().solver.pointerTracking) {
192
214
  let indicesCollection = undefined;
193
215
  if (sourceIds.length === 1) {
194
- // support for tracking indices
216
+ // support for tracking indices.
195
217
  // Indices were defined for the vertex e.g. a <- list(c = 1) or a$b <- list(c = 1)
196
218
  indicesCollection = information.graph.getVertex(sourceIds[0])?.indicesCollection;
219
+ // support assignment of container e.g. container1 <- container2
220
+ // defined indices are passed
221
+ if (!indicesCollection) {
222
+ const node = information.graph.idMap?.get(sourceIds[0]);
223
+ if (node && node.type === type_1.RType.Symbol) {
224
+ indicesCollection = (0, containers_1.resolveIndicesByName)(node.lexeme, information.environment);
225
+ }
226
+ }
197
227
  }
198
228
  // Indices defined by replacement operation e.g. $<-
199
229
  if (config?.indicesCollection !== undefined) {
200
230
  // If there were indices stored in the vertex, then a container was defined
201
231
  // and assigned to the index of another container e.g. a$b <- list(c = 1)
202
232
  if (indicesCollection) {
203
- indicesCollection = (0, list_access_1.addSubIndicesToLeafIndices)(config.indicesCollection, indicesCollection);
233
+ indicesCollection = (0, containers_1.addSubIndicesToLeafIndices)(config.indicesCollection, indicesCollection);
204
234
  }
205
235
  else {
206
236
  // No indices were defined for the vertex e.g. a$b <- 2
@@ -0,0 +1,10 @@
1
+ import { type DataflowProcessorInformation } from '../../../../../processor';
2
+ import type { DataflowInformation } from '../../../../../info';
3
+ import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
4
+ import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
5
+ import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
6
+ import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
7
+ export declare function processEvalCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
8
+ /** should this produce an explicit source function call in the graph? */
9
+ includeFunctionCall?: boolean;
10
+ }): DataflowInformation;