@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.
- package/README.md +4 -4
- package/benchmark/slicer.d.ts +49 -22
- package/benchmark/slicer.js +88 -28
- package/benchmark/stats/print.js +16 -10
- package/benchmark/stats/size-of.js +18 -1
- package/benchmark/stats/stats.d.ts +3 -0
- package/benchmark/summarizer/second-phase/process.js +8 -2
- package/cli/benchmark-app.d.ts +5 -0
- package/cli/benchmark-app.js +49 -6
- package/cli/benchmark-helper-app.d.ts +4 -0
- package/cli/benchmark-helper-app.js +20 -4
- package/cli/common/options.js +13 -4
- package/cli/repl/commands/repl-commands.js +2 -0
- package/cli/repl/commands/repl-dataflow.d.ts +2 -0
- package/cli/repl/commands/repl-dataflow.js +35 -1
- package/config.d.ts +18 -2
- package/config.js +24 -4
- package/dataflow/environments/built-in-config.d.ts +5 -2
- package/dataflow/environments/built-in-config.js +8 -2
- package/dataflow/environments/built-in.d.ts +8 -1
- package/dataflow/environments/built-in.js +8 -1
- package/dataflow/environments/clone.d.ts +5 -0
- package/dataflow/environments/clone.js +5 -0
- package/dataflow/environments/default-builtin-config.js +93 -9
- package/dataflow/environments/define.d.ts +5 -1
- package/dataflow/environments/define.js +36 -10
- package/dataflow/environments/overwrite.js +4 -0
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +24 -0
- package/dataflow/environments/resolve-by-name.js +1 -1
- package/dataflow/graph/dataflowgraph-builder.d.ts +76 -6
- package/dataflow/graph/dataflowgraph-builder.js +102 -6
- package/dataflow/graph/graph.d.ts +6 -1
- package/dataflow/graph/graph.js +24 -0
- package/dataflow/graph/vertex.d.ts +42 -2
- package/dataflow/graph/vertex.js +32 -0
- package/dataflow/internal/linker.js +3 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +55 -45
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +6 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +27 -8
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +37 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +10 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +140 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +3 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +83 -29
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +7 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +41 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +17 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +15 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +75 -0
- package/dataflow/internal/process/functions/call/common.d.ts +1 -1
- package/dataflow/internal/process/functions/call/common.js +4 -2
- package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -0
- package/dataflow/internal/process/functions/call/named-call-handling.js +9 -5
- package/dataflow/internal/process/process-named-call.d.ts +3 -0
- package/dataflow/internal/process/process-named-call.js +3 -0
- package/documentation/doc-util/doc-cfg.d.ts +11 -2
- package/documentation/doc-util/doc-cfg.js +35 -6
- package/documentation/doc-util/doc-code.js +10 -2
- package/documentation/print-capabilities-markdown.js +1 -1
- package/documentation/print-cfg-wiki.d.ts +1 -0
- package/documentation/print-cfg-wiki.js +84 -0
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-interface-wiki.js +1 -0
- package/documentation/print-query-wiki.js +2 -2
- package/package.json +2 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +13 -5
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -25
- package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -145
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +24 -0
- package/queries/catalog/dependencies-query/function-info/function-info.js +10 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.js +18 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.js +101 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.js +11 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +87 -0
- package/r-bridge/data/data.d.ts +2 -2
- package/r-bridge/data/data.js +2 -2
- package/util/arrays.d.ts +23 -0
- package/util/arrays.js +41 -0
- package/util/cfg/visitor.d.ts +1 -1
- package/util/cfg/visitor.js +2 -2
- package/util/{list-access.d.ts → containers.d.ts} +24 -4
- package/util/{list-access.js → containers.js} +42 -12
- package/util/mermaid/ast.js +12 -1
- package/util/mermaid/cfg.js +2 -2
- package/util/parallel.d.ts +2 -1
- package/util/parallel.js +11 -2
- package/util/prefix.d.ts +13 -0
- package/util/prefix.js +34 -0
- 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
|
|
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 =
|
|
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
|
|
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
|
|
166
|
+
return;
|
|
154
167
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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 \`<-\` `(<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
|
|
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 (
|
|
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
|
|
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 (
|
|
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,
|
|
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
|
|
20
|
+
return fnCall.information;
|
|
20
21
|
}
|
|
21
|
-
const
|
|
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.
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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:
|
|
54
|
+
subIndices: indicesCollection,
|
|
39
55
|
};
|
|
40
56
|
}
|
|
41
57
|
}
|
|
42
|
-
|
|
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:
|
|
74
|
+
indices: listArgs,
|
|
46
75
|
isContainer: true,
|
|
47
76
|
};
|
|
48
|
-
|
|
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;
|