@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.
- 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/cli/repl/server/compact.d.ts +2 -2
- package/cli/repl/server/compact.js +3 -3
- package/cli/repl/server/messages/message-analysis.d.ts +2 -2
- package/cli/repl/server/messages/message-analysis.js +2 -2
- package/config.d.ts +27 -2
- package/config.js +30 -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 +96 -10
- package/dataflow/environments/define.d.ts +5 -1
- package/dataflow/environments/define.js +36 -10
- package/dataflow/environments/environment.js +4 -2
- 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/extractor.d.ts +1 -1
- package/dataflow/extractor.js +8 -6
- package/dataflow/graph/dataflowgraph-builder.d.ts +76 -6
- package/dataflow/graph/dataflowgraph-builder.js +102 -6
- package/dataflow/graph/edge.js +4 -1
- package/dataflow/graph/graph.d.ts +12 -1
- package/dataflow/graph/graph.js +37 -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/argument/unpack-argument.d.ts +3 -0
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +4 -10
- 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-expression-list.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +21 -3
- 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 +20 -6
- 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/dataflow/processor.d.ts +7 -7
- package/documentation/data/server/doc-data-server-messages.js +2 -2
- 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 +4 -0
- package/documentation/print-query-wiki.js +22 -3
- package/package.json +4 -3
- package/queries/catalog/call-context-query/call-context-query-executor.js +13 -0
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +4 -0
- package/queries/catalog/call-context-query/call-context-query-format.js +1 -0
- 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/queries/catalog/location-map-query/location-map-query-executor.d.ts +1 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +38 -3
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +10 -1
- package/queries/catalog/location-map-query/location-map-query-format.js +5 -1
- package/queries/catalog/project-query/project-query-executor.d.ts +3 -0
- package/queries/catalog/project-query/project-query-executor.js +17 -0
- package/queries/catalog/project-query/project-query-format.d.ts +67 -0
- package/queries/catalog/project-query/project-query-format.js +26 -0
- package/queries/query.d.ts +60 -1
- package/queries/query.js +3 -1
- package/r-bridge/data/data.d.ts +2 -2
- package/r-bridge/data/data.js +2 -2
- package/slicing/static/fingerprint.js +8 -1
- package/slicing/static/slice-call.d.ts +1 -1
- package/slicing/static/slice-call.js +5 -16
- package/slicing/static/slicer-types.d.ts +2 -0
- package/slicing/static/static-slicer.d.ts +4 -2
- package/slicing/static/static-slicer.js +24 -18
- package/slicing/static/visiting-queue.d.ts +7 -1
- package/slicing/static/visiting-queue.js +20 -6
- 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
package/dataflow/graph/graph.js
CHANGED
|
@@ -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
|
|
54
|
+
* Distinctive identifier of index, see {@link IndexIdentifier}.
|
|
25
55
|
*/
|
|
26
|
-
readonly
|
|
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
|
*/
|
package/dataflow/graph/vertex.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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;
|