@eagleoutice/flowr 2.2.11 → 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 (97) 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/config.d.ts +18 -2
  17. package/config.js +24 -4
  18. package/dataflow/environments/built-in-config.d.ts +5 -2
  19. package/dataflow/environments/built-in-config.js +8 -2
  20. package/dataflow/environments/built-in.d.ts +8 -1
  21. package/dataflow/environments/built-in.js +8 -1
  22. package/dataflow/environments/clone.d.ts +5 -0
  23. package/dataflow/environments/clone.js +5 -0
  24. package/dataflow/environments/default-builtin-config.js +93 -9
  25. package/dataflow/environments/define.d.ts +5 -1
  26. package/dataflow/environments/define.js +36 -10
  27. package/dataflow/environments/overwrite.js +4 -0
  28. package/dataflow/environments/remove.d.ts +6 -0
  29. package/dataflow/environments/remove.js +24 -0
  30. package/dataflow/environments/resolve-by-name.js +1 -1
  31. package/dataflow/graph/dataflowgraph-builder.d.ts +76 -6
  32. package/dataflow/graph/dataflowgraph-builder.js +102 -6
  33. package/dataflow/graph/graph.d.ts +6 -1
  34. package/dataflow/graph/graph.js +24 -0
  35. package/dataflow/graph/vertex.d.ts +42 -2
  36. package/dataflow/graph/vertex.js +32 -0
  37. package/dataflow/internal/linker.js +3 -1
  38. package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -0
  39. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +55 -45
  40. package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +6 -4
  41. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +27 -8
  42. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +37 -7
  43. package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +10 -0
  44. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +140 -0
  45. package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
  46. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +3 -0
  47. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +83 -29
  48. package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +7 -0
  49. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +41 -0
  50. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +17 -5
  51. package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +15 -0
  52. package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +75 -0
  53. package/dataflow/internal/process/functions/call/common.d.ts +1 -1
  54. package/dataflow/internal/process/functions/call/common.js +4 -2
  55. package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -0
  56. package/dataflow/internal/process/functions/call/named-call-handling.js +9 -5
  57. package/dataflow/internal/process/process-named-call.d.ts +3 -0
  58. package/dataflow/internal/process/process-named-call.js +3 -0
  59. package/documentation/doc-util/doc-cfg.d.ts +11 -2
  60. package/documentation/doc-util/doc-cfg.js +35 -6
  61. package/documentation/doc-util/doc-code.js +10 -2
  62. package/documentation/print-capabilities-markdown.js +1 -1
  63. package/documentation/print-cfg-wiki.d.ts +1 -0
  64. package/documentation/print-cfg-wiki.js +84 -0
  65. package/documentation/print-core-wiki.js +2 -2
  66. package/documentation/print-interface-wiki.js +1 -0
  67. package/documentation/print-query-wiki.js +2 -2
  68. package/package.json +2 -1
  69. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
  70. package/queries/catalog/dependencies-query/dependencies-query-executor.js +13 -5
  71. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -25
  72. package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -145
  73. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +24 -0
  74. package/queries/catalog/dependencies-query/function-info/function-info.js +10 -0
  75. package/queries/catalog/dependencies-query/function-info/library-functions.d.ts +2 -0
  76. package/queries/catalog/dependencies-query/function-info/library-functions.js +18 -0
  77. package/queries/catalog/dependencies-query/function-info/read-functions.d.ts +2 -0
  78. package/queries/catalog/dependencies-query/function-info/read-functions.js +101 -0
  79. package/queries/catalog/dependencies-query/function-info/source-functions.d.ts +2 -0
  80. package/queries/catalog/dependencies-query/function-info/source-functions.js +11 -0
  81. package/queries/catalog/dependencies-query/function-info/write-functions.d.ts +2 -0
  82. package/queries/catalog/dependencies-query/function-info/write-functions.js +87 -0
  83. package/r-bridge/data/data.d.ts +2 -2
  84. package/r-bridge/data/data.js +2 -2
  85. package/util/arrays.d.ts +23 -0
  86. package/util/arrays.js +41 -0
  87. package/util/cfg/visitor.d.ts +1 -1
  88. package/util/cfg/visitor.js +2 -2
  89. package/util/{list-access.d.ts → containers.d.ts} +24 -4
  90. package/util/{list-access.js → containers.js} +42 -12
  91. package/util/mermaid/ast.js +12 -1
  92. package/util/mermaid/cfg.js +2 -2
  93. package/util/parallel.d.ts +2 -1
  94. package/util/parallel.js +11 -2
  95. package/util/prefix.d.ts +13 -0
  96. package/util/prefix.js +34 -0
  97. package/util/version.js +1 -1
@@ -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;
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processEvalCall = processEvalCall;
4
+ const info_1 = require("../../../../../info");
5
+ const config_1 = require("../../../../../../config");
6
+ const known_call_handling_1 = require("../known-call-handling");
7
+ const retriever_1 = require("../../../../../../r-bridge/retriever");
8
+ const decorate_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate");
9
+ const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
10
+ const logger_1 = require("../../../../../logger");
11
+ const log_1 = require("../../../../../../util/log");
12
+ const built_in_source_1 = require("./built-in-source");
13
+ const edge_1 = require("../../../../../graph/edge");
14
+ const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
15
+ const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
16
+ const append_1 = require("../../../../../environments/append");
17
+ const assert_1 = require("../../../../../../util/assert");
18
+ const arrays_1 = require("../../../../../../util/arrays");
19
+ function processEvalCall(name, args, rootId, data, config) {
20
+ if (args.length !== 1 || args[0] === r_function_call_1.EmptyArgument || !args[0].value) {
21
+ logger_1.dataflowLogger.warn(`Expected exactly one argument for eval currently, but got ${args.length} instead, skipping`);
22
+ return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information;
23
+ }
24
+ const information = config.includeFunctionCall ?
25
+ (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: [true] }).information
26
+ : (0, info_1.initializeCleanDataflowInformation)(rootId, data);
27
+ const evalArgument = args[0];
28
+ if (config.includeFunctionCall) {
29
+ information.graph.addEdge(rootId, args[0].value.info.id, edge_1.EdgeType.Returns);
30
+ }
31
+ if (!(0, config_1.getConfig)().solver.evalStrings) {
32
+ (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping eval call ${JSON.stringify(evalArgument)} (disabled in config file)`);
33
+ information.graph.markIdForUnknownSideEffects(rootId);
34
+ return information;
35
+ }
36
+ const code = resolveEvalToCode(evalArgument.value, data.environment, data.completeAst.idMap);
37
+ if (code) {
38
+ const idGenerator = (0, decorate_1.sourcedDeterministicCountingIdGenerator)(name.lexeme + '::' + rootId, name.location);
39
+ data = {
40
+ ...data,
41
+ controlDependencies: [...(data.controlDependencies ?? []), { id: rootId, when: true }]
42
+ };
43
+ const originalInfo = { ...information };
44
+ const result = [];
45
+ for (const c of code) {
46
+ const codeRequest = (0, retriever_1.requestFromInput)(c);
47
+ const r = (0, built_in_source_1.sourceRequest)(rootId, codeRequest, data, originalInfo, idGenerator);
48
+ result.push(r);
49
+ // add a returns edge from the eval to the result
50
+ for (const e of r.exitPoints) {
51
+ information.graph.addEdge(rootId, e, edge_1.EdgeType.Returns);
52
+ }
53
+ }
54
+ return {
55
+ graph: result.reduce((acc, r) => acc.mergeWith(r.graph), information.graph),
56
+ environment: result.reduce((acc, r) => (0, append_1.appendEnvironment)(acc, r.environment), information.environment),
57
+ entryPoint: rootId,
58
+ out: [...information.out, ...result.flatMap(r => r.out)],
59
+ in: [...information.in, ...result.flatMap(r => r.in)],
60
+ unknownReferences: [...information.unknownReferences, ...result.flatMap(r => r.unknownReferences)],
61
+ exitPoints: [...information.exitPoints, ...result.flatMap(r => r.exitPoints)],
62
+ };
63
+ }
64
+ (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(args)} for eval is currently not supported, skipping`);
65
+ information.graph.markIdForUnknownSideEffects(rootId);
66
+ return information;
67
+ }
68
+ function resolveEvalToCode(evalArgument, env, idMap) {
69
+ const val = evalArgument;
70
+ if (val.type === type_1.RType.FunctionCall && val.named && val.functionName.content === 'parse') {
71
+ const arg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'text');
72
+ const nArg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'n');
73
+ if (nArg !== undefined || arg === undefined || arg === r_function_call_1.EmptyArgument) {
74
+ return undefined;
75
+ }
76
+ if (arg.value?.type === type_1.RType.String) {
77
+ return [arg.value.content.str];
78
+ }
79
+ else if (arg.value?.type === type_1.RType.Symbol) {
80
+ const resolve = (0, resolve_by_name_1.resolveValueOfVariable)(arg.value.content, env, idMap);
81
+ if (resolve && resolve.every(r => typeof r === 'object' && r !== null && 'str' in r)) {
82
+ return resolve.map(r => r.str);
83
+ }
84
+ }
85
+ else if (arg.value?.type === type_1.RType.FunctionCall && arg.value.named && ['paste', 'paste0'].includes(arg.value.functionName.content)) {
86
+ return handlePaste(arg.value.arguments, env, idMap, arg.value.functionName.content === 'paste' ? [' '] : ['']);
87
+ }
88
+ return undefined;
89
+ }
90
+ else if (val.type === type_1.RType.Symbol) {
91
+ // const resolved = resolveValueOfVariable(val.content, env);
92
+ // see https://github.com/flowr-analysis/flowr/pull/1467
93
+ return undefined;
94
+ }
95
+ else {
96
+ return undefined;
97
+ }
98
+ }
99
+ function getAsString(val, env, idMap) {
100
+ if (!val) {
101
+ return undefined;
102
+ }
103
+ if (val.type === type_1.RType.String) {
104
+ return [val.content.str];
105
+ }
106
+ else if (val.type === type_1.RType.Symbol) {
107
+ const resolved = (0, resolve_by_name_1.resolveValueOfVariable)(val.content, env, idMap);
108
+ if (resolved && resolved.every(r => typeof r === 'object' && r !== null && 'str' in r)) {
109
+ return resolved.map(r => r.str);
110
+ }
111
+ }
112
+ return undefined;
113
+ }
114
+ function handlePaste(args, env, idMap, sepDefault) {
115
+ const sepArg = args.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'sep');
116
+ if (sepArg) {
117
+ const res = sepArg !== r_function_call_1.EmptyArgument && sepArg.value ? getAsString(sepArg.value, env, idMap) : undefined;
118
+ if (!res) {
119
+ // sep not resolvable clearly / unknown
120
+ return undefined;
121
+ }
122
+ sepDefault = res;
123
+ }
124
+ const allArgs = args
125
+ .filter(v => v !== r_function_call_1.EmptyArgument && v.name?.content !== 'sep' && v.value)
126
+ .map(v => getAsString(v.value, env, idMap));
127
+ if (allArgs.some(assert_1.isUndefined)) {
128
+ return undefined;
129
+ }
130
+ // return all cartesian products using the separator
131
+ const result = [];
132
+ const cartesianProducts = (0, arrays_1.cartesianProduct)(...allArgs);
133
+ for (const sep of sepDefault) {
134
+ for (const c of cartesianProducts) {
135
+ result.push(c.join(sep));
136
+ }
137
+ }
138
+ return result;
139
+ }
140
+ //# sourceMappingURL=built-in-eval.js.map
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.processList = processList;
4
4
  const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
5
5
  const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
6
- const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
7
6
  const known_call_handling_1 = require("../known-call-handling");
8
7
  const config_1 = require("../../../../../../config");
8
+ const containers_1 = require("../../../../../../util/containers");
9
9
  /**
10
10
  * Process a list call.
11
11
  *
@@ -15,36 +15,70 @@ const config_1 = require("../../../../../../config");
15
15
  * ```
16
16
  */
17
17
  function processList(name, args, rootId, data) {
18
+ const fnCall = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data });
18
19
  if (!(0, config_1.getConfig)().solver.pointerTracking) {
19
- return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information;
20
+ return fnCall.information;
20
21
  }
21
- const namedArguments = [];
22
+ const listArgs = [];
22
23
  for (const arg of args) {
23
24
  // Skip non named arguments
24
- if (arg === r_function_call_1.EmptyArgument || arg.type !== type_1.RType.Argument || arg.name === undefined) {
25
+ if (arg === r_function_call_1.EmptyArgument || arg.type !== type_1.RType.Argument || arg.value === undefined) {
25
26
  continue;
26
27
  }
27
- let newIndex = {
28
- lexeme: arg.name.content,
29
- nodeId: arg.info.id,
30
- };
31
- // Check whether argument value is non-primitive
32
- if (arg.value?.type === type_1.RType.Symbol) {
33
- const defs = (0, resolve_by_name_1.resolveByName)(arg.value.lexeme, data.environment);
34
- const indices = defs?.flatMap(index => index.indicesCollection ?? []);
35
- if (indices) {
28
+ let newIndex;
29
+ if (arg.name) {
30
+ // Named argument
31
+ newIndex = {
32
+ identifier: {
33
+ index: arg.info.index,
34
+ lexeme: arg.name.content
35
+ },
36
+ nodeId: arg.info.id,
37
+ };
38
+ }
39
+ else {
40
+ // Unnamed argument
41
+ newIndex = {
42
+ identifier: {
43
+ index: arg.info.index,
44
+ },
45
+ nodeId: arg.value.info.id,
46
+ };
47
+ }
48
+ // Check whether argument value can be resolved
49
+ if (arg.value.type === type_1.RType.Symbol) {
50
+ const indicesCollection = (0, containers_1.resolveIndicesByName)(arg.value.lexeme, data.environment);
51
+ if (indicesCollection) {
36
52
  newIndex = {
37
53
  ...newIndex,
38
- subIndices: indices,
54
+ subIndices: indicesCollection,
39
55
  };
40
56
  }
41
57
  }
42
- namedArguments.push(newIndex);
58
+ else {
59
+ // Check whether argument is nested container
60
+ const indicesCollection = fnCall.information.graph.getVertex(arg.value.info.id)?.indicesCollection;
61
+ if (indicesCollection) {
62
+ newIndex = {
63
+ ...newIndex,
64
+ subIndices: indicesCollection,
65
+ };
66
+ }
67
+ }
68
+ listArgs.push(newIndex);
69
+ }
70
+ if ((0, config_1.isOverPointerAnalysisThreshold)(listArgs.length)) {
71
+ return fnCall.information;
43
72
  }
44
73
  const indices = {
45
- indices: namedArguments,
74
+ indices: listArgs,
46
75
  isContainer: true,
47
76
  };
48
- return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }, [indices]).information;
77
+ // Add resolved indices to vertex
78
+ const vertex = fnCall.information.graph.getVertex(rootId);
79
+ if (vertex) {
80
+ vertex.indicesCollection = [indices];
81
+ }
82
+ return fnCall.information;
49
83
  }
50
84
  //# sourceMappingURL=built-in-list.js.map
@@ -5,9 +5,12 @@ import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/
5
5
  import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
6
6
  import { type RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
7
7
  import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
8
+ import type { ContainerIndicesCollection } from '../../../../../graph/vertex';
8
9
  export declare function processReplacementFunction<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>,
9
10
  /** The last one has to be the value */
10
11
  args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
11
12
  makeMaybe?: boolean;
12
13
  assignmentOperator?: '<-' | '<<-';
14
+ readIndices?: boolean;
15
+ activeIndices?: ContainerIndicesCollection;
13
16
  } & ForceArguments): DataflowInformation;