@eagleoutice/flowr 2.1.7 → 2.1.9
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 +2 -1
- package/abstract-interpretation/normalized-ast-fold.d.ts +124 -0
- package/abstract-interpretation/normalized-ast-fold.js +178 -0
- package/benchmark/summarizer/first-phase/process.js +6 -5
- package/cli/repl/commands/repl-dataflow.js +5 -2
- package/cli/repl/commands/repl-normalize.js +5 -2
- package/cli/repl/commands/repl-query.js +2 -2
- package/cli/repl/server/messages/message-query.js +1 -1
- package/cli/slicer-app.js +1 -1
- package/core/steps/pipeline/pipeline.d.ts +63 -0
- package/dataflow/environments/default-builtin-config.js +45 -6
- package/dataflow/environments/environment.d.ts +46 -8
- package/dataflow/environments/environment.js +24 -1
- package/dataflow/environments/identifier.d.ts +49 -7
- package/dataflow/environments/identifier.js +11 -2
- package/dataflow/environments/resolve-by-name.d.ts +5 -0
- package/dataflow/environments/resolve-by-name.js +14 -0
- package/dataflow/extractor.js +5 -4
- package/dataflow/graph/dataflowgraph-builder.d.ts +6 -0
- package/dataflow/graph/dataflowgraph-builder.js +8 -0
- package/dataflow/graph/edge.d.ts +10 -4
- package/dataflow/graph/edge.js +12 -5
- package/dataflow/graph/graph.d.ts +41 -3
- package/dataflow/graph/graph.js +39 -34
- package/dataflow/graph/vertex.d.ts +66 -7
- package/dataflow/graph/vertex.js +15 -0
- package/dataflow/info.d.ts +79 -11
- package/dataflow/info.js +20 -0
- package/dataflow/internal/linker.d.ts +4 -2
- package/dataflow/internal/linker.js +12 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +2 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +16 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +83 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +17 -7
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/documentation/doc-util/doc-dfg.d.ts +2 -2
- package/documentation/doc-util/doc-dfg.js +11 -16
- package/documentation/doc-util/doc-normalized-ast.js +1 -1
- package/documentation/doc-util/doc-types.d.ts +1 -1
- package/documentation/doc-util/doc-types.js +21 -0
- package/documentation/print-capabilities-markdown.js +1 -1
- package/documentation/print-dataflow-graph-wiki.js +44 -7
- package/documentation/print-linting-and-testing-wiki.js +60 -26
- package/documentation/print-normalized-ast-wiki.js +107 -5
- package/documentation/print-query-wiki.js +8 -1
- package/package.json +17 -3
- package/queries/catalog/call-context-query/call-context-query-executor.js +23 -2
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +29 -2
- package/queries/catalog/call-context-query/call-context-query-format.js +7 -1
- package/queries/catalog/call-context-query/cascade-action.d.ts +8 -0
- package/queries/catalog/call-context-query/cascade-action.js +13 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +11 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +41 -4
- package/queries/catalog/dependencies-query/dependencies-query-format.js +4 -0
- package/queries/query.d.ts +4 -4
- package/queries/query.js +17 -5
- package/r-bridge/lang-4.x/ast/model/model.d.ts +3 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +5 -1
- package/r-bridge/lang-4.x/ast/model/processing/node-id.d.ts +6 -1
- package/r-bridge/lang-4.x/ast/model/processing/node-id.js +6 -1
- package/r-bridge/lang-4.x/ast/model/processing/visitor.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/model/processing/visitor.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/json/format.js +2 -2
- package/reconstruct/reconstruct.js +1 -1
- package/slicing/static/slice-call.d.ts +7 -2
- package/slicing/static/slice-call.js +33 -44
- package/slicing/static/static-slicer.d.ts +5 -1
- package/slicing/static/static-slicer.js +22 -8
- package/slicing/static/visiting-queue.d.ts +4 -4
- package/slicing/static/visiting-queue.js +5 -3
- package/statistics/output/print-stats.js +2 -1
- package/statistics/summarizer/post-process/histogram.js +2 -1
- package/statistics/summarizer/post-process/post-process-output.js +2 -1
- package/statistics/summarizer/second-phase/process.js +3 -3
- package/util/arrays.d.ts +1 -1
- package/util/arrays.js +3 -3
- package/util/assert.d.ts +1 -1
- package/util/assert.js +3 -2
- package/util/cfg/cfg.js +4 -2
- package/util/mermaid/cfg.js +1 -1
- package/util/summarizer.js +2 -2
- package/util/version.js +1 -1
|
@@ -7,19 +7,22 @@
|
|
|
7
7
|
import type { Identifier, IdentifierDefinition, IdentifierReference } from './identifier';
|
|
8
8
|
import type { DataflowGraph } from '../graph/graph';
|
|
9
9
|
import type { ControlDependency } from '../info';
|
|
10
|
+
/**
|
|
11
|
+
* Marks the reference as maybe (i.e., as controlled by a set of {@link IdentifierReference#controlDependencies|control dependencies}).
|
|
12
|
+
*/
|
|
10
13
|
export declare function makeReferenceMaybe(ref: IdentifierReference, graph: DataflowGraph, environments: REnvironmentInformation, includeDefs: boolean, defaultCd?: ControlDependency | undefined): IdentifierReference;
|
|
11
14
|
export declare function makeAllMaybe(references: readonly IdentifierReference[] | undefined, graph: DataflowGraph, environments: REnvironmentInformation, includeDefs: boolean, defaultCd?: ControlDependency | undefined): IdentifierReference[];
|
|
12
15
|
export type EnvironmentMemory = Map<Identifier, IdentifierDefinition[]>;
|
|
16
|
+
/** A single entry/scope within an {@link REnvironmentInformation} */
|
|
13
17
|
export interface IEnvironment {
|
|
14
|
-
/**
|
|
18
|
+
/** Unique and internally generated identifier -- will not be used for comparison but helps with debugging for tracking identities */
|
|
15
19
|
readonly id: number;
|
|
16
20
|
/** Lexical parent of the environment, if any (can be manipulated by R code) */
|
|
17
21
|
parent: IEnvironment;
|
|
18
|
-
/**
|
|
19
|
-
* Maps to exactly one definition of an identifier if the source is known, otherwise to a list of all possible definitions
|
|
20
|
-
*/
|
|
22
|
+
/** Maps to exactly one definition of an identifier if the source is known, otherwise to a list of all possible definitions */
|
|
21
23
|
memory: EnvironmentMemory;
|
|
22
24
|
}
|
|
25
|
+
/** @see REnvironmentInformation */
|
|
23
26
|
export declare class Environment implements IEnvironment {
|
|
24
27
|
readonly id: number;
|
|
25
28
|
parent: IEnvironment;
|
|
@@ -27,11 +30,26 @@ export declare class Environment implements IEnvironment {
|
|
|
27
30
|
constructor(parent: IEnvironment);
|
|
28
31
|
}
|
|
29
32
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
+
* An environment describes a ({@link IEnvironment#parent|scoped}) mapping of names to their definitions ({@link EnvironmentMemory}).
|
|
34
|
+
*
|
|
35
|
+
* First, yes, R stores its environments differently, potentially even with another differentiation between
|
|
36
|
+
* the `baseenv`, the `emptyenv`, and other default environments (see https://adv-r.hadley.nz/environments.html).
|
|
37
|
+
* Yet, during the dataflow analysis, we want sometimes to know more (static {@link IdentifierDefinition|reference information})
|
|
38
|
+
* and sometimes know less (to be honest, we do not want that,
|
|
33
39
|
* but statically determining all attached environments is theoretically impossible --- consider attachments by user input).
|
|
34
|
-
*
|
|
40
|
+
*
|
|
41
|
+
* One important environment is the {@link BuiltInEnvironment} which contains the default definitions for R's built-in functions and constants.
|
|
42
|
+
* Please use {@link initializeCleanEnvironments} to initialize the environments (which includes the built-ins).
|
|
43
|
+
* During serialization, you may want to rely on the {@link builtInEnvJsonReplacer} to avoid the huge built-in environment.
|
|
44
|
+
*
|
|
45
|
+
*
|
|
46
|
+
* @see {@link define} - to define a new {@link IdentifierDefinition|identifier definition} within an environment
|
|
47
|
+
* @see {@link resolveByName} - to resolve an {@link Identifier|identifier/name} to its {@link IdentifierDefinition|definitions} within an environment
|
|
48
|
+
* @see {@link makeReferenceMaybe} - to attach control dependencies to a reference
|
|
49
|
+
* @see {@link pushLocalEnvironment} - to create a new local scope
|
|
50
|
+
* @see {@link popLocalEnvironment} - to remove the current local scope
|
|
51
|
+
* @see {@link appendEnvironment} - to append an environment to the current one
|
|
52
|
+
* @see {@link overwriteEnvironment} - to overwrite the definitions in the current environment with those of another one
|
|
35
53
|
*/
|
|
36
54
|
export interface REnvironmentInformation {
|
|
37
55
|
/** The currently active environment (the stack is represented by the currently active {@link IEnvironment#parent}). Environments are maintained within the dataflow graph. */
|
|
@@ -39,7 +57,27 @@ export interface REnvironmentInformation {
|
|
|
39
57
|
/** nesting level of the environment, will be `0` for the global/root environment */
|
|
40
58
|
readonly level: number;
|
|
41
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* The built-in {@link REnvironmentInformation|environment} is the root of all environments.
|
|
62
|
+
*
|
|
63
|
+
* For its default content (when not overwritten by a flowR config),
|
|
64
|
+
* see the {@link DefaultBuiltinConfig}.
|
|
65
|
+
*/
|
|
42
66
|
export declare const BuiltInEnvironment: Environment;
|
|
67
|
+
/**
|
|
68
|
+
* The twin of the {@link BuiltInEnvironment} but with less built ins defined for
|
|
69
|
+
* cases in which we want some commonly overwritten variables to remain open.
|
|
70
|
+
* If you do not know if you need the empty environment, you do not need the empty environment (right now).
|
|
71
|
+
*
|
|
72
|
+
* @see {@link BuiltInEnvironment}
|
|
73
|
+
*/
|
|
43
74
|
export declare const EmptyBuiltInEnvironment: IEnvironment;
|
|
75
|
+
/**
|
|
76
|
+
* Initialize a new {@link REnvironmentInformation|environment} with the built-ins.
|
|
77
|
+
* See {@link EmptyBuiltInEnvironment} for the case `fullBuiltIns = false`.
|
|
78
|
+
*/
|
|
44
79
|
export declare function initializeCleanEnvironments(fullBuiltIns?: boolean): REnvironmentInformation;
|
|
80
|
+
/**
|
|
81
|
+
* Helps to serialize an environment, but replaces the built-in environment with a placeholder.
|
|
82
|
+
*/
|
|
45
83
|
export declare function builtInEnvJsonReplacer(k: unknown, v: unknown): unknown;
|
|
@@ -9,6 +9,9 @@ const identifier_1 = require("./identifier");
|
|
|
9
9
|
const built_in_1 = require("./built-in");
|
|
10
10
|
const resolve_by_name_1 = require("./resolve-by-name");
|
|
11
11
|
const json_1 = require("../../util/json");
|
|
12
|
+
/**
|
|
13
|
+
* Marks the reference as maybe (i.e., as controlled by a set of {@link IdentifierReference#controlDependencies|control dependencies}).
|
|
14
|
+
*/
|
|
12
15
|
function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = undefined) {
|
|
13
16
|
const node = graph.get(ref.nodeId, true);
|
|
14
17
|
if (includeDefs) {
|
|
@@ -42,6 +45,7 @@ function makeAllMaybe(references, graph, environments, includeDefs, defaultCd =
|
|
|
42
45
|
return references.map(ref => makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd));
|
|
43
46
|
}
|
|
44
47
|
let environmentIdCounter = 0;
|
|
48
|
+
/** @see REnvironmentInformation */
|
|
45
49
|
class Environment {
|
|
46
50
|
id = environmentIdCounter++;
|
|
47
51
|
parent;
|
|
@@ -52,14 +56,30 @@ class Environment {
|
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
exports.Environment = Environment;
|
|
55
|
-
|
|
59
|
+
/**
|
|
60
|
+
* The built-in {@link REnvironmentInformation|environment} is the root of all environments.
|
|
61
|
+
*
|
|
62
|
+
* For its default content (when not overwritten by a flowR config),
|
|
63
|
+
* see the {@link DefaultBuiltinConfig}.
|
|
64
|
+
*/
|
|
56
65
|
exports.BuiltInEnvironment = new Environment(undefined);
|
|
57
66
|
exports.BuiltInEnvironment.memory = undefined;
|
|
67
|
+
/**
|
|
68
|
+
* The twin of the {@link BuiltInEnvironment} but with less built ins defined for
|
|
69
|
+
* cases in which we want some commonly overwritten variables to remain open.
|
|
70
|
+
* If you do not know if you need the empty environment, you do not need the empty environment (right now).
|
|
71
|
+
*
|
|
72
|
+
* @see {@link BuiltInEnvironment}
|
|
73
|
+
*/
|
|
58
74
|
exports.EmptyBuiltInEnvironment = {
|
|
59
75
|
id: exports.BuiltInEnvironment.id,
|
|
60
76
|
memory: undefined,
|
|
61
77
|
parent: undefined
|
|
62
78
|
};
|
|
79
|
+
/**
|
|
80
|
+
* Initialize a new {@link REnvironmentInformation|environment} with the built-ins.
|
|
81
|
+
* See {@link EmptyBuiltInEnvironment} for the case `fullBuiltIns = false`.
|
|
82
|
+
*/
|
|
63
83
|
function initializeCleanEnvironments(fullBuiltIns = true) {
|
|
64
84
|
exports.BuiltInEnvironment.memory ??= built_in_1.BuiltInMemory;
|
|
65
85
|
exports.EmptyBuiltInEnvironment.memory ??= built_in_1.EmptyBuiltInMemory;
|
|
@@ -68,6 +88,9 @@ function initializeCleanEnvironments(fullBuiltIns = true) {
|
|
|
68
88
|
level: 0
|
|
69
89
|
};
|
|
70
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Helps to serialize an environment, but replaces the built-in environment with a placeholder.
|
|
93
|
+
*/
|
|
71
94
|
function builtInEnvJsonReplacer(k, v) {
|
|
72
95
|
if (v === exports.BuiltInEnvironment) {
|
|
73
96
|
return '<BuiltInEnvironment>';
|
|
@@ -5,9 +5,17 @@ export type Identifier = string & {
|
|
|
5
5
|
__brand?: 'identifier';
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
|
-
* Each reference
|
|
9
|
-
* However, when checking we may want to allow for one of several types,
|
|
8
|
+
* Each reference has exactly one reference type, stored as the respective number.
|
|
9
|
+
* However, when checking, we may want to allow for one of several types,
|
|
10
10
|
* allowing the combination of the respective bitmasks.
|
|
11
|
+
*
|
|
12
|
+
* Having reference types is important as R separates a variable definition from
|
|
13
|
+
* a function when resolving an {@link Identifier|identifier}.
|
|
14
|
+
* In `c <- 3; print(c(1, 2))` the call to `c` works normally (as the vector constructor),
|
|
15
|
+
* while writing `c <- function(...) ..1` overshadows the built-in and causes `print` to only output the first element.
|
|
16
|
+
*
|
|
17
|
+
* @see {@link isReferenceType} - for checking if a (potentially joint) reference type contains a certain type
|
|
18
|
+
* @see {@link ReferenceTypeReverseMapping} - for debugging
|
|
11
19
|
*/
|
|
12
20
|
export declare enum ReferenceType {
|
|
13
21
|
/** The identifier type is unknown */
|
|
@@ -27,19 +35,38 @@ export declare enum ReferenceType {
|
|
|
27
35
|
/** The identifier is defined by a built-in function */
|
|
28
36
|
BuiltInFunction = 128
|
|
29
37
|
}
|
|
38
|
+
/** Reverse mapping of the reference types so you can get the name from the bitmask (useful for debugging) */
|
|
30
39
|
export declare const ReferenceTypeReverseMapping: Map<ReferenceType, string>;
|
|
31
40
|
/**
|
|
32
41
|
* Check if the reference types have an overlapping type!
|
|
33
42
|
*/
|
|
34
43
|
export declare function isReferenceType(t: ReferenceType, target: ReferenceType): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Describes all types of reference (definitions) that can appear within a graph (i.e., that are not built-in like the
|
|
46
|
+
* default definition for the assignment operator `<-`).
|
|
47
|
+
*
|
|
48
|
+
* @see {@link InGraphIdentifierDefinition} - for the definition of an identifier within the graph
|
|
49
|
+
*/
|
|
35
50
|
export type InGraphReferenceType = Exclude<ReferenceType, ReferenceType.BuiltInConstant | ReferenceType.BuiltInFunction>;
|
|
36
51
|
/**
|
|
37
|
-
*
|
|
38
|
-
* Without any surrounding
|
|
39
|
-
* Similarly, `b` will create a reference
|
|
52
|
+
* An identifier reference points to a variable like `a` in `b <- a`.
|
|
53
|
+
* Without any surrounding code, `a` will produce the identifier reference `a`.
|
|
54
|
+
* Similarly, `b` will create a reference (although it will be an {@link IdentifierDefinition|identifier definition}
|
|
55
|
+
* which adds even more information).
|
|
56
|
+
*
|
|
57
|
+
* In general,
|
|
58
|
+
* references are merely pointers (with meta-information) to a vertex in the {@link DataflowGraph|dataflow graph}.
|
|
59
|
+
* In the context of the extractor, for example,
|
|
60
|
+
* they indicate the references that are currently (during the analysis at this given node)
|
|
61
|
+
* {@link DataflowInformation#in|read (`in`)}, {@link DataflowInformation#out|written (`out`)},
|
|
62
|
+
* or {@link DataflowInformation#unknownReferences|unknown (`unknownReferences`)}.
|
|
63
|
+
*
|
|
64
|
+
* @see {@link InGraphIdentifierDefinition}
|
|
40
65
|
*/
|
|
41
66
|
export interface IdentifierReference {
|
|
42
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* The id of the node which represents the reference in the {@link NormalizedAst|normalized AST} and the {@link DataflowGraph|dataflow graph}.
|
|
69
|
+
*/
|
|
43
70
|
readonly nodeId: NodeId;
|
|
44
71
|
/** Name the reference is identified by (e.g., the name of the variable), undefined if the reference is "artificial" (e.g., anonymous) */
|
|
45
72
|
readonly name: Identifier | undefined;
|
|
@@ -51,13 +78,28 @@ export interface IdentifierReference {
|
|
|
51
78
|
*/
|
|
52
79
|
controlDependencies: ControlDependency[] | undefined;
|
|
53
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* The definition of an {@link Identifier|identifier} within the {@link DataflowGraph|graph}.
|
|
83
|
+
* This extends on the {@link IdentifierReference}
|
|
84
|
+
* by adding the {@link NodeId} of the definition
|
|
85
|
+
* (and using `type` to mark the object type).
|
|
86
|
+
*
|
|
87
|
+
* Within a code snippet like `a <- 3`, the symbol processor will first create an
|
|
88
|
+
* {@link IdentifierReference|identifier reference} for `a` to reference the use
|
|
89
|
+
* and then promote it to an {@link InGraphIdentifierDefinition|identifier definition}.
|
|
90
|
+
*
|
|
91
|
+
* @see {@link IdentifierReference}
|
|
92
|
+
*/
|
|
54
93
|
interface InGraphIdentifierDefinition extends IdentifierReference {
|
|
55
94
|
readonly type: InGraphReferenceType;
|
|
56
95
|
/** The assignment (or whatever, like `assign` function call) node which ultimately defined this identifier */
|
|
57
96
|
readonly definedAt: NodeId;
|
|
58
97
|
}
|
|
59
98
|
/**
|
|
60
|
-
* Stores the definition of an identifier within an {@link IEnvironment}
|
|
99
|
+
* Stores the definition of an identifier within an {@link IEnvironment}.
|
|
100
|
+
*
|
|
101
|
+
* {@link BuiltInIdentifierDefinition} and {@link BuiltInIdentifierConstant} are used for built-in functions and constants only,
|
|
102
|
+
* so the most important one for your day-to-day R script is the {@link InGraphIdentifierDefinition}.
|
|
61
103
|
*/
|
|
62
104
|
export type IdentifierDefinition = InGraphIdentifierDefinition | BuiltInIdentifierDefinition | BuiltInIdentifierConstant;
|
|
63
105
|
export {};
|
|
@@ -3,9 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ReferenceTypeReverseMapping = exports.ReferenceType = void 0;
|
|
4
4
|
exports.isReferenceType = isReferenceType;
|
|
5
5
|
/**
|
|
6
|
-
* Each reference
|
|
7
|
-
* However, when checking we may want to allow for one of several types,
|
|
6
|
+
* Each reference has exactly one reference type, stored as the respective number.
|
|
7
|
+
* However, when checking, we may want to allow for one of several types,
|
|
8
8
|
* allowing the combination of the respective bitmasks.
|
|
9
|
+
*
|
|
10
|
+
* Having reference types is important as R separates a variable definition from
|
|
11
|
+
* a function when resolving an {@link Identifier|identifier}.
|
|
12
|
+
* In `c <- 3; print(c(1, 2))` the call to `c` works normally (as the vector constructor),
|
|
13
|
+
* while writing `c <- function(...) ..1` overshadows the built-in and causes `print` to only output the first element.
|
|
14
|
+
*
|
|
15
|
+
* @see {@link isReferenceType} - for checking if a (potentially joint) reference type contains a certain type
|
|
16
|
+
* @see {@link ReferenceTypeReverseMapping} - for debugging
|
|
9
17
|
*/
|
|
10
18
|
var ReferenceType;
|
|
11
19
|
(function (ReferenceType) {
|
|
@@ -26,6 +34,7 @@ var ReferenceType;
|
|
|
26
34
|
/** The identifier is defined by a built-in function */
|
|
27
35
|
ReferenceType[ReferenceType["BuiltInFunction"] = 128] = "BuiltInFunction";
|
|
28
36
|
})(ReferenceType || (exports.ReferenceType = ReferenceType = {}));
|
|
37
|
+
/** Reverse mapping of the reference types so you can get the name from the bitmask (useful for debugging) */
|
|
29
38
|
exports.ReferenceTypeReverseMapping = new Map(Object.entries(ReferenceType).map(([k, v]) => [v, k]));
|
|
30
39
|
/**
|
|
31
40
|
* Check if the reference types have an overlapping type!
|
|
@@ -13,3 +13,8 @@ import { ReferenceType } from './identifier';
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function resolveByName(name: Identifier, environment: REnvironmentInformation, target?: ReferenceType): IdentifierDefinition[] | undefined;
|
|
15
15
|
export declare function resolvesToBuiltInConstant(name: Identifier | undefined, environment: REnvironmentInformation, wantedValue: unknown): Ternary;
|
|
16
|
+
export interface ResolveResult<T = unknown> {
|
|
17
|
+
value: T;
|
|
18
|
+
from: ReferenceType;
|
|
19
|
+
}
|
|
20
|
+
export declare function resolveToConstants(name: Identifier | undefined, environment: REnvironmentInformation): ResolveResult[] | undefined;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveByName = resolveByName;
|
|
4
4
|
exports.resolvesToBuiltInConstant = resolvesToBuiltInConstant;
|
|
5
|
+
exports.resolveToConstants = resolveToConstants;
|
|
5
6
|
const environment_1 = require("./environment");
|
|
6
7
|
const identifier_1 = require("./identifier");
|
|
7
8
|
const info_1 = require("../info");
|
|
@@ -80,4 +81,17 @@ function resolvesToBuiltInConstant(name, environment, wantedValue) {
|
|
|
80
81
|
return some ? 1 /* Ternary.Maybe */ : 2 /* Ternary.Never */;
|
|
81
82
|
}
|
|
82
83
|
}
|
|
84
|
+
function resolveToConstants(name, environment) {
|
|
85
|
+
if (name === undefined) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
const definitions = resolveByName(name, environment, identifier_1.ReferenceType.Constant);
|
|
89
|
+
if (definitions === undefined) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
return definitions.map(def => ({
|
|
93
|
+
value: def.value,
|
|
94
|
+
from: def.type
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
83
97
|
//# sourceMappingURL=resolve-by-name.js.map
|
package/dataflow/extractor.js
CHANGED
|
@@ -20,6 +20,7 @@ const built_in_source_1 = require("./internal/process/functions/call/built-in/bu
|
|
|
20
20
|
const cfg_1 = require("../util/cfg/cfg");
|
|
21
21
|
const edge_1 = require("./graph/edge");
|
|
22
22
|
const identify_link_to_last_call_relation_1 = require("../queries/catalog/call-context-query/identify-link-to-last-call-relation");
|
|
23
|
+
const built_in_function_definition_1 = require("./internal/process/functions/call/built-in/built-in-function-definition");
|
|
23
24
|
exports.processors = {
|
|
24
25
|
[type_1.RType.Number]: process_value_1.processValue,
|
|
25
26
|
[type_1.RType.String]: process_value_1.processValue,
|
|
@@ -56,11 +57,9 @@ function resolveLinkToSideEffects(ast, graph) {
|
|
|
56
57
|
if (typeof s !== 'object') {
|
|
57
58
|
continue;
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
-
cfg = (0, cfg_1.extractCFG)(ast).graph;
|
|
61
|
-
}
|
|
60
|
+
cfg ??= (0, cfg_1.extractCFG)(ast).graph;
|
|
62
61
|
/* this has to change whenever we add a new link to relations because we currently offer no abstraction for the type */
|
|
63
|
-
const potentials = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(s.id, cfg, graph, s.linkTo
|
|
62
|
+
const potentials = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(s.id, cfg, graph, s.linkTo);
|
|
64
63
|
for (const pot of potentials) {
|
|
65
64
|
graph.addEdge(s.id, pot, edge_1.EdgeType.Reads);
|
|
66
65
|
}
|
|
@@ -92,6 +91,8 @@ function produceDataFlowGraph(request, ast) {
|
|
|
92
91
|
df = (0, built_in_source_1.standaloneSourceFile)(request[i], dfData, `root-${i}`, df);
|
|
93
92
|
}
|
|
94
93
|
}
|
|
94
|
+
// finally, resolve linkages
|
|
95
|
+
(0, built_in_function_definition_1.updateNestedFunctionCalls)(df.graph, df.environment);
|
|
95
96
|
resolveLinkToSideEffects(ast, df.graph);
|
|
96
97
|
return df;
|
|
97
98
|
}
|
|
@@ -114,6 +114,12 @@ export declare class DataflowGraphBuilder extends DataflowGraph {
|
|
|
114
114
|
* @see reads for parameters.
|
|
115
115
|
*/
|
|
116
116
|
definesOnCall(from: NodeId, to: DataflowGraphEdgeTarget): this;
|
|
117
|
+
/**
|
|
118
|
+
* Adds a **defined-by-on-call edge** with from as definition, and to as variable.
|
|
119
|
+
*
|
|
120
|
+
* @see reads for parameters.
|
|
121
|
+
*/
|
|
122
|
+
definedByOnCall(from: NodeId, to: DataflowGraphEdgeTarget): this;
|
|
117
123
|
/**
|
|
118
124
|
* Adds an **argument edge** (E9) with from as function call, and to as argument.
|
|
119
125
|
*
|
|
@@ -212,6 +212,14 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
|
|
|
212
212
|
definesOnCall(from, to) {
|
|
213
213
|
return this.edgeHelper(from, to, edge_1.EdgeType.DefinesOnCall);
|
|
214
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Adds a **defined-by-on-call edge** with from as definition, and to as variable.
|
|
217
|
+
*
|
|
218
|
+
* @see reads for parameters.
|
|
219
|
+
*/
|
|
220
|
+
definedByOnCall(from, to) {
|
|
221
|
+
return this.edgeHelper(from, to, edge_1.EdgeType.DefinedByOnCall);
|
|
222
|
+
}
|
|
215
223
|
/**
|
|
216
224
|
* Adds an **argument edge** (E9) with from as function call, and to as argument.
|
|
217
225
|
*
|
package/dataflow/graph/edge.d.ts
CHANGED
|
@@ -19,9 +19,15 @@ export declare enum EdgeType {
|
|
|
19
19
|
Calls = 4,
|
|
20
20
|
/** The source returns target on call */
|
|
21
21
|
Returns = 8,
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* The edge determines that source (probably argument) defines the target (probably parameter).
|
|
24
|
+
* This may also link a function call to definitions it causes to be active (as part of the closure) of the called function definition.
|
|
25
|
+
*/
|
|
23
26
|
DefinesOnCall = 16,
|
|
24
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Usually the inverse of `defines-on-call` (in the context of arguments and parameters).
|
|
29
|
+
* This may also link an open read (within a function) to the definition that is active at the call site.
|
|
30
|
+
*/
|
|
25
31
|
DefinedByOnCall = 32,
|
|
26
32
|
/** Formal used as argument to a function call */
|
|
27
33
|
Argument = 64,
|
|
@@ -57,8 +63,8 @@ export declare const enum TraverseEdge {
|
|
|
57
63
|
Never = 0,
|
|
58
64
|
/** Traverse the edge as a side effect */
|
|
59
65
|
SideEffect = 1,
|
|
60
|
-
/** Traverse this edge if the definition is relevant */
|
|
61
|
-
|
|
66
|
+
/** Traverse this edge if the definition is relevant (i.e., if two matching edges trigger this state) */
|
|
67
|
+
OnlyIfBoth = 2,
|
|
62
68
|
/** Always traverse this edge */
|
|
63
69
|
Always = 3
|
|
64
70
|
}
|
package/dataflow/graph/edge.js
CHANGED
|
@@ -22,9 +22,15 @@ var EdgeType;
|
|
|
22
22
|
EdgeType[EdgeType["Calls"] = 4] = "Calls";
|
|
23
23
|
/** The source returns target on call */
|
|
24
24
|
EdgeType[EdgeType["Returns"] = 8] = "Returns";
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* The edge determines that source (probably argument) defines the target (probably parameter).
|
|
27
|
+
* This may also link a function call to definitions it causes to be active (as part of the closure) of the called function definition.
|
|
28
|
+
*/
|
|
26
29
|
EdgeType[EdgeType["DefinesOnCall"] = 16] = "DefinesOnCall";
|
|
27
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Usually the inverse of `defines-on-call` (in the context of arguments and parameters).
|
|
32
|
+
* This may also link an open read (within a function) to the definition that is active at the call site.
|
|
33
|
+
*/
|
|
28
34
|
EdgeType[EdgeType["DefinedByOnCall"] = 32] = "DefinedByOnCall";
|
|
29
35
|
/** Formal used as argument to a function call */
|
|
30
36
|
EdgeType[EdgeType["Argument"] = 64] = "Argument";
|
|
@@ -89,13 +95,14 @@ function edgeIncludesType(type, types) {
|
|
|
89
95
|
function edgeDoesNotIncludeType(type, types) {
|
|
90
96
|
return (types & type) === 0;
|
|
91
97
|
}
|
|
92
|
-
const alwaysTraverseEdgeTypes = EdgeType.Reads | EdgeType.DefinedBy | EdgeType.Argument | EdgeType.Calls
|
|
98
|
+
const alwaysTraverseEdgeTypes = EdgeType.Reads | EdgeType.DefinedBy | EdgeType.Argument | EdgeType.Calls;
|
|
99
|
+
const definedByOnCallTypes = EdgeType.DefinesOnCall | EdgeType.DefinedByOnCall;
|
|
93
100
|
function shouldTraverseEdge(types) {
|
|
94
101
|
if (edgeIncludesType(types, alwaysTraverseEdgeTypes)) {
|
|
95
102
|
return 3 /* TraverseEdge.Always */;
|
|
96
103
|
}
|
|
97
|
-
else if (edgeIncludesType(types,
|
|
98
|
-
return 2 /* TraverseEdge.
|
|
104
|
+
else if (edgeIncludesType(types, definedByOnCallTypes)) {
|
|
105
|
+
return 2 /* TraverseEdge.OnlyIfBoth */;
|
|
99
106
|
}
|
|
100
107
|
else if (edgeIncludesType(types, EdgeType.SideEffectOnCall)) {
|
|
101
108
|
return 1 /* TraverseEdge.SideEffect */;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { DataflowGraphEdge } from './edge';
|
|
2
|
-
import { EdgeType } from './edge';
|
|
1
|
+
import type { DataflowGraphEdge, EdgeType } from './edge';
|
|
3
2
|
import type { DataflowInformation } from '../info';
|
|
4
3
|
import type { DataflowGraphVertexArgument, DataflowGraphVertexFunctionCall, DataflowGraphVertexInfo } from './vertex';
|
|
5
4
|
import { EmptyArgument } from '../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
@@ -7,30 +6,56 @@ import type { IdentifierDefinition, IdentifierReference } from '../environments/
|
|
|
7
6
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
7
|
import type { AstIdMap } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
9
8
|
import type { LinkTo } from '../../queries/catalog/call-context-query/call-context-query-format';
|
|
9
|
+
/**
|
|
10
|
+
* Describes the information we store per function body.
|
|
11
|
+
* The {@link DataflowFunctionFlowInformation#exitPoints} are stored within the enclosing {@link DataflowGraphVertexFunctionDefinition} vertex.
|
|
12
|
+
*/
|
|
10
13
|
export type DataflowFunctionFlowInformation = Omit<DataflowInformation, 'graph' | 'exitPoints'> & {
|
|
11
14
|
graph: Set<NodeId>;
|
|
12
15
|
};
|
|
13
16
|
/**
|
|
17
|
+
* A reference with a name, e.g. `a` and `b` in the following function call:
|
|
18
|
+
*
|
|
14
19
|
* ```r
|
|
15
20
|
* foo(a = 3, b = 2)
|
|
16
21
|
* ```
|
|
22
|
+
*
|
|
23
|
+
* @see #isNamedArgument
|
|
24
|
+
* @see PositionalFunctionArgument
|
|
17
25
|
*/
|
|
18
26
|
export interface NamedFunctionArgument extends IdentifierReference {
|
|
19
27
|
readonly name: string;
|
|
20
28
|
}
|
|
21
29
|
/**
|
|
30
|
+
* A reference which does not have a name, like the references to the arguments `3` and `2` in the following:
|
|
31
|
+
*
|
|
22
32
|
* ```r
|
|
23
33
|
* foo(3, 2)
|
|
24
34
|
* ```
|
|
35
|
+
*
|
|
36
|
+
* @see #isPositionalArgument
|
|
37
|
+
* @see NamedFunctionArgument
|
|
25
38
|
*/
|
|
26
39
|
export interface PositionalFunctionArgument extends Omit<IdentifierReference, 'name'> {
|
|
27
40
|
readonly name?: undefined;
|
|
28
41
|
}
|
|
29
42
|
/** Summarizes either named (`foo(a = 3, b = 2)`), unnamed (`foo(3, 2)`), or empty (`foo(,)`) arguments within a function. */
|
|
30
43
|
export type FunctionArgument = NamedFunctionArgument | PositionalFunctionArgument | typeof EmptyArgument;
|
|
44
|
+
/**
|
|
45
|
+
* Check if the given argument is a {@link PositionalFunctionArgument}.
|
|
46
|
+
*/
|
|
31
47
|
export declare function isPositionalArgument(arg: FunctionArgument): arg is PositionalFunctionArgument;
|
|
48
|
+
/**
|
|
49
|
+
* Check if the given argument is a {@link NamedFunctionArgument}.
|
|
50
|
+
*/
|
|
32
51
|
export declare function isNamedArgument(arg: FunctionArgument): arg is NamedFunctionArgument;
|
|
52
|
+
/**
|
|
53
|
+
* Returns the reference of a non-empty argument.
|
|
54
|
+
*/
|
|
33
55
|
export declare function getReferenceOfArgument(arg: FunctionArgument): NodeId | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* A reference that is enough to indicate start and end points of an edge within the dataflow graph.
|
|
58
|
+
*/
|
|
34
59
|
type ReferenceForEdge = Pick<IdentifierReference, 'nodeId' | 'controlDependencies'> | IdentifierDefinition;
|
|
35
60
|
/**
|
|
36
61
|
* Maps the edges target to the edge information
|
|
@@ -41,11 +66,20 @@ export type OutgoingEdges<Edge extends DataflowGraphEdge = DataflowGraphEdge> =
|
|
|
41
66
|
* In other words, it maps the source to the edge information.
|
|
42
67
|
*/
|
|
43
68
|
export type IngoingEdges<Edge extends DataflowGraphEdge = DataflowGraphEdge> = Map<NodeId, Edge>;
|
|
69
|
+
/**
|
|
70
|
+
* The structure of the serialized {@link DataflowGraph}.
|
|
71
|
+
*/
|
|
44
72
|
export interface DataflowGraphJson {
|
|
45
73
|
readonly rootVertices: NodeId[];
|
|
46
74
|
readonly vertexInformation: [NodeId, DataflowGraphVertexInfo][];
|
|
47
75
|
readonly edgeInformation: [NodeId, [NodeId, DataflowGraphEdge][]][];
|
|
48
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* An unknown side effect describes something that we cannot handle correctly (in all cases).
|
|
79
|
+
* For example, `eval` will be marked as an unknown side effect as we have no idea of how it will affect the program.
|
|
80
|
+
* Linked side effects are used whenever we know that a call may be affected by another one in a way that we cannot
|
|
81
|
+
* grasp from the dataflow perspective (e.g., an indirect dependency based on the currently active graphic device).
|
|
82
|
+
*/
|
|
49
83
|
export type UnknownSidEffect = NodeId | {
|
|
50
84
|
id: NodeId;
|
|
51
85
|
linkTo: LinkTo<RegExp>;
|
|
@@ -60,6 +94,11 @@ export type UnknownSidEffect = NodeId | {
|
|
|
60
94
|
* However, this does not have to hold during the construction as edges may point from or to vertices which are yet to be constructed.
|
|
61
95
|
*
|
|
62
96
|
* All methods return the modified graph to allow for chaining.
|
|
97
|
+
*
|
|
98
|
+
* @see {@link DataflowGraph#addEdge|`addEdge`} - to add an edge to the graph
|
|
99
|
+
* @see {@link DataflowGraph#addVertex|`addVertex`} - to add a vertex to the graph
|
|
100
|
+
* @see {@link DataflowGraph#fromJson|`fromJson`} - to construct a dataflow graph object from a deserialized JSON object.
|
|
101
|
+
* @see {@link emptyGraph} - to create an empty graph (useful in tests)
|
|
63
102
|
*/
|
|
64
103
|
export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo, Edge extends DataflowGraphEdge = DataflowGraphEdge> {
|
|
65
104
|
private static DEFAULT_ENVIRONMENT;
|
|
@@ -144,7 +183,6 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
|
|
|
144
183
|
addEdge(from: ReferenceForEdge, to: ReferenceForEdge, type: EdgeType): this;
|
|
145
184
|
/** {@inheritDoc} */
|
|
146
185
|
addEdge(from: NodeId | ReferenceForEdge, to: NodeId | ReferenceForEdge, type: EdgeType): this;
|
|
147
|
-
private installEdge;
|
|
148
186
|
/**
|
|
149
187
|
* Merges the other graph into *this* one (in-place). The return value is only for convenience.
|
|
150
188
|
*
|