@eagleoutice/flowr 2.4.0 → 2.4.1
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 +23 -23
- package/benchmark/stats/size-of.js +3 -3
- package/cli/repl/commands/repl-query.js +1 -1
- package/core/pipeline-executor.js +0 -8
- package/core/steps/all/static-slicing/00-slice.js +1 -1
- package/dataflow/environments/append.js +1 -1
- package/dataflow/environments/built-in-config.d.ts +12 -4
- package/dataflow/environments/built-in-config.js +23 -82
- package/dataflow/environments/built-in.d.ts +38 -4
- package/dataflow/environments/built-in.js +106 -11
- package/dataflow/environments/clone.d.ts +3 -2
- package/dataflow/environments/clone.js +6 -5
- package/dataflow/environments/define.js +1 -2
- package/dataflow/environments/diff.js +1 -3
- package/dataflow/environments/environment.d.ts +18 -24
- package/dataflow/environments/environment.js +25 -37
- package/dataflow/environments/overwrite.d.ts +1 -1
- package/dataflow/environments/overwrite.js +1 -1
- package/dataflow/environments/remove.d.ts +2 -2
- package/dataflow/environments/remove.js +3 -4
- package/dataflow/environments/resolve-by-name.d.ts +3 -3
- package/dataflow/environments/resolve-by-name.js +4 -5
- package/dataflow/eval/resolve/alias-tracking.d.ts +12 -12
- package/dataflow/eval/resolve/alias-tracking.js +12 -12
- package/dataflow/eval/resolve/resolve.js +1 -1
- package/dataflow/extractor.js +6 -1
- package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
- package/dataflow/graph/graph.d.ts +2 -1
- package/dataflow/graph/graph.js +5 -1
- package/dataflow/info.d.ts +1 -1
- package/dataflow/internal/linker.js +9 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +1 -1
- package/dataflow/processor.d.ts +5 -1
- package/documentation/doc-util/doc-env.js +1 -2
- package/package.json +1 -1
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +7 -7
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +18 -0
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +9 -5
- package/queries/catalog/dependencies-query/function-info/read-functions.js +4 -2
- package/queries/catalog/dependencies-query/function-info/write-functions.js +5 -0
- package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -2
- package/slicing/static/fingerprint.js +1 -2
- package/slicing/static/slice-call.d.ts +2 -1
- package/slicing/static/slice-call.js +3 -3
- package/slicing/static/static-slicer.d.ts +3 -4
- package/slicing/static/static-slicer.js +4 -4
- package/util/containers.d.ts +1 -0
- package/util/containers.js +1 -0
- package/util/json.js +1 -4
- package/util/mermaid/dfg.js +1 -2
- package/util/prefix.d.ts +1 -1
- package/util/version.js +1 -1
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.mergeDefinitions = mergeDefinitions;
|
|
4
4
|
exports.define = define;
|
|
5
5
|
const assert_1 = require("../../util/assert");
|
|
6
|
-
const environment_1 = require("./environment");
|
|
7
6
|
const clone_1 = require("./clone");
|
|
8
7
|
const vertex_1 = require("../graph/vertex");
|
|
9
8
|
function defInEnv(newEnvironments, name, definition, config) {
|
|
@@ -138,7 +137,7 @@ function define(definition, superAssign, environment, config) {
|
|
|
138
137
|
}
|
|
139
138
|
last = current;
|
|
140
139
|
current = current.parent;
|
|
141
|
-
} while (current.
|
|
140
|
+
} while (!current.builtInEnv);
|
|
142
141
|
if (!found) {
|
|
143
142
|
(0, assert_1.guard)(last !== undefined, () => `Could not find global scope for ${name}`);
|
|
144
143
|
last.memory.set(name, [definition]);
|
|
@@ -7,7 +7,6 @@ const diff_1 = require("../../util/diff");
|
|
|
7
7
|
const environment_1 = require("./environment");
|
|
8
8
|
const json_1 = require("../../util/json");
|
|
9
9
|
const info_1 = require("../info");
|
|
10
|
-
const built_in_1 = require("./built-in");
|
|
11
10
|
function diffIdentifierReferences(a, b, info) {
|
|
12
11
|
if (a === undefined || b === undefined) {
|
|
13
12
|
if (a !== b) {
|
|
@@ -59,8 +58,7 @@ function diffEnvironment(a, b, info, depth) {
|
|
|
59
58
|
}
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
62
|
-
if (
|
|
63
|
-
(b.memory === built_in_1.BuiltInMemory || b.memory === built_in_1.EmptyBuiltInMemory)) {
|
|
61
|
+
if (a.builtInEnv && b.builtInEnv) {
|
|
64
62
|
return;
|
|
65
63
|
}
|
|
66
64
|
if (a.memory.size !== b.memory.size) {
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { IdentifierReference } from './identifier';
|
|
8
8
|
import type { DataflowGraph } from '../graph/graph';
|
|
9
9
|
import type { ControlDependency } from '../info';
|
|
10
|
+
import type { BuiltInMemory } from './built-in';
|
|
10
11
|
/**
|
|
11
12
|
* Marks the reference as maybe (i.e., as controlled by a set of {@link IdentifierReference#controlDependencies|control dependencies}).
|
|
12
13
|
*/
|
|
13
14
|
export declare function makeReferenceMaybe(ref: IdentifierReference, graph: DataflowGraph, environments: REnvironmentInformation, includeDefs: boolean, defaultCd?: ControlDependency | undefined): IdentifierReference;
|
|
14
15
|
export declare function makeAllMaybe(references: readonly IdentifierReference[] | undefined, graph: DataflowGraph, environments: REnvironmentInformation, includeDefs: boolean, defaultCd?: ControlDependency | undefined): IdentifierReference[];
|
|
15
|
-
export type EnvironmentMemory = Map<Identifier, IdentifierDefinition[]>;
|
|
16
16
|
/** A single entry/scope within an {@link REnvironmentInformation} */
|
|
17
17
|
export interface IEnvironment {
|
|
18
18
|
/** Unique and internally generated identifier -- will not be used for comparison but helps with debugging for tracking identities */
|
|
@@ -20,21 +20,31 @@ export interface IEnvironment {
|
|
|
20
20
|
/** Lexical parent of the environment, if any (can be manipulated by R code) */
|
|
21
21
|
parent: IEnvironment;
|
|
22
22
|
/** Maps to exactly one definition of an identifier if the source is known, otherwise to a list of all possible definitions */
|
|
23
|
-
memory:
|
|
23
|
+
memory: BuiltInMemory;
|
|
24
|
+
/**
|
|
25
|
+
* Is this a built-in environment that is not allowed to change? Please use this carefully and only for the top-most envs!
|
|
26
|
+
*/
|
|
27
|
+
builtInEnv?: true | undefined;
|
|
24
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Please use this function only if you do not know the object type.
|
|
31
|
+
* Otherwise, rely on {@link IEnvironment#builtInEnv}
|
|
32
|
+
*/
|
|
33
|
+
export declare function isDefaultBuiltInEnvironment(obj: unknown): boolean;
|
|
25
34
|
/** @see REnvironmentInformation */
|
|
26
35
|
export declare class Environment implements IEnvironment {
|
|
27
36
|
readonly id: number;
|
|
28
37
|
parent: IEnvironment;
|
|
29
|
-
memory:
|
|
30
|
-
|
|
38
|
+
memory: BuiltInMemory;
|
|
39
|
+
builtInEnv?: true;
|
|
40
|
+
constructor(parent: IEnvironment, isBuiltInDefault?: true | undefined);
|
|
31
41
|
}
|
|
32
42
|
export interface WorkingDirectoryReference {
|
|
33
43
|
readonly path: string;
|
|
34
44
|
readonly controlDependencies: ControlDependency[] | undefined;
|
|
35
45
|
}
|
|
36
46
|
/**
|
|
37
|
-
* An environment describes a ({@link IEnvironment#parent|scoped}) mapping of names to their definitions ({@link
|
|
47
|
+
* An environment describes a ({@link IEnvironment#parent|scoped}) mapping of names to their definitions ({@link BuiltIns}).
|
|
38
48
|
*
|
|
39
49
|
* First, yes, R stores its environments differently, potentially even with another differentiation between
|
|
40
50
|
* the `baseenv`, the `emptyenv`, and other default environments (see https://adv-r.hadley.nz/environments.html).
|
|
@@ -42,7 +52,7 @@ export interface WorkingDirectoryReference {
|
|
|
42
52
|
* and sometimes know less (to be honest, we do not want that,
|
|
43
53
|
* but statically determining all attached environments is theoretically impossible --- consider attachments by user input).
|
|
44
54
|
*
|
|
45
|
-
* One important environment is the {@link BuiltInEnvironment} which contains the default definitions for R's built-in functions and constants.
|
|
55
|
+
* One important environment is the {@link BuiltIns|BuiltInEnvironment} which contains the default definitions for R's built-in functions and constants.
|
|
46
56
|
* Please use {@link initializeCleanEnvironments} to initialize the environments (which includes the built-ins).
|
|
47
57
|
* During serialization, you may want to rely on the {@link builtInEnvJsonReplacer} to avoid the huge built-in environment.
|
|
48
58
|
*
|
|
@@ -61,26 +71,10 @@ export interface REnvironmentInformation {
|
|
|
61
71
|
/** nesting level of the environment, will be `0` for the global/root environment */
|
|
62
72
|
readonly level: number;
|
|
63
73
|
}
|
|
64
|
-
/**
|
|
65
|
-
* The built-in {@link REnvironmentInformation|environment} is the root of all environments.
|
|
66
|
-
*
|
|
67
|
-
* For its default content (when not overwritten by a flowR config),
|
|
68
|
-
* see the {@link DefaultBuiltinConfig}.
|
|
69
|
-
*/
|
|
70
|
-
export declare const BuiltInEnvironment: Environment;
|
|
71
|
-
/**
|
|
72
|
-
* The twin of the {@link BuiltInEnvironment} but with less built ins defined for
|
|
73
|
-
* cases in which we want some commonly overwritten variables to remain open.
|
|
74
|
-
* If you do not know if you need the empty environment, you do not need the empty environment (right now).
|
|
75
|
-
*
|
|
76
|
-
* @see {@link BuiltInEnvironment}
|
|
77
|
-
*/
|
|
78
|
-
export declare const EmptyBuiltInEnvironment: IEnvironment;
|
|
79
74
|
/**
|
|
80
75
|
* Initialize a new {@link REnvironmentInformation|environment} with the built-ins.
|
|
81
|
-
* See {@link EmptyBuiltInEnvironment} for the case `fullBuiltIns = false`.
|
|
82
76
|
*/
|
|
83
|
-
export declare function initializeCleanEnvironments(fullBuiltIns?: boolean): REnvironmentInformation;
|
|
77
|
+
export declare function initializeCleanEnvironments(memory?: BuiltInMemory, fullBuiltIns?: boolean): REnvironmentInformation;
|
|
84
78
|
/**
|
|
85
79
|
* Helps to serialize an environment, but replaces the built-in environment with a placeholder.
|
|
86
80
|
*/
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.Environment = void 0;
|
|
4
4
|
exports.makeReferenceMaybe = makeReferenceMaybe;
|
|
5
5
|
exports.makeAllMaybe = makeAllMaybe;
|
|
6
|
+
exports.isDefaultBuiltInEnvironment = isDefaultBuiltInEnvironment;
|
|
6
7
|
exports.initializeCleanEnvironments = initializeCleanEnvironments;
|
|
7
8
|
exports.builtInEnvJsonReplacer = builtInEnvJsonReplacer;
|
|
8
9
|
const identifier_1 = require("./identifier");
|
|
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
|
+
const built_in_config_1 = require("./built-in-config");
|
|
12
13
|
/**
|
|
13
14
|
* Marks the reference as maybe (i.e., as controlled by a set of {@link IdentifierReference#controlDependencies|control dependencies}).
|
|
14
15
|
*/
|
|
15
16
|
function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = undefined) {
|
|
16
|
-
const node = graph.get(ref.nodeId, true);
|
|
17
17
|
if (includeDefs) {
|
|
18
18
|
const definitions = ref.name ? (0, resolve_by_name_1.resolveByName)(ref.name, environments, ref.type) : undefined;
|
|
19
19
|
for (const definition of definitions ?? []) {
|
|
@@ -27,6 +27,7 @@ function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = u
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
const node = graph.get(ref.nodeId, true);
|
|
30
31
|
if (node) {
|
|
31
32
|
const [fst] = node;
|
|
32
33
|
if (fst.cds && defaultCd && !fst.cds.includes(defaultCd)) {
|
|
@@ -44,49 +45,39 @@ function makeAllMaybe(references, graph, environments, includeDefs, defaultCd =
|
|
|
44
45
|
}
|
|
45
46
|
return references.map(ref => makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd));
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Please use this function only if you do not know the object type.
|
|
50
|
+
* Otherwise, rely on {@link IEnvironment#builtInEnv}
|
|
51
|
+
*/
|
|
52
|
+
function isDefaultBuiltInEnvironment(obj) {
|
|
53
|
+
return typeof obj === 'object' && obj !== null && (obj.builtInEnv === true);
|
|
54
|
+
}
|
|
55
|
+
let environmentIdCounter = 1; // Zero is reserved for built-in environment
|
|
48
56
|
/** @see REnvironmentInformation */
|
|
49
57
|
class Environment {
|
|
50
|
-
id
|
|
58
|
+
id;
|
|
51
59
|
parent;
|
|
52
60
|
memory;
|
|
53
|
-
|
|
61
|
+
builtInEnv;
|
|
62
|
+
constructor(parent, isBuiltInDefault = undefined) {
|
|
63
|
+
this.id = isBuiltInDefault ? 0 : environmentIdCounter++;
|
|
54
64
|
this.parent = parent;
|
|
55
65
|
this.memory = new Map();
|
|
66
|
+
// do not store if not needed!
|
|
67
|
+
if (isBuiltInDefault) {
|
|
68
|
+
this.builtInEnv = isBuiltInDefault;
|
|
69
|
+
}
|
|
56
70
|
}
|
|
57
71
|
}
|
|
58
72
|
exports.Environment = Environment;
|
|
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
|
-
*/
|
|
65
|
-
exports.BuiltInEnvironment = new Environment(undefined);
|
|
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
|
-
*/
|
|
74
|
-
exports.EmptyBuiltInEnvironment = {
|
|
75
|
-
id: exports.BuiltInEnvironment.id,
|
|
76
|
-
memory: undefined,
|
|
77
|
-
parent: undefined
|
|
78
|
-
};
|
|
79
73
|
/**
|
|
80
74
|
* Initialize a new {@link REnvironmentInformation|environment} with the built-ins.
|
|
81
|
-
* See {@link EmptyBuiltInEnvironment} for the case `fullBuiltIns = false`.
|
|
82
75
|
*/
|
|
83
|
-
function initializeCleanEnvironments(fullBuiltIns = true) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
exports.EmptyBuiltInEnvironment.memory = built_in_1.EmptyBuiltInMemory;
|
|
87
|
-
}
|
|
76
|
+
function initializeCleanEnvironments(memory, fullBuiltIns = true) {
|
|
77
|
+
const builtInEnv = new Environment(undefined, true);
|
|
78
|
+
builtInEnv.memory = memory ?? (fullBuiltIns ? (0, built_in_config_1.getDefaultBuiltInDefinitions)().builtInMemory : (0, built_in_config_1.getDefaultBuiltInDefinitions)().emptyBuiltInMemory);
|
|
88
79
|
return {
|
|
89
|
-
current: new Environment(
|
|
80
|
+
current: new Environment(builtInEnv),
|
|
90
81
|
level: 0
|
|
91
82
|
};
|
|
92
83
|
}
|
|
@@ -94,12 +85,9 @@ function initializeCleanEnvironments(fullBuiltIns = true) {
|
|
|
94
85
|
* Helps to serialize an environment, but replaces the built-in environment with a placeholder.
|
|
95
86
|
*/
|
|
96
87
|
function builtInEnvJsonReplacer(k, v) {
|
|
97
|
-
if (v
|
|
88
|
+
if (isDefaultBuiltInEnvironment(v)) {
|
|
98
89
|
return '<BuiltInEnvironment>';
|
|
99
90
|
}
|
|
100
|
-
else if (v === exports.EmptyBuiltInEnvironment) {
|
|
101
|
-
return '<EmptyBuiltInEnvironment>';
|
|
102
|
-
}
|
|
103
91
|
else {
|
|
104
92
|
return (0, json_1.jsonReplacer)(k, v);
|
|
105
93
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IEnvironment, REnvironmentInformation } from './environment';
|
|
2
2
|
import type { ControlDependency } from '../info';
|
|
3
3
|
export declare function overwriteIEnvironmentWith(base: IEnvironment | undefined, next: IEnvironment | undefined, includeParent?: boolean, applyCds?: readonly ControlDependency[]): IEnvironment;
|
|
4
4
|
export declare function overwriteEnvironment(base: REnvironmentInformation, next: REnvironmentInformation | undefined, applyCds?: readonly ControlDependency[]): REnvironmentInformation;
|
|
@@ -50,7 +50,7 @@ function overwriteIEnvironmentWith(base, next, includeParent = true, applyCds) {
|
|
|
50
50
|
}
|
|
51
51
|
let parent;
|
|
52
52
|
if (includeParent) {
|
|
53
|
-
parent = base.parent.
|
|
53
|
+
parent = base.parent.builtInEnv ? base.parent : overwriteIEnvironmentWith(base.parent, next.parent, includeParent, applyCds);
|
|
54
54
|
}
|
|
55
55
|
else {
|
|
56
56
|
parent = base.parent;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { REnvironmentInformation } from './environment';
|
|
1
|
+
import type { IEnvironment, REnvironmentInformation } from './environment';
|
|
2
2
|
import type { Identifier } from './identifier';
|
|
3
3
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
4
4
|
/**
|
|
5
5
|
* Removes all definitions of a given name from the environment.
|
|
6
6
|
*/
|
|
7
|
-
export declare function remove(name: Identifier, environment: REnvironmentInformation): REnvironmentInformation;
|
|
7
|
+
export declare function remove(name: Identifier, environment: REnvironmentInformation, defaultEnvironment: IEnvironment): REnvironmentInformation;
|
|
8
8
|
/** Creates a copy of the original environment but without the definitions of the given ids */
|
|
9
9
|
export declare function removeAll(definitions: readonly {
|
|
10
10
|
nodeId: NodeId;
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.remove = remove;
|
|
4
4
|
exports.removeAll = removeAll;
|
|
5
|
-
const environment_1 = require("./environment");
|
|
6
5
|
const info_1 = require("../info");
|
|
7
6
|
const clone_1 = require("./clone");
|
|
8
7
|
/**
|
|
9
8
|
* Removes all definitions of a given name from the environment.
|
|
10
9
|
*/
|
|
11
|
-
function remove(name, environment) {
|
|
10
|
+
function remove(name, environment, defaultEnvironment) {
|
|
12
11
|
let current = environment.current;
|
|
13
12
|
do {
|
|
14
13
|
const definition = current.memory.get(name);
|
|
@@ -19,7 +18,7 @@ function remove(name, environment) {
|
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
20
|
current = current.parent;
|
|
22
|
-
} while (current.id !==
|
|
21
|
+
} while (current.id !== defaultEnvironment.id);
|
|
23
22
|
// we never remove built ins
|
|
24
23
|
return environment;
|
|
25
24
|
}
|
|
@@ -46,7 +45,7 @@ function removeAll(definitions, environment) {
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
current = current.parent;
|
|
49
|
-
} while (current.
|
|
48
|
+
} while (!current.builtInEnv);
|
|
50
49
|
// we never remove built ins so we can stop one early
|
|
51
50
|
return environment;
|
|
52
51
|
}
|
|
@@ -5,9 +5,9 @@ import { ReferenceType } from './identifier';
|
|
|
5
5
|
/**
|
|
6
6
|
* Resolves a given identifier name to a list of its possible definition location using R scoping and resolving rules.
|
|
7
7
|
*
|
|
8
|
-
* @param name
|
|
9
|
-
* @param environment
|
|
10
|
-
* @param target
|
|
8
|
+
* @param name - The name of the identifier to resolve
|
|
9
|
+
* @param environment - The current environment used for name resolution
|
|
10
|
+
* @param target - The target (meta) type of the identifier to resolve
|
|
11
11
|
*
|
|
12
12
|
* @returns A list of possible identifier definitions (one if the definition location is exactly and always known), or `undefined`
|
|
13
13
|
* if the identifier is undefined in the current scope/with the current environment information.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveByName = resolveByName;
|
|
4
4
|
exports.resolvesToBuiltInConstant = resolvesToBuiltInConstant;
|
|
5
|
-
const environment_1 = require("./environment");
|
|
6
5
|
const logic_1 = require("../../util/logic");
|
|
7
6
|
const identifier_1 = require("./identifier");
|
|
8
7
|
const info_1 = require("../info");
|
|
@@ -24,9 +23,9 @@ const TargetTypePredicate = {
|
|
|
24
23
|
/**
|
|
25
24
|
* Resolves a given identifier name to a list of its possible definition location using R scoping and resolving rules.
|
|
26
25
|
*
|
|
27
|
-
* @param name
|
|
28
|
-
* @param environment
|
|
29
|
-
* @param target
|
|
26
|
+
* @param name - The name of the identifier to resolve
|
|
27
|
+
* @param environment - The current environment used for name resolution
|
|
28
|
+
* @param target - The target (meta) type of the identifier to resolve
|
|
30
29
|
*
|
|
31
30
|
* @returns A list of possible identifier definitions (one if the definition location is exactly and always known), or `undefined`
|
|
32
31
|
* if the identifier is undefined in the current scope/with the current environment information.
|
|
@@ -48,7 +47,7 @@ function resolveByName(name, environment, target = identifier_1.ReferenceType.Un
|
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
current = current.parent;
|
|
51
|
-
} while (current.
|
|
50
|
+
} while (!current.builtInEnv);
|
|
52
51
|
const builtIns = current.memory.get(name);
|
|
53
52
|
if (definitions) {
|
|
54
53
|
return builtIns === undefined ? definitions : definitions.concat(builtIns);
|
|
@@ -27,9 +27,9 @@ export interface ResolveInfo {
|
|
|
27
27
|
* us later, in the {@link trackAliasInEnvironments} function, to get all the
|
|
28
28
|
* aliases of an identifier.
|
|
29
29
|
*
|
|
30
|
-
* @param sourceIds
|
|
31
|
-
* @param dataflow
|
|
32
|
-
* @param environment
|
|
30
|
+
* @param sourceIds - node ids to get the definitions for
|
|
31
|
+
* @param dataflow - dataflow graph
|
|
32
|
+
* @param environment - environment
|
|
33
33
|
* @returns node id of alias
|
|
34
34
|
*/
|
|
35
35
|
export declare function getAliases(sourceIds: readonly NodeId[], dataflow: DataflowGraph, environment: REnvironmentInformation): NodeId[] | undefined;
|
|
@@ -46,12 +46,12 @@ export declare function getAliases(sourceIds: readonly NodeId[], dataflow: Dataf
|
|
|
46
46
|
* to resolve values. For e.g. in the Dependency Query it is used to resolve calls
|
|
47
47
|
* like `lapply(c("a", "b", "c"), library, character.only = TRUE)`
|
|
48
48
|
*
|
|
49
|
-
* @param id
|
|
50
|
-
* @param environment
|
|
51
|
-
* @param graph
|
|
52
|
-
* @param idMap
|
|
53
|
-
* @param full
|
|
54
|
-
* @param resolve
|
|
49
|
+
* @param id - The node id or node to resolve
|
|
50
|
+
* @param environment - The current environment used for name resolution
|
|
51
|
+
* @param graph - The graph to resolve in
|
|
52
|
+
* @param idMap - The id map to resolve the node if given as an id
|
|
53
|
+
* @param full - Whether to track aliases on resolve
|
|
54
|
+
* @param resolve - Variable resolve mode
|
|
55
55
|
*/
|
|
56
56
|
export declare function resolveIdToValue(id: NodeId | RNodeWithParent | undefined, { environment, graph, idMap, full, resolve }: ResolveInfo): ResolveResult;
|
|
57
57
|
/**
|
|
@@ -64,7 +64,7 @@ export declare function resolveIdToValue(id: NodeId | RNodeWithParent | undefine
|
|
|
64
64
|
* @param resolve - Variable resolve mode
|
|
65
65
|
* @param identifier - Identifier to resolve
|
|
66
66
|
* @param use - Environment to use
|
|
67
|
-
* @param graph -
|
|
67
|
+
* @param graph - dataflow graph
|
|
68
68
|
* @param idMap - id map of Dataflow graph
|
|
69
69
|
* @returns Value of Identifier or Top
|
|
70
70
|
*/
|
|
@@ -85,8 +85,8 @@ export declare function trackAliasesInGraph(id: NodeId, graph: DataflowGraph, id
|
|
|
85
85
|
*
|
|
86
86
|
* Resolve an Identifier to a constant, if the identifier is a constant
|
|
87
87
|
*
|
|
88
|
-
* @param name
|
|
89
|
-
* @param environment
|
|
88
|
+
* @param name - Identifier to resolve
|
|
89
|
+
* @param environment - Environment to use
|
|
90
90
|
* @returns Value of Constant or Top
|
|
91
91
|
*/
|
|
92
92
|
export declare function resolveToConstants(name: Identifier | undefined, environment: REnvironmentInformation): ResolveResult;
|
|
@@ -78,9 +78,9 @@ function getUseAlias(sourceId, dataflow, environment) {
|
|
|
78
78
|
* us later, in the {@link trackAliasInEnvironments} function, to get all the
|
|
79
79
|
* aliases of an identifier.
|
|
80
80
|
*
|
|
81
|
-
* @param sourceIds
|
|
82
|
-
* @param dataflow
|
|
83
|
-
* @param environment
|
|
81
|
+
* @param sourceIds - node ids to get the definitions for
|
|
82
|
+
* @param dataflow - dataflow graph
|
|
83
|
+
* @param environment - environment
|
|
84
84
|
* @returns node id of alias
|
|
85
85
|
*/
|
|
86
86
|
function getAliases(sourceIds, dataflow, environment) {
|
|
@@ -110,12 +110,12 @@ function getAliases(sourceIds, dataflow, environment) {
|
|
|
110
110
|
* to resolve values. For e.g. in the Dependency Query it is used to resolve calls
|
|
111
111
|
* like `lapply(c("a", "b", "c"), library, character.only = TRUE)`
|
|
112
112
|
*
|
|
113
|
-
* @param id
|
|
114
|
-
* @param environment
|
|
115
|
-
* @param graph
|
|
116
|
-
* @param idMap
|
|
117
|
-
* @param full
|
|
118
|
-
* @param resolve
|
|
113
|
+
* @param id - The node id or node to resolve
|
|
114
|
+
* @param environment - The current environment used for name resolution
|
|
115
|
+
* @param graph - The graph to resolve in
|
|
116
|
+
* @param idMap - The id map to resolve the node if given as an id
|
|
117
|
+
* @param full - Whether to track aliases on resolve
|
|
118
|
+
* @param resolve - Variable resolve mode
|
|
119
119
|
*/
|
|
120
120
|
function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve }) {
|
|
121
121
|
if (id === undefined) {
|
|
@@ -160,7 +160,7 @@ function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve
|
|
|
160
160
|
* @param resolve - Variable resolve mode
|
|
161
161
|
* @param identifier - Identifier to resolve
|
|
162
162
|
* @param use - Environment to use
|
|
163
|
-
* @param graph -
|
|
163
|
+
* @param graph - dataflow graph
|
|
164
164
|
* @param idMap - id map of Dataflow graph
|
|
165
165
|
* @returns Value of Identifier or Top
|
|
166
166
|
*/
|
|
@@ -333,8 +333,8 @@ function trackAliasesInGraph(id, graph, idMap) {
|
|
|
333
333
|
*
|
|
334
334
|
* Resolve an Identifier to a constant, if the identifier is a constant
|
|
335
335
|
*
|
|
336
|
-
* @param name
|
|
337
|
-
* @param environment
|
|
336
|
+
* @param name - Identifier to resolve
|
|
337
|
+
* @param environment - Environment to use
|
|
338
338
|
* @returns Value of Constant or Top
|
|
339
339
|
*/
|
|
340
340
|
function resolveToConstants(name, environment) {
|
|
@@ -59,7 +59,7 @@ function resolveNode(resolve, a, env, graph, map) {
|
|
|
59
59
|
else {
|
|
60
60
|
return r_value_2.Top;
|
|
61
61
|
}
|
|
62
|
-
if (Object.
|
|
62
|
+
if (Object.hasOwn(built_in_1.BuiltInEvalHandlerMapper, builtInName)) {
|
|
63
63
|
const handler = built_in_1.BuiltInEvalHandlerMapper[builtInName];
|
|
64
64
|
return handler(resolve, a, env, graph, map);
|
|
65
65
|
}
|
package/dataflow/extractor.js
CHANGED
|
@@ -20,6 +20,7 @@ const extract_cfg_1 = require("../control-flow/extract-cfg");
|
|
|
20
20
|
const edge_1 = require("./graph/edge");
|
|
21
21
|
const identify_link_to_last_call_relation_1 = require("../queries/catalog/call-context-query/identify-link-to-last-call-relation");
|
|
22
22
|
const built_in_function_definition_1 = require("./internal/process/functions/call/built-in/built-in-function-definition");
|
|
23
|
+
const built_in_config_1 = require("./environments/built-in-config");
|
|
23
24
|
/**
|
|
24
25
|
* The best friend of {@link produceDataFlowGraph} and {@link processDataflowFor}.
|
|
25
26
|
* Maps every {@link RType} in the normalized AST to a processor.
|
|
@@ -89,10 +90,14 @@ function produceDataFlowGraph(parser, request, completeAst, config) {
|
|
|
89
90
|
else {
|
|
90
91
|
firstRequest = request;
|
|
91
92
|
}
|
|
93
|
+
const builtInsConfig = config.semantics.environment.overwriteBuiltIns;
|
|
94
|
+
const builtIns = (0, built_in_config_1.getBuiltInDefinitions)(builtInsConfig.definitions, builtInsConfig.loadDefaults);
|
|
95
|
+
const env = (0, environment_1.initializeCleanEnvironments)(builtIns.builtInMemory);
|
|
92
96
|
const dfData = {
|
|
93
97
|
parser,
|
|
94
98
|
completeAst,
|
|
95
|
-
environment:
|
|
99
|
+
environment: env,
|
|
100
|
+
builtInEnvironment: env.current.parent,
|
|
96
101
|
processors: exports.processors,
|
|
97
102
|
currentRequest: firstRequest,
|
|
98
103
|
controlDependencies: undefined,
|
|
@@ -2,7 +2,7 @@ import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-i
|
|
|
2
2
|
import type { AstIdMap } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
3
3
|
import type { DataflowFunctionFlowInformation, FunctionArgument } from './graph';
|
|
4
4
|
import { DataflowGraph } from './graph';
|
|
5
|
-
import type { REnvironmentInformation } from '../environments/environment';
|
|
5
|
+
import type { IEnvironment, REnvironmentInformation } from '../environments/environment';
|
|
6
6
|
import type { DataflowGraphVertexAstLink, DataflowGraphVertexUse, FunctionOriginInformation } from './vertex';
|
|
7
7
|
import type { ControlDependency } from '../info';
|
|
8
8
|
import type { LinkTo } from '../../queries/catalog/call-context-query/call-context-query-format';
|
|
@@ -29,6 +29,7 @@ export declare class DataflowGraphBuilder extends DataflowGraph {
|
|
|
29
29
|
*/
|
|
30
30
|
defineFunction(id: NodeId, exitPoints: readonly NodeId[], subflow: DataflowFunctionFlowInformation, info?: {
|
|
31
31
|
environment?: REnvironmentInformation;
|
|
32
|
+
builtInEnvironment?: IEnvironment;
|
|
32
33
|
controlDependencies?: ControlDependency[];
|
|
33
34
|
}, asRoot?: boolean): this;
|
|
34
35
|
/**
|
|
@@ -46,6 +47,7 @@ export declare class DataflowGraphBuilder extends DataflowGraph {
|
|
|
46
47
|
reads?: readonly NodeId[];
|
|
47
48
|
onlyBuiltIn?: boolean;
|
|
48
49
|
environment?: REnvironmentInformation;
|
|
50
|
+
builtInEnvironment?: IEnvironment;
|
|
49
51
|
controlDependencies?: ControlDependency[];
|
|
50
52
|
origin?: FunctionOriginInformation[];
|
|
51
53
|
link?: DataflowGraphVertexAstLink;
|
|
@@ -160,7 +160,7 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
|
|
|
160
160
|
*
|
|
161
161
|
* @see #edges
|
|
162
162
|
*/
|
|
163
|
-
vertices(includeDefinedFunctions: boolean):
|
|
163
|
+
vertices(includeDefinedFunctions: boolean): MapIterator<[NodeId, Vertex]>;
|
|
164
164
|
/**
|
|
165
165
|
* @returns the ids of all edges in the graph together with their edge information
|
|
166
166
|
*
|
|
@@ -231,5 +231,6 @@ export interface IEnvironmentJson {
|
|
|
231
231
|
readonly id: number;
|
|
232
232
|
parent: IEnvironmentJson;
|
|
233
233
|
memory: Record<Identifier, IdentifierDefinition[]>;
|
|
234
|
+
builtInEnv: true | undefined;
|
|
234
235
|
}
|
|
235
236
|
export {};
|
package/dataflow/graph/graph.js
CHANGED
|
@@ -394,11 +394,15 @@ function envFromJson(json) {
|
|
|
394
394
|
for (const [key, value] of Object.entries(json.memory)) {
|
|
395
395
|
memory.set(key, value);
|
|
396
396
|
}
|
|
397
|
-
|
|
397
|
+
const obj = {
|
|
398
398
|
id: json.id,
|
|
399
399
|
parent: parent,
|
|
400
400
|
memory
|
|
401
401
|
};
|
|
402
|
+
if (json.builtInEnv) {
|
|
403
|
+
obj.builtInEnv = true;
|
|
404
|
+
}
|
|
405
|
+
return obj;
|
|
402
406
|
}
|
|
403
407
|
function renvFromJson(json) {
|
|
404
408
|
const current = envFromJson(json.current);
|
package/dataflow/info.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ export interface DataflowInformation extends DataflowCfgInformation {
|
|
|
109
109
|
*
|
|
110
110
|
* @see {@link DataflowInformation}
|
|
111
111
|
*/
|
|
112
|
-
export declare function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'completeAst'>): DataflowInformation;
|
|
112
|
+
export declare function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'builtInEnvironment' | 'completeAst'>): DataflowInformation;
|
|
113
113
|
/**
|
|
114
114
|
* Checks whether the given control dependencies are exhaustive (i.e. if for every control dependency on a boolean,
|
|
115
115
|
* the list contains a dependency on the `true` and on the `false` case).
|
|
@@ -25,7 +25,7 @@ const built_in_1 = require("../environments/built-in");
|
|
|
25
25
|
const prefix_1 = require("../../util/prefix");
|
|
26
26
|
function findNonLocalReads(graph, ignore) {
|
|
27
27
|
const ignores = new Set(ignore.map(i => i.nodeId));
|
|
28
|
-
const ids = new Set(
|
|
28
|
+
const ids = new Set(graph.vertices(true)
|
|
29
29
|
.filter(([_, info]) => info.tag === vertex_1.VertexType.Use || info.tag === vertex_1.VertexType.FunctionCall)
|
|
30
30
|
.map(([id, _]) => id));
|
|
31
31
|
/* find all variable use ids which do not link to a given id */
|
|
@@ -74,27 +74,27 @@ function produceNameSharedIdMap(references) {
|
|
|
74
74
|
}
|
|
75
75
|
function linkArgumentsOnCall(args, params, graph) {
|
|
76
76
|
const nameArgMap = new Map(args.filter(graph_1.isNamedArgument).map(a => [a.name, a]));
|
|
77
|
-
const nameParamMap = new Map(params.filter(p => p
|
|
77
|
+
const nameParamMap = new Map(params.filter(p => p?.name?.content !== undefined).map(p => [p.name.content, p]));
|
|
78
78
|
const specialDotParameter = params.find(p => p.special);
|
|
79
79
|
// all parameters matched by name
|
|
80
80
|
const matchedParameters = new Set();
|
|
81
81
|
// first map names
|
|
82
82
|
for (const [name, arg] of nameArgMap) {
|
|
83
|
-
const pmatchName = (0, prefix_1.findByPrefixIfUnique)(name,
|
|
83
|
+
const pmatchName = (0, prefix_1.findByPrefixIfUnique)(name, nameParamMap.keys()) ?? name;
|
|
84
84
|
const param = nameParamMap.get(pmatchName);
|
|
85
|
-
if (param
|
|
85
|
+
if (param?.name) {
|
|
86
86
|
logger_1.dataflowLogger.trace(`mapping named argument "${name}" to parameter "${param.name.content}"`);
|
|
87
87
|
graph.addEdge(arg.nodeId, param.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
88
88
|
graph.addEdge(param.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
89
89
|
matchedParameters.add(name);
|
|
90
90
|
}
|
|
91
|
-
else if (specialDotParameter
|
|
91
|
+
else if (specialDotParameter?.name) {
|
|
92
92
|
logger_1.dataflowLogger.trace(`mapping named argument "${name}" to dot-dot-dot parameter`);
|
|
93
93
|
graph.addEdge(arg.nodeId, specialDotParameter.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
94
94
|
graph.addEdge(specialDotParameter.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
const remainingParameter = params.filter(p => !p
|
|
97
|
+
const remainingParameter = params.filter(p => !p?.name || !matchedParameters.has(p.name.content));
|
|
98
98
|
const remainingArguments = args.filter(a => !(0, graph_1.isNamedArgument)(a));
|
|
99
99
|
for (let i = 0; i < remainingArguments.length; i++) {
|
|
100
100
|
const arg = remainingArguments[i];
|
|
@@ -169,14 +169,14 @@ function linkFunctionCall(graph, id, info, idMap, thisGraph, calledFunctionDefin
|
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
171
|
const readBits = edge_1.EdgeType.Reads | edge_1.EdgeType.Calls;
|
|
172
|
-
const functionDefinitionReadIds =
|
|
172
|
+
const functionDefinitionReadIds = edges.entries().filter(([_, e]) => (0, edge_1.edgeDoesNotIncludeType)(e.types, edge_1.EdgeType.Argument)
|
|
173
173
|
&& (0, edge_1.edgeIncludesType)(e.types, readBits)).map(([target, _]) => target);
|
|
174
174
|
const functionDefs = getAllLinkedFunctionDefinitions(new Set(functionDefinitionReadIds), graph)[0];
|
|
175
175
|
for (const def of functionDefs.values()) {
|
|
176
176
|
(0, assert_1.guard)(def.tag === vertex_1.VertexType.FunctionDefinition, () => `expected function definition, but got ${def.tag}`);
|
|
177
177
|
linkFunctionCallWithSingleTarget(graph, def, info, idMap);
|
|
178
178
|
}
|
|
179
|
-
if (thisGraph.isRoot(id)) {
|
|
179
|
+
if (thisGraph.isRoot(id) && functionDefs.size > 0) {
|
|
180
180
|
calledFunctionDefinitions.push({ functionCall: id, called: [...functionDefs.values()] });
|
|
181
181
|
}
|
|
182
182
|
}
|
|
@@ -189,7 +189,7 @@ function linkFunctionCall(graph, id, info, idMap, thisGraph, calledFunctionDefin
|
|
|
189
189
|
* @param thisGraph - The graph to search for function calls in
|
|
190
190
|
*/
|
|
191
191
|
function linkFunctionCalls(graph, idMap, thisGraph) {
|
|
192
|
-
const functionCalls =
|
|
192
|
+
const functionCalls = thisGraph.vertices(true)
|
|
193
193
|
.filter(([_, info]) => info.tag === vertex_1.VertexType.FunctionCall);
|
|
194
194
|
const calledFunctionDefinitions = [];
|
|
195
195
|
for (const [id, info] of functionCalls) {
|
|
@@ -112,7 +112,7 @@ function processNumberBasedAccess(data, name, args, rootId, config, head) {
|
|
|
112
112
|
data.environment.current.memory.set(':=', existing);
|
|
113
113
|
}
|
|
114
114
|
if (head.value && outInfo.definitionRootNodes.length > 0) {
|
|
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, data
|
|
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, data);
|
|
116
116
|
}
|
|
117
117
|
if (data.flowrConfig.solver.pointerTracking) {
|
|
118
118
|
referenceAccessedIndices(args, data, fnCall, rootId, true);
|