@eagleoutice/flowr 2.10.3 → 2.10.5
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 +43 -26
- package/abstract-interpretation/absint-visitor.d.ts +17 -21
- package/abstract-interpretation/absint-visitor.js +47 -48
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -3
- package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -1
- package/abstract-interpretation/data-frame/shape-inference.js +5 -4
- package/abstract-interpretation/domains/abstract-domain.d.ts +17 -16
- package/abstract-interpretation/domains/abstract-domain.js +25 -27
- package/abstract-interpretation/domains/bounded-set-domain.js +1 -1
- package/abstract-interpretation/domains/multi-value-state-domain.d.ts +32 -0
- package/abstract-interpretation/domains/multi-value-state-domain.js +60 -0
- package/abstract-interpretation/domains/partial-product-domain.d.ts +43 -0
- package/abstract-interpretation/domains/partial-product-domain.js +163 -0
- package/abstract-interpretation/domains/product-domain.d.ts +2 -29
- package/abstract-interpretation/domains/product-domain.js +6 -123
- package/abstract-interpretation/domains/set-range-domain.js +3 -3
- package/abstract-interpretation/domains/set-upper-bound-domain.js +1 -1
- package/abstract-interpretation/domains/singleton-domain.js +1 -1
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +13 -28
- package/abstract-interpretation/domains/state-abstract-domain.js +16 -38
- package/abstract-interpretation/domains/state-domain-like.d.ts +36 -0
- package/abstract-interpretation/domains/state-domain-like.js +3 -0
- package/cli/flowr.js +11 -1
- package/config.d.ts +7 -0
- package/config.js +22 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +4 -0
- package/control-flow/semantic-cfg-guided-visitor.js +20 -32
- package/dataflow/environments/default-builtin-config.d.ts +10 -0
- package/dataflow/environments/default-builtin-config.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +2 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +38 -21
- package/documentation/doc-readme.js +13 -2
- package/documentation/wiki-absint.d.ts +1 -2
- package/documentation/wiki-absint.js +34 -10
- package/documentation/wiki-analyzer.js +3 -4
- package/documentation/wiki-interface.js +21 -16
- package/documentation/wiki-linter.js +1 -1
- package/linter/linter-rules.d.ts +12 -12
- package/linter/linter-rules.js +2 -2
- package/linter/rules/network-functions.d.ts +1 -1
- package/linter/rules/network-functions.js +8 -2
- package/linter/rules/problematic-inputs.d.ts +43 -0
- package/linter/rules/problematic-inputs.js +110 -0
- package/linter/rules/seeded-randomness.d.ts +1 -1
- package/linter/rules/seeded-randomness.js +8 -1
- package/package.json +4 -4
- package/project/flowr-analyzer-builder.d.ts +6 -3
- package/project/flowr-analyzer-builder.js +12 -5
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.d.ts +4 -3
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +17 -4
- package/project/plugins/flowr-analyzer-plugin.d.ts +1 -1
- package/project/plugins/flowr-analyzer-plugin.js +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-format.js +1 -2
- package/queries/catalog/dependencies-query/function-info/read-functions.js +6 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +7 -0
- package/queries/catalog/input-sources-query/input-source-functions.d.ts +6 -0
- package/queries/catalog/input-sources-query/input-source-functions.js +50 -0
- package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +1 -1
- package/queries/catalog/input-sources-query/input-sources-query-executor.js +19 -31
- package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +2 -1
- package/queries/catalog/input-sources-query/input-sources-query-format.js +26 -8
- package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +33 -28
- package/queries/catalog/input-sources-query/simple-input-classifier.js +192 -99
- package/r-bridge/lang-4.x/ast/model/model.d.ts +4 -4
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +3 -3
- package/util/record.d.ts +18 -3
- package/util/record.js +22 -1
- package/util/version.js +1 -1
- package/linter/rules/problematic-eval.d.ts +0 -44
- package/linter/rules/problematic-eval.js +0 -83
- package/project/plugins/flowr-analyzer-plugin-defaults.d.ts +0 -5
- package/project/plugins/flowr-analyzer-plugin-defaults.js +0 -37
|
@@ -2,19 +2,20 @@ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/nod
|
|
|
2
2
|
import type { DataflowGraph } from '../../../dataflow/graph/graph';
|
|
3
3
|
import type { MergeableRecord } from '../../../util/objects';
|
|
4
4
|
import { Identifier } from '../../../dataflow/environments/identifier';
|
|
5
|
+
import type { FlowrSearchLike } from '../../../search/flowr-search-builder';
|
|
5
6
|
/**
|
|
6
7
|
* Lattice flattening until we have a taint engine :)
|
|
7
8
|
* Please note that the classifier considers this basis with a set-lift,
|
|
8
9
|
* joining differing lattice elements.
|
|
9
10
|
*
|
|
10
11
|
*```
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*[Param] [File] [Net]
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* [ Unknown ]
|
|
13
|
+
* |
|
|
14
|
+
* [Param] [File] [Net], ...
|
|
15
|
+
* |
|
|
16
|
+
* [ DerivedConstant ]
|
|
17
|
+
* |
|
|
18
|
+
* [ Constant ]
|
|
18
19
|
*```
|
|
19
20
|
*
|
|
20
21
|
*/
|
|
@@ -23,6 +24,14 @@ export declare enum InputType {
|
|
|
23
24
|
File = "file",
|
|
24
25
|
Network = "net",
|
|
25
26
|
Random = "rand",
|
|
27
|
+
/** Calls to system/system2 and similar */
|
|
28
|
+
System = "system",
|
|
29
|
+
/** Calls to .C / Fortran interfaces (foreign function interfaces) */
|
|
30
|
+
Ffi = "ffi",
|
|
31
|
+
/** Language objects (quote/substitute/etc.) */
|
|
32
|
+
Lang = "lang",
|
|
33
|
+
/** Global options / option accessors (options, getOption) */
|
|
34
|
+
Options = "options",
|
|
26
35
|
Constant = "const",
|
|
27
36
|
/** Read from environment/call scope */
|
|
28
37
|
Scope = "scope",
|
|
@@ -40,16 +49,24 @@ export declare enum InputTraceType {
|
|
|
40
49
|
/** Not fully known origin */
|
|
41
50
|
Unknown = "unknown"
|
|
42
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Scalar R constant values representable in TypeScript.
|
|
54
|
+
* `null` corresponds to R's `NULL`.
|
|
55
|
+
* NA values are not included (they have no direct TS equivalent).
|
|
56
|
+
*/
|
|
57
|
+
export type ConstantValue = string | number | boolean | null;
|
|
43
58
|
/**
|
|
44
59
|
* Object attached to an input source
|
|
45
60
|
* @see {@link InputSources}
|
|
46
61
|
*/
|
|
47
62
|
export interface InputSource extends MergeableRecord {
|
|
48
63
|
id: NodeId;
|
|
49
|
-
|
|
64
|
+
types: InputType[];
|
|
50
65
|
trace: InputTraceType;
|
|
51
66
|
/** if the trace is affected by control dependencies, they are classified too, this is a duplicate free array */
|
|
52
67
|
cds?: InputType[];
|
|
68
|
+
/** the concrete scalar value when the source is a constant or a pure alias of one */
|
|
69
|
+
value?: ConstantValue;
|
|
53
70
|
}
|
|
54
71
|
/**
|
|
55
72
|
* Map of input sources, keyed by the node id of the input source. Each input source is classified with an {@link InputSource} object.
|
|
@@ -59,34 +76,22 @@ export type InputSources = InputSource[];
|
|
|
59
76
|
* This is either an {@link NodeId|id} of a known functions all of that category (e.g., you can issue a dependencies query before and then pass all
|
|
60
77
|
* identified ids to this query here).
|
|
61
78
|
*/
|
|
62
|
-
export type
|
|
79
|
+
export type InputClassifierFunctionIdentifiers = readonly (Identifier | NodeId)[];
|
|
63
80
|
/**
|
|
64
|
-
* For the specifications of `
|
|
81
|
+
* For the specifications of `pure` etc. please have a look at {@link InputClassifierFunctionIdentifiers}.
|
|
65
82
|
*/
|
|
66
|
-
export interface InputClassifierConfig extends
|
|
83
|
+
export interface InputClassifierConfig<Functions extends InputClassifierFunctionIdentifiers | FlowrSearchLike = readonly Identifier[] | FlowrSearchLike> extends Partial<Record<InputType, Functions>> {
|
|
67
84
|
/**
|
|
68
85
|
* Functions which are considered to be pure (i.e., deterministic, trusted, safe, idempotent on the lub of the input types)
|
|
69
86
|
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Functions that read from the network
|
|
73
|
-
*/
|
|
74
|
-
networkFns: readonly InputClassifierFunctionIdentifier[];
|
|
75
|
-
/**
|
|
76
|
-
* Functions that produce a random value
|
|
77
|
-
* Note: may need to check with respect to seeded randomness
|
|
78
|
-
*/
|
|
79
|
-
randomFns: readonly InputClassifierFunctionIdentifier[];
|
|
80
|
-
/**
|
|
81
|
-
* Functions that read from the file system
|
|
82
|
-
*/
|
|
83
|
-
readFileFns: readonly InputClassifierFunctionIdentifier[];
|
|
87
|
+
[InputTraceType.Pure]?: Functions;
|
|
84
88
|
}
|
|
85
89
|
/**
|
|
86
90
|
* Takes the given id which is expected to either be:
|
|
87
91
|
* - a function call - in this case all arguments are considered to be inputs (additionally to all read edges from the function call in the dataflow graph)
|
|
88
|
-
* - anything else - in that case the node itself is considered as an "input" - please note that in these scenarios the *return* value will only contain one mapping - that for the id you
|
|
92
|
+
* - anything else - in that case the node itself is considered as an "input" - please note that in these scenarios the *return* value will only contain one mapping - that for the id you passed in.
|
|
89
93
|
*
|
|
90
|
-
* This method traces the dependencies in the dataflow graph using the specification of functions passed in
|
|
94
|
+
* This method traces the dependencies in the dataflow graph using the specification of functions passed in.
|
|
95
|
+
* For the scope escape analysis, pass on the full, non-reduced DFG as `fullDfg`.
|
|
91
96
|
*/
|
|
92
|
-
export declare function classifyInput(id: NodeId, dfg: DataflowGraph, config: InputClassifierConfig): InputSources;
|
|
97
|
+
export declare function classifyInput(id: NodeId, dfg: DataflowGraph, config: InputClassifierConfig<InputClassifierFunctionIdentifiers>, fullDfg?: DataflowGraph): InputSources;
|
|
@@ -6,17 +6,110 @@ const graph_1 = require("../../../dataflow/graph/graph");
|
|
|
6
6
|
const objects_1 = require("../../../util/objects");
|
|
7
7
|
const vertex_1 = require("../../../dataflow/graph/vertex");
|
|
8
8
|
const df_helper_1 = require("../../../dataflow/graph/df-helper");
|
|
9
|
+
const edge_1 = require("../../../dataflow/graph/edge");
|
|
9
10
|
const identifier_1 = require("../../../dataflow/environments/identifier");
|
|
10
11
|
const assert_1 = require("../../../util/assert");
|
|
11
12
|
const arrays_1 = require("../../../util/collections/arrays");
|
|
12
13
|
const built_in_proc_name_1 = require("../../../dataflow/environments/built-in-proc-name");
|
|
14
|
+
const record_1 = require("../../../util/record");
|
|
15
|
+
const r_number_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-number");
|
|
16
|
+
const r_string_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-string");
|
|
17
|
+
const r_logical_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-logical");
|
|
18
|
+
const r_symbol_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol");
|
|
19
|
+
const convert_values_1 = require("../../../r-bridge/lang-4.x/convert-values");
|
|
20
|
+
function isConstantLike(type) {
|
|
21
|
+
return type === InputType.Constant || type === InputType.DerivedConstant;
|
|
22
|
+
}
|
|
23
|
+
/** Returns the common value shared by all defined entries, or `undefined` if they disagree or all are `undefined`. */
|
|
24
|
+
function singleValue(values) {
|
|
25
|
+
let result;
|
|
26
|
+
let seen = false;
|
|
27
|
+
for (const v of values) {
|
|
28
|
+
if (v === undefined) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
if (!seen) {
|
|
32
|
+
result = v;
|
|
33
|
+
seen = true;
|
|
34
|
+
}
|
|
35
|
+
else if (v !== result) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Accumulates types, control-dependency types, values, and purity while traversing origin
|
|
43
|
+
* chains. Call {@link build} to produce the resulting {@link InputSource}.
|
|
44
|
+
*/
|
|
45
|
+
class ClassificationAccumulator {
|
|
46
|
+
types = [];
|
|
47
|
+
cds = [];
|
|
48
|
+
values = [];
|
|
49
|
+
allPure = true;
|
|
50
|
+
merge(c) {
|
|
51
|
+
this.types.push(...c.types);
|
|
52
|
+
this.values.push(c.value);
|
|
53
|
+
if (c.cds) {
|
|
54
|
+
this.cds.push(...c.cds);
|
|
55
|
+
}
|
|
56
|
+
if (c.trace !== InputTraceType.Pure) {
|
|
57
|
+
this.allPure = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
pushUnknown() {
|
|
61
|
+
this.types.push(InputType.Unknown);
|
|
62
|
+
this.values.push(undefined);
|
|
63
|
+
}
|
|
64
|
+
build(id) {
|
|
65
|
+
const types = this.types.length === 0 ? [InputType.Unknown] : (0, arrays_1.uniqueArray)(this.types);
|
|
66
|
+
const trace = this.allPure ? InputTraceType.Pure : InputTraceType.Alias;
|
|
67
|
+
const src = { id, types, trace };
|
|
68
|
+
const cds = this.cds.length === 0 ? undefined : (0, arrays_1.uniqueArray)(this.cds);
|
|
69
|
+
if (cds) {
|
|
70
|
+
src.cds = cds;
|
|
71
|
+
}
|
|
72
|
+
if (types.every(isConstantLike)) {
|
|
73
|
+
const v = singleValue(this.values);
|
|
74
|
+
if (v !== undefined) {
|
|
75
|
+
src.value = v;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return src;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
13
81
|
class InputClassifier {
|
|
14
82
|
dfg;
|
|
15
83
|
config;
|
|
16
84
|
cache = new Map();
|
|
17
|
-
|
|
85
|
+
fullDfg;
|
|
86
|
+
constructor(dfg, config, fullDfg) {
|
|
18
87
|
this.dfg = dfg;
|
|
19
88
|
this.config = config;
|
|
89
|
+
this.fullDfg = fullDfg;
|
|
90
|
+
}
|
|
91
|
+
isDefinedByOnCall(id) {
|
|
92
|
+
const out = (this.fullDfg ?? this.dfg).outgoingEdges(id) ?? new Map();
|
|
93
|
+
return out.values().some(e => edge_1.DfEdge.includesType(e, edge_1.EdgeType.DefinedByOnCall));
|
|
94
|
+
}
|
|
95
|
+
extractConstantValue(id) {
|
|
96
|
+
const node = this.dfg.idMap?.get(id);
|
|
97
|
+
if (node === undefined) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
if (r_number_1.RNumber.is(node)) {
|
|
101
|
+
return node.content.num;
|
|
102
|
+
}
|
|
103
|
+
if (r_string_1.RString.is(node)) {
|
|
104
|
+
return node.content.str;
|
|
105
|
+
}
|
|
106
|
+
if (r_logical_1.RLogical.is(node)) {
|
|
107
|
+
return node.content;
|
|
108
|
+
}
|
|
109
|
+
if (r_symbol_1.RSymbol.is(node) && node.content === convert_values_1.RNull) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
20
113
|
}
|
|
21
114
|
classifyEntry(vertex) {
|
|
22
115
|
const cached = this.cache.get(vertex.id);
|
|
@@ -24,10 +117,16 @@ class InputClassifier {
|
|
|
24
117
|
return cached;
|
|
25
118
|
}
|
|
26
119
|
// insert temporary unknown to break cycles
|
|
27
|
-
this.cache.set(vertex.id, { id: vertex.id,
|
|
120
|
+
this.cache.set(vertex.id, { id: vertex.id, types: [InputType.Unknown], trace: InputTraceType.Unknown });
|
|
28
121
|
switch (vertex.tag) {
|
|
29
|
-
case vertex_1.VertexType.Value:
|
|
30
|
-
|
|
122
|
+
case vertex_1.VertexType.Value: {
|
|
123
|
+
const src = { id: vertex.id, types: [InputType.Constant], trace: InputTraceType.Unknown };
|
|
124
|
+
const v = this.extractConstantValue(vertex.id);
|
|
125
|
+
if (v !== undefined) {
|
|
126
|
+
src.value = v;
|
|
127
|
+
}
|
|
128
|
+
return this.classifyCdsAndReturn(vertex, src);
|
|
129
|
+
}
|
|
31
130
|
case vertex_1.VertexType.FunctionCall:
|
|
32
131
|
return this.classifyFunctionCall(vertex);
|
|
33
132
|
case vertex_1.VertexType.VariableDefinition:
|
|
@@ -35,7 +134,7 @@ class InputClassifier {
|
|
|
35
134
|
case vertex_1.VertexType.Use:
|
|
36
135
|
return this.classifyVariable(vertex);
|
|
37
136
|
default:
|
|
38
|
-
return this.classifyCdsAndReturn(vertex, { id: vertex.id,
|
|
137
|
+
return this.classifyCdsAndReturn(vertex, { id: vertex.id, types: [InputType.Unknown], trace: InputTraceType.Unknown });
|
|
39
138
|
}
|
|
40
139
|
}
|
|
41
140
|
classifyFunctionCall(call) {
|
|
@@ -57,20 +156,18 @@ class InputClassifier {
|
|
|
57
156
|
}
|
|
58
157
|
}
|
|
59
158
|
}
|
|
60
|
-
if (!matchesList(call, this.config.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
else if (matchesList(call, this.config.randomFns)) {
|
|
68
|
-
return this.classifyCdsAndReturn(call, { id: call.id, type: [InputType.Random], trace: InputTraceType.Unknown });
|
|
159
|
+
if (!matchesList(call, this.config.pure)) {
|
|
160
|
+
const types = [];
|
|
161
|
+
for (const [type, entry] of record_1.Record.entries(this.config)) {
|
|
162
|
+
if (record_1.Record.values(InputType).includes(type) && matchesList(call, entry)) {
|
|
163
|
+
types.push(type);
|
|
164
|
+
}
|
|
69
165
|
}
|
|
70
|
-
|
|
166
|
+
if (types.length === 0) {
|
|
71
167
|
// if it is not pure, we cannot classify based on the inputs, in that case we do not know!
|
|
72
|
-
|
|
168
|
+
types.push(InputType.Unknown);
|
|
73
169
|
}
|
|
170
|
+
return this.classifyCdsAndReturn(call, { id: call.id, types, trace: InputTraceType.Unknown });
|
|
74
171
|
}
|
|
75
172
|
// Otherwise, classify by arguments; pure functions get Known/Pure handling
|
|
76
173
|
const argTypes = [];
|
|
@@ -91,111 +188,98 @@ class InputClassifier {
|
|
|
91
188
|
}
|
|
92
189
|
const classified = this.classifyEntry(argVtx);
|
|
93
190
|
// collect all observed types from this argument
|
|
94
|
-
argTypes.push(...classified.
|
|
191
|
+
argTypes.push(...classified.types);
|
|
95
192
|
if (classified.cds) {
|
|
96
193
|
cdTypes.push(...classified.cds);
|
|
97
194
|
}
|
|
98
195
|
}
|
|
99
196
|
const cds = cdTypes.length > 0 ? (0, arrays_1.uniqueArray)(cdTypes) : undefined;
|
|
100
197
|
// all arguments only contain constant-like types -> derived constant
|
|
101
|
-
const allConstLike = argTypes.length > 0 && argTypes.every(
|
|
198
|
+
const allConstLike = argTypes.length > 0 && argTypes.every(isConstantLike);
|
|
102
199
|
if (allConstLike) {
|
|
103
|
-
return this.classifyCdsAndReturn(call, (0, objects_1.compactRecord)({ id: call.id,
|
|
200
|
+
return this.classifyCdsAndReturn(call, (0, objects_1.compactRecord)({ id: call.id, types: [InputType.DerivedConstant], trace: InputTraceType.Pure, cds }));
|
|
104
201
|
}
|
|
105
202
|
argTypes.push(InputType.DerivedConstant);
|
|
106
|
-
return this.classifyCdsAndReturn(call, (0, objects_1.compactRecord)({ id: call.id,
|
|
203
|
+
return this.classifyCdsAndReturn(call, (0, objects_1.compactRecord)({ id: call.id, types: (0, arrays_1.uniqueArray)(argTypes), trace: InputTraceType.Known, cds }));
|
|
107
204
|
}
|
|
108
205
|
classifyVariable(vtx) {
|
|
109
206
|
const origins = df_helper_1.Dataflow.origin(this.dfg, vtx.id);
|
|
110
207
|
if (origins === undefined) {
|
|
111
|
-
return this.classifyCdsAndReturn(vtx, { id: vtx.id,
|
|
208
|
+
return this.classifyCdsAndReturn(vtx, { id: vtx.id, types: this.isDefinedByOnCall(vtx.id) ? [InputType.Scope] : [InputType.Unknown], trace: InputTraceType.Unknown });
|
|
112
209
|
}
|
|
113
|
-
const
|
|
114
|
-
const cds = [];
|
|
115
|
-
let allPure = true;
|
|
210
|
+
const acc = new ClassificationAccumulator();
|
|
116
211
|
for (const o of origins) {
|
|
117
212
|
if (o.type === 4 /* OriginType.ConstantOrigin */) {
|
|
118
|
-
types.push(InputType.DerivedConstant);
|
|
119
|
-
|
|
213
|
+
acc.types.push(InputType.DerivedConstant);
|
|
214
|
+
acc.values.push(this.extractConstantValue(o.id));
|
|
120
215
|
}
|
|
121
|
-
if (o.type === 0 /* OriginType.ReadVariableOrigin */ || o.type === 1 /* OriginType.WriteVariableOrigin */) {
|
|
122
|
-
|
|
123
|
-
if (v) {
|
|
124
|
-
// if this is a variable definition that is a parameter, classify as Parameter
|
|
125
|
-
if (v.tag === vertex_1.VertexType.VariableDefinition && this.dfg.idMap?.get(v.id)?.info.role === "param-n" /* RoleInParent.ParameterName */) {
|
|
126
|
-
types.push(InputType.Parameter);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
const c = this.classifyEntry(v);
|
|
130
|
-
types.push(...c.type);
|
|
131
|
-
if (c.cds) {
|
|
132
|
-
cds.push(...c.cds);
|
|
133
|
-
}
|
|
134
|
-
if (c.trace !== InputTraceType.Pure) {
|
|
135
|
-
allPure = false;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
types.push(InputType.Unknown);
|
|
140
|
-
}
|
|
141
|
-
continue;
|
|
216
|
+
else if (o.type === 0 /* OriginType.ReadVariableOrigin */ || o.type === 1 /* OriginType.WriteVariableOrigin */) {
|
|
217
|
+
this.classifyVariableOrigin(o.id, acc);
|
|
142
218
|
}
|
|
143
|
-
if (o.type === 2 /* OriginType.FunctionCallOrigin */ || o.type === 3 /* OriginType.BuiltInFunctionOrigin */) {
|
|
144
|
-
|
|
145
|
-
if (v) {
|
|
146
|
-
const c = this.classifyEntry(v);
|
|
147
|
-
types.push(...c.type);
|
|
148
|
-
if (c.cds) {
|
|
149
|
-
cds.push(...c.cds);
|
|
150
|
-
}
|
|
151
|
-
if (c.trace !== InputTraceType.Pure) {
|
|
152
|
-
allPure = false;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
types.push(InputType.Unknown);
|
|
157
|
-
}
|
|
158
|
-
continue;
|
|
219
|
+
else if (o.type === 2 /* OriginType.FunctionCallOrigin */ || o.type === 3 /* OriginType.BuiltInFunctionOrigin */) {
|
|
220
|
+
this.classifyByVertex(o.id, acc);
|
|
159
221
|
}
|
|
160
|
-
|
|
161
|
-
|
|
222
|
+
else {
|
|
223
|
+
acc.pushUnknown();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return this.classifyCdsAndReturn(vtx, acc.build(vtx.id));
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Resolves a variable definition or use origin, handling the special cases of
|
|
230
|
+
* scope-escaped variables (DefinedByOnCall) and parameter definitions.
|
|
231
|
+
*/
|
|
232
|
+
classifyVariableOrigin(definitionId, acc) {
|
|
233
|
+
const v = this.dfg.getVertex(definitionId);
|
|
234
|
+
if (!v) {
|
|
235
|
+
acc.pushUnknown();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// if the referenced definition is linked via defined-by-on-call to another
|
|
239
|
+
// id (e.g., a parameter linked to a caller argument), mark it as a Scope origin
|
|
240
|
+
if (this.isDefinedByOnCall(v.id)) {
|
|
241
|
+
acc.types.push(InputType.Scope);
|
|
242
|
+
acc.values.push(undefined);
|
|
243
|
+
acc.allPure = false;
|
|
244
|
+
}
|
|
245
|
+
// if this is a variable definition that is a parameter, classify as Parameter
|
|
246
|
+
if (v.tag === vertex_1.VertexType.VariableDefinition && this.dfg.idMap?.get(v.id)?.info.role === "param-n" /* RoleInParent.ParameterName */) {
|
|
247
|
+
acc.types.push(InputType.Parameter);
|
|
248
|
+
acc.values.push(undefined);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
acc.merge(this.classifyEntry(v));
|
|
252
|
+
}
|
|
253
|
+
classifyByVertex(id, acc) {
|
|
254
|
+
const v = this.dfg.getVertex(id);
|
|
255
|
+
if (v) {
|
|
256
|
+
acc.merge(this.classifyEntry(v));
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
acc.pushUnknown();
|
|
162
260
|
}
|
|
163
|
-
const t = types.length === 0 ? [InputType.Unknown] : (0, arrays_1.uniqueArray)(types);
|
|
164
|
-
const trace = allPure ? InputTraceType.Pure : InputTraceType.Alias;
|
|
165
|
-
return this.classifyCdsAndReturn(vtx, { id: vtx.id, type: t, trace, cds: cds.length === 0 ? undefined : (0, arrays_1.uniqueArray)(cds) });
|
|
166
261
|
}
|
|
167
262
|
classifyVariableDefinition(vtx) {
|
|
168
263
|
// parameter definitions are classified as Parameter
|
|
169
264
|
if (this.dfg.idMap?.get(vtx.id)?.info.role === "param-n" /* RoleInParent.ParameterName */) {
|
|
170
|
-
return this.classifyCdsAndReturn(vtx, { id: vtx.id,
|
|
265
|
+
return this.classifyCdsAndReturn(vtx, { id: vtx.id, types: [InputType.Parameter], trace: InputTraceType.Unknown });
|
|
171
266
|
}
|
|
172
267
|
const sources = vtx.source;
|
|
173
268
|
if (sources === undefined || sources.length === 0) {
|
|
174
269
|
// fallback to unknown if we cannot find the value
|
|
175
|
-
return this.classifyCdsAndReturn(vtx, { id: vtx.id,
|
|
270
|
+
return this.classifyCdsAndReturn(vtx, { id: vtx.id, types: [InputType.Unknown], trace: InputTraceType.Unknown });
|
|
176
271
|
}
|
|
177
|
-
const
|
|
178
|
-
const cds = [];
|
|
179
|
-
let allPure = true;
|
|
272
|
+
const acc = new ClassificationAccumulator();
|
|
180
273
|
for (const tid of sources) {
|
|
181
274
|
const tv = this.dfg.getVertex(tid);
|
|
182
275
|
if (tv) {
|
|
183
|
-
|
|
184
|
-
types.push(...c.type);
|
|
185
|
-
if (c.cds) {
|
|
186
|
-
cds.push(...c.cds);
|
|
187
|
-
}
|
|
188
|
-
if (c.trace !== InputTraceType.Pure) {
|
|
189
|
-
allPure = false;
|
|
190
|
-
}
|
|
276
|
+
acc.merge(this.classifyEntry(tv));
|
|
191
277
|
}
|
|
192
278
|
else {
|
|
193
|
-
|
|
279
|
+
acc.pushUnknown();
|
|
194
280
|
}
|
|
195
281
|
}
|
|
196
|
-
|
|
197
|
-
const trace = allPure ? InputTraceType.Pure : InputTraceType.Alias;
|
|
198
|
-
return this.classifyCdsAndReturn(vtx, { id: vtx.id, type: t, trace, cds: cds.length === 0 ? undefined : (0, arrays_1.uniqueArray)(cds) });
|
|
282
|
+
return this.classifyCdsAndReturn(vtx, acc.build(vtx.id));
|
|
199
283
|
}
|
|
200
284
|
classifyCdsAndReturn(vtx, src) {
|
|
201
285
|
if (vtx.cds) {
|
|
@@ -205,7 +289,7 @@ class InputClassifier {
|
|
|
205
289
|
return undefined;
|
|
206
290
|
}
|
|
207
291
|
const e = this.classifyEntry(cv);
|
|
208
|
-
return e.cds ? [...e.
|
|
292
|
+
return e.cds ? [...e.types, ...e.cds] : [...e.types];
|
|
209
293
|
}).filter(assert_1.isNotUndefined).concat(src.cds ?? []));
|
|
210
294
|
if (cds.length > 0) {
|
|
211
295
|
src.cds = cds;
|
|
@@ -224,13 +308,13 @@ class InputClassifier {
|
|
|
224
308
|
* joining differing lattice elements.
|
|
225
309
|
*
|
|
226
310
|
*```
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*[Param] [File] [Net]
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
311
|
+
* [ Unknown ]
|
|
312
|
+
* |
|
|
313
|
+
* [Param] [File] [Net], ...
|
|
314
|
+
* |
|
|
315
|
+
* [ DerivedConstant ]
|
|
316
|
+
* |
|
|
317
|
+
* [ Constant ]
|
|
234
318
|
*```
|
|
235
319
|
*
|
|
236
320
|
*/
|
|
@@ -240,6 +324,14 @@ var InputType;
|
|
|
240
324
|
InputType["File"] = "file";
|
|
241
325
|
InputType["Network"] = "net";
|
|
242
326
|
InputType["Random"] = "rand";
|
|
327
|
+
/** Calls to system/system2 and similar */
|
|
328
|
+
InputType["System"] = "system";
|
|
329
|
+
/** Calls to .C / Fortran interfaces (foreign function interfaces) */
|
|
330
|
+
InputType["Ffi"] = "ffi";
|
|
331
|
+
/** Language objects (quote/substitute/etc.) */
|
|
332
|
+
InputType["Lang"] = "lang";
|
|
333
|
+
/** Global options / option accessors (options, getOption) */
|
|
334
|
+
InputType["Options"] = "options";
|
|
243
335
|
InputType["Constant"] = "const";
|
|
244
336
|
/** Read from environment/call scope */
|
|
245
337
|
InputType["Scope"] = "scope";
|
|
@@ -259,11 +351,11 @@ var InputTraceType;
|
|
|
259
351
|
InputTraceType["Unknown"] = "unknown";
|
|
260
352
|
})(InputTraceType || (exports.InputTraceType = InputTraceType = {}));
|
|
261
353
|
function matchesList(fn, list) {
|
|
262
|
-
if (
|
|
354
|
+
if (list === undefined || list.length === 0) {
|
|
263
355
|
return false;
|
|
264
356
|
}
|
|
265
357
|
for (const id of list) {
|
|
266
|
-
if (fn.id === id || identifier_1.Identifier.matches(id, fn.name)) {
|
|
358
|
+
if (fn.id === id || (identifier_1.Identifier.is(id) && identifier_1.Identifier.matches(id, fn.name))) {
|
|
267
359
|
return true;
|
|
268
360
|
}
|
|
269
361
|
}
|
|
@@ -272,16 +364,17 @@ function matchesList(fn, list) {
|
|
|
272
364
|
/**
|
|
273
365
|
* Takes the given id which is expected to either be:
|
|
274
366
|
* - a function call - in this case all arguments are considered to be inputs (additionally to all read edges from the function call in the dataflow graph)
|
|
275
|
-
* - anything else - in that case the node itself is considered as an "input" - please note that in these scenarios the *return* value will only contain one mapping - that for the id you
|
|
367
|
+
* - anything else - in that case the node itself is considered as an "input" - please note that in these scenarios the *return* value will only contain one mapping - that for the id you passed in.
|
|
276
368
|
*
|
|
277
|
-
* This method traces the dependencies in the dataflow graph using the specification of functions passed in
|
|
369
|
+
* This method traces the dependencies in the dataflow graph using the specification of functions passed in.
|
|
370
|
+
* For the scope escape analysis, pass on the full, non-reduced DFG as `fullDfg`.
|
|
278
371
|
*/
|
|
279
|
-
function classifyInput(id, dfg, config) {
|
|
372
|
+
function classifyInput(id, dfg, config, fullDfg) {
|
|
280
373
|
const vtx = dfg.getVertex(id);
|
|
281
374
|
if (!vtx) {
|
|
282
375
|
return [];
|
|
283
376
|
}
|
|
284
|
-
const c = new InputClassifier(dfg, config);
|
|
377
|
+
const c = new InputClassifier(dfg, config, fullDfg);
|
|
285
378
|
if (vtx.tag === vertex_1.VertexType.FunctionCall) {
|
|
286
379
|
const ret = [];
|
|
287
380
|
const args = vtx.args;
|
|
@@ -24,7 +24,7 @@ import type { RUnaryOp } from './nodes/r-unary-op';
|
|
|
24
24
|
import type { RBinaryOp } from './nodes/r-binary-op';
|
|
25
25
|
import type { RPipe } from './nodes/r-pipe';
|
|
26
26
|
import type { RDelimiter } from './nodes/info/r-delimiter';
|
|
27
|
-
import type { ParentInformation } from './processing/decorate';
|
|
27
|
+
import type { AstIdMap, ParentInformation } from './processing/decorate';
|
|
28
28
|
import type { NodeId } from './processing/node-id';
|
|
29
29
|
import type { OnEnter, OnExit } from './processing/visitor';
|
|
30
30
|
import type { SingleOrArrayOrNothing } from '../../../../abstract-interpretation/normalized-ast-fold';
|
|
@@ -264,16 +264,16 @@ export declare const RNode: {
|
|
|
264
264
|
* linear chain of parents leading to the root node.
|
|
265
265
|
* @see {@link iterateParents} - to get all parents of a node
|
|
266
266
|
*/
|
|
267
|
-
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation>, idMap:
|
|
267
|
+
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation>, idMap: AstIdMap<OtherInfo & ParentInformation>) => RNode<OtherInfo & ParentInformation> | undefined;
|
|
268
268
|
/**
|
|
269
269
|
* Returns an iterable of all parents of a node, starting with the direct parent and ending with the root node.
|
|
270
270
|
*/
|
|
271
|
-
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation> | undefined, idMap:
|
|
271
|
+
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation> | undefined, idMap: AstIdMap<OtherInfo & ParentInformation>) => Generator<RNode<OtherInfo & ParentInformation>>;
|
|
272
272
|
/**
|
|
273
273
|
* In contrast to the nesting stored in the {@link RNode} structure,
|
|
274
274
|
* this function calculates the depth of a node by counting the number of parents until the root node is reached.
|
|
275
275
|
*/
|
|
276
|
-
readonly depth: (this: void, node: RNode<ParentInformation>, idMap:
|
|
276
|
+
readonly depth: (this: void, node: RNode<ParentInformation>, idMap: AstIdMap<ParentInformation>) => number;
|
|
277
277
|
/**
|
|
278
278
|
* Collects all node ids within a tree given by a respective root node, but stops collecting at nodes where the given `stop` function returns `true`.
|
|
279
279
|
* <p>
|
|
@@ -49,9 +49,9 @@ export declare const RAccess: {
|
|
|
49
49
|
readonly visitAst: <OtherInfo = object>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo>>, onVisit?: import("../processing/visitor").OnEnter<OtherInfo>, onExit?: import("../processing/visitor").OnExit<OtherInfo>) => void;
|
|
50
50
|
readonly collectAllIds: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>) => Set<import("../processing/node-id").NodeId>;
|
|
51
51
|
readonly directChildren: <OtherInfo>(this: void, node: RNode<OtherInfo>) => readonly (RNode<OtherInfo> | typeof EmptyArgument)[];
|
|
52
|
-
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>, idMap:
|
|
53
|
-
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined, idMap:
|
|
54
|
-
readonly depth: (this: void, node: RNode<import("../processing/decorate").ParentInformation>, idMap:
|
|
52
|
+
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>, idMap: import("../processing/decorate").AstIdMap<OtherInfo & import("../processing/decorate").ParentInformation>) => RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined;
|
|
53
|
+
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined, idMap: import("../processing/decorate").AstIdMap<OtherInfo & import("../processing/decorate").ParentInformation>) => Generator<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>;
|
|
54
|
+
readonly depth: (this: void, node: RNode<import("../processing/decorate").ParentInformation>, idMap: import("../processing/decorate").AstIdMap<import("../processing/decorate").ParentInformation>) => number;
|
|
55
55
|
readonly collectAllIdsWithStop: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>, stop: (node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>) => boolean) => Set<import("../processing/node-id").NodeId>;
|
|
56
56
|
readonly lexeme: <R extends RNode<import("../processing/decorate").ParentInformation>>(this: void, node: R | undefined) => R extends {
|
|
57
57
|
lexeme: string;
|
|
@@ -68,9 +68,9 @@ export declare const RArgument: {
|
|
|
68
68
|
readonly visitAst: <OtherInfo = object>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo>>, onVisit?: import("../processing/visitor").OnEnter<OtherInfo>, onExit?: import("../processing/visitor").OnExit<OtherInfo>) => void;
|
|
69
69
|
readonly collectAllIds: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & ParentInformation>>) => Set<NodeId>;
|
|
70
70
|
readonly directChildren: <OtherInfo>(this: void, node: RNode<OtherInfo>) => readonly (RNode<OtherInfo> | typeof EmptyArgument)[];
|
|
71
|
-
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation>, idMap:
|
|
72
|
-
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation> | undefined, idMap:
|
|
73
|
-
readonly depth: (this: void, node: RNode<ParentInformation>, idMap:
|
|
71
|
+
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation>, idMap: import("../processing/decorate").AstIdMap<OtherInfo & ParentInformation>) => RNode<OtherInfo & ParentInformation> | undefined;
|
|
72
|
+
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation> | undefined, idMap: import("../processing/decorate").AstIdMap<OtherInfo & ParentInformation>) => Generator<RNode<OtherInfo & ParentInformation>>;
|
|
73
|
+
readonly depth: (this: void, node: RNode<ParentInformation>, idMap: import("../processing/decorate").AstIdMap<ParentInformation>) => number;
|
|
74
74
|
readonly collectAllIdsWithStop: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & ParentInformation>>, stop: (node: RNode<OtherInfo & ParentInformation>) => boolean) => Set<NodeId>;
|
|
75
75
|
readonly lexeme: <R extends RNode<ParentInformation>>(this: void, node: R | undefined) => R extends {
|
|
76
76
|
lexeme: string;
|
|
@@ -30,9 +30,9 @@ export declare const RBinaryOp: {
|
|
|
30
30
|
readonly visitAst: <OtherInfo = object>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo>>, onVisit?: import("../processing/visitor").OnEnter<OtherInfo>, onExit?: import("../processing/visitor").OnExit<OtherInfo>) => void;
|
|
31
31
|
readonly collectAllIds: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>) => Set<import("../processing/node-id").NodeId>;
|
|
32
32
|
readonly directChildren: <OtherInfo>(this: void, node: RNode<OtherInfo>) => readonly (RNode<OtherInfo> | typeof import("./r-function-call").EmptyArgument)[];
|
|
33
|
-
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>, idMap:
|
|
34
|
-
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined, idMap:
|
|
35
|
-
readonly depth: (this: void, node: RNode<import("../processing/decorate").ParentInformation>, idMap:
|
|
33
|
+
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>, idMap: import("../processing/decorate").AstIdMap<OtherInfo & import("../processing/decorate").ParentInformation>) => RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined;
|
|
34
|
+
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined, idMap: import("../processing/decorate").AstIdMap<OtherInfo & import("../processing/decorate").ParentInformation>) => Generator<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>;
|
|
35
|
+
readonly depth: (this: void, node: RNode<import("../processing/decorate").ParentInformation>, idMap: import("../processing/decorate").AstIdMap<import("../processing/decorate").ParentInformation>) => number;
|
|
36
36
|
readonly collectAllIdsWithStop: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>, stop: (node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>) => boolean) => Set<import("../processing/node-id").NodeId>;
|
|
37
37
|
readonly lexeme: <R extends RNode<import("../processing/decorate").ParentInformation>>(this: void, node: R | undefined) => R extends {
|
|
38
38
|
lexeme: string;
|
|
@@ -22,9 +22,9 @@ export declare const RBreak: {
|
|
|
22
22
|
readonly visitAst: <OtherInfo = object>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo>>, onVisit?: import("../processing/visitor").OnEnter<OtherInfo>, onExit?: import("../processing/visitor").OnExit<OtherInfo>) => void;
|
|
23
23
|
readonly collectAllIds: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>) => Set<import("../processing/node-id").NodeId>;
|
|
24
24
|
readonly directChildren: <OtherInfo>(this: void, node: RNode<OtherInfo>) => readonly (RNode<OtherInfo> | typeof import("./r-function-call").EmptyArgument)[];
|
|
25
|
-
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>, idMap:
|
|
26
|
-
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined, idMap:
|
|
27
|
-
readonly depth: (this: void, node: RNode<import("../processing/decorate").ParentInformation>, idMap:
|
|
25
|
+
readonly directParent: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>, idMap: import("../processing/decorate").AstIdMap<OtherInfo & import("../processing/decorate").ParentInformation>) => RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined;
|
|
26
|
+
readonly iterateParents: <OtherInfo>(this: void, node: RNode<OtherInfo & import("../processing/decorate").ParentInformation> | undefined, idMap: import("../processing/decorate").AstIdMap<OtherInfo & import("../processing/decorate").ParentInformation>) => Generator<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>;
|
|
27
|
+
readonly depth: (this: void, node: RNode<import("../processing/decorate").ParentInformation>, idMap: import("../processing/decorate").AstIdMap<import("../processing/decorate").ParentInformation>) => number;
|
|
28
28
|
readonly collectAllIdsWithStop: <OtherInfo>(this: void, nodes: import("../../../../../abstract-interpretation/normalized-ast-fold").SingleOrArrayOrNothing<RNode<OtherInfo & import("../processing/decorate").ParentInformation>>, stop: (node: RNode<OtherInfo & import("../processing/decorate").ParentInformation>) => boolean) => Set<import("../processing/node-id").NodeId>;
|
|
29
29
|
readonly lexeme: <R extends RNode<import("../processing/decorate").ParentInformation>>(this: void, node: R | undefined) => R extends {
|
|
30
30
|
lexeme: string;
|