@eagleoutice/flowr 2.2.14 → 2.2.16
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 +210 -6
- package/benchmark/slicer.d.ts +3 -1
- package/benchmark/slicer.js +8 -5
- package/benchmark/summarizer/first-phase/process.d.ts +2 -1
- package/benchmark/summarizer/first-phase/process.js +2 -2
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +4 -1
- package/cli/benchmark-helper-app.d.ts +1 -0
- package/cli/benchmark-helper-app.js +7 -8
- package/cli/common/options.js +2 -0
- package/cli/export-quads-app.js +2 -1
- package/cli/flowr.js +58 -57
- package/cli/repl/commands/repl-cfg.js +13 -13
- package/cli/repl/commands/repl-commands.js +3 -3
- package/cli/repl/commands/repl-dataflow.js +10 -10
- package/cli/repl/commands/repl-execute.d.ts +2 -3
- package/cli/repl/commands/repl-execute.js +5 -4
- package/cli/repl/commands/repl-lineage.js +4 -4
- package/cli/repl/commands/repl-main.d.ts +12 -1
- package/cli/repl/commands/repl-normalize.js +6 -6
- package/cli/repl/commands/repl-parse.js +2 -2
- package/cli/repl/commands/repl-query.js +9 -9
- package/cli/repl/commands/repl-version.js +1 -1
- package/cli/repl/core.d.ts +5 -2
- package/cli/repl/core.js +10 -8
- package/cli/repl/server/connection.d.ts +3 -1
- package/cli/repl/server/connection.js +7 -5
- package/cli/repl/server/server.d.ts +3 -2
- package/cli/repl/server/server.js +4 -2
- package/cli/script-core/statistics-core.d.ts +2 -1
- package/cli/script-core/statistics-core.js +2 -2
- package/cli/script-core/statistics-helper-core.d.ts +2 -1
- package/cli/script-core/statistics-helper-core.js +5 -4
- package/cli/slicer-app.js +4 -2
- package/cli/statistics-app.js +2 -1
- package/cli/statistics-helper-app.js +2 -1
- package/config.d.ts +12 -10
- package/config.js +27 -43
- package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
- package/control-flow/cfg-dead-code.d.ts +4 -0
- package/control-flow/cfg-dead-code.js +124 -0
- package/control-flow/cfg-simplification.d.ts +19 -6
- package/control-flow/cfg-simplification.js +23 -19
- package/control-flow/control-flow-graph.d.ts +3 -1
- package/control-flow/control-flow-graph.js +5 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +9 -7
- package/control-flow/dfg-cfg-guided-visitor.js +16 -5
- package/control-flow/extract-cfg.d.ts +4 -2
- package/control-flow/extract-cfg.js +63 -59
- package/control-flow/semantic-cfg-guided-visitor.d.ts +36 -9
- package/control-flow/semantic-cfg-guided-visitor.js +73 -20
- package/control-flow/simple-visitor.d.ts +4 -0
- package/control-flow/simple-visitor.js +14 -0
- package/control-flow/syntax-cfg-guided-visitor.d.ts +2 -2
- package/core/pipeline-executor.d.ts +4 -1
- package/core/pipeline-executor.js +6 -5
- package/core/steps/all/core/10-normalize.d.ts +2 -0
- package/core/steps/all/core/10-normalize.js +1 -1
- package/core/steps/all/core/11-normalize-tree-sitter.d.ts +2 -1
- package/core/steps/all/core/11-normalize-tree-sitter.js +2 -2
- package/core/steps/all/core/20-dataflow.d.ts +2 -1
- package/core/steps/all/core/20-dataflow.js +2 -2
- package/core/steps/all/static-slicing/00-slice.d.ts +2 -1
- package/core/steps/all/static-slicing/00-slice.js +2 -2
- package/core/steps/pipeline/default-pipelines.d.ts +32 -31
- package/core/steps/pipeline/default-pipelines.js +8 -8
- package/core/steps/pipeline-step.d.ts +2 -1
- package/dataflow/environments/built-in-config.d.ts +4 -3
- package/dataflow/environments/built-in.d.ts +16 -1
- package/dataflow/environments/built-in.js +11 -5
- package/dataflow/environments/default-builtin-config.js +5 -3
- package/dataflow/environments/define.d.ts +2 -1
- package/dataflow/environments/define.js +4 -5
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +29 -0
- package/dataflow/environments/resolve-by-name.d.ts +0 -36
- package/dataflow/environments/resolve-by-name.js +0 -240
- package/dataflow/eval/resolve/alias-tracking.d.ts +92 -0
- package/dataflow/eval/resolve/alias-tracking.js +352 -0
- package/dataflow/eval/resolve/resolve-argument.d.ts +8 -0
- package/dataflow/eval/resolve/resolve-argument.js +118 -0
- package/dataflow/eval/resolve/resolve.d.ts +37 -0
- package/dataflow/eval/resolve/resolve.js +95 -0
- package/dataflow/eval/values/general.d.ts +27 -0
- package/dataflow/eval/values/general.js +73 -0
- package/dataflow/eval/values/intervals/interval-constants.d.ts +4 -0
- package/dataflow/eval/values/intervals/interval-constants.js +27 -0
- package/dataflow/eval/values/logical/logical-constants.d.ts +7 -0
- package/dataflow/eval/values/logical/logical-constants.js +31 -0
- package/dataflow/eval/values/r-value.d.ts +58 -0
- package/dataflow/eval/values/r-value.js +90 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.d.ts +15 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.js +35 -0
- package/dataflow/eval/values/sets/set-constants.d.ts +7 -0
- package/dataflow/eval/values/sets/set-constants.js +34 -0
- package/dataflow/eval/values/string/string-constants.d.ts +8 -0
- package/dataflow/eval/values/string/string-constants.js +45 -0
- package/dataflow/eval/values/vectors/vector-constants.d.ts +14 -0
- package/dataflow/eval/values/vectors/vector-constants.js +35 -0
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/graph/unknown-replacement.d.ts +11 -0
- package/dataflow/graph/unknown-replacement.js +12 -0
- package/dataflow/graph/unknown-side-effect.d.ts +7 -0
- package/dataflow/graph/unknown-side-effect.js +13 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +5 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +8 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +4 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +15 -13
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +20 -18
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +7 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +11 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +26 -29
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +23 -0
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
- package/dataflow/internal/process/functions/process-parameter.js +1 -1
- package/dataflow/origin/dfg-get-symbol-refs.d.ts +21 -0
- package/dataflow/origin/dfg-get-symbol-refs.js +50 -0
- package/dataflow/processor.d.ts +5 -0
- package/documentation/doc-util/doc-cfg.js +4 -3
- package/documentation/doc-util/doc-code.d.ts +1 -1
- package/documentation/doc-util/doc-dfg.js +3 -2
- package/documentation/doc-util/doc-functions.d.ts +24 -0
- package/documentation/doc-util/doc-functions.js +65 -0
- package/documentation/doc-util/doc-normalized-ast.js +3 -2
- package/documentation/doc-util/doc-print.d.ts +5 -0
- package/documentation/doc-util/doc-print.js +36 -0
- package/documentation/doc-util/doc-query.d.ts +6 -3
- package/documentation/doc-util/doc-query.js +6 -3
- package/documentation/doc-util/doc-repl.js +2 -1
- package/documentation/doc-util/doc-search.js +3 -2
- package/documentation/doc-util/doc-types.d.ts +28 -6
- package/documentation/doc-util/doc-types.js +89 -45
- package/documentation/print-cfg-wiki.js +10 -11
- package/documentation/print-core-wiki.js +5 -5
- package/documentation/print-dataflow-graph-wiki.js +14 -13
- package/documentation/print-engines-wiki.js +2 -3
- package/documentation/print-faq-wiki.js +8 -2
- package/documentation/print-interface-wiki.js +1 -2
- package/documentation/print-linter-issue.d.ts +1 -0
- package/documentation/print-linter-issue.js +71 -0
- package/documentation/print-linter-wiki.js +219 -34
- package/documentation/print-linting-and-testing-wiki.js +2 -4
- package/documentation/print-normalized-ast-wiki.js +3 -3
- package/documentation/print-query-wiki.js +81 -2
- package/documentation/print-readme.js +24 -1
- package/documentation/print-search-wiki.js +1 -2
- package/linter/linter-executor.d.ts +3 -1
- package/linter/linter-executor.js +3 -2
- package/linter/linter-format.d.ts +67 -7
- package/linter/linter-format.js +12 -1
- package/linter/linter-rules.d.ts +155 -16
- package/linter/linter-rules.js +12 -4
- package/linter/linter-tags.d.ts +80 -0
- package/linter/linter-tags.js +85 -0
- package/linter/rules/absolute-path.d.ts +71 -0
- package/linter/rules/absolute-path.js +177 -0
- package/linter/rules/deprecated-functions.d.ts +43 -0
- package/linter/rules/deprecated-functions.js +58 -0
- package/linter/rules/{2-file-path-validity.d.ts → file-path-validity.d.ts} +16 -6
- package/linter/rules/{2-file-path-validity.js → file-path-validity.js} +21 -13
- package/linter/rules/naming-convention.d.ts +71 -0
- package/linter/rules/naming-convention.js +164 -0
- package/linter/rules/seeded-randomness.d.ts +65 -0
- package/linter/rules/seeded-randomness.js +122 -0
- package/linter/rules/unused-definition.d.ts +41 -0
- package/linter/rules/unused-definition.js +105 -0
- package/package.json +4 -1
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.js +2 -3
- package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +3 -0
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +20 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +81 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.js +34 -0
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -115
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.js +2 -2
- package/queries/catalog/linter-query/linter-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-format.js +17 -12
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
- package/queries/catalog/origin-query/origin-query-format.d.ts +1 -1
- package/queries/catalog/project-query/project-query-format.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +4 -4
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +3 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -22
- package/queries/catalog/search-query/search-query-executor.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.js +2 -2
- package/queries/catalog/search-query/search-query-format.d.ts +1 -1
- 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/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
- package/queries/query.d.ts +75 -15
- package/queries/query.js +2 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +4 -2
- package/r-bridge/lang-4.x/convert-values.js +2 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +3 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +18 -9
- package/r-bridge/shell.d.ts +3 -2
- package/r-bridge/shell.js +4 -5
- package/search/flowr-search-builder.d.ts +6 -2
- package/search/flowr-search-builder.js +7 -0
- package/search/flowr-search-filters.d.ts +32 -8
- package/search/flowr-search-filters.js +42 -15
- package/search/flowr-search.d.ts +4 -0
- package/search/search-executor/search-enrichers.d.ts +7 -3
- package/search/search-executor/search-enrichers.js +32 -20
- package/search/search-executor/search-generators.js +1 -1
- package/search/search-executor/search-transformer.d.ts +2 -0
- package/search/search-executor/search-transformer.js +10 -1
- package/slicing/criterion/parse.d.ts +8 -0
- package/slicing/criterion/parse.js +20 -0
- package/slicing/static/static-slicer.d.ts +1 -1
- package/slicing/static/static-slicer.js +2 -3
- package/statistics/statistics.d.ts +3 -1
- package/statistics/statistics.js +5 -4
- package/util/containers.d.ts +12 -9
- package/util/containers.js +12 -9
- package/util/objects.d.ts +5 -4
- package/util/range.d.ts +5 -1
- package/util/range.js +11 -3
- package/util/text/strings.d.ts +6 -0
- package/util/text/strings.js +35 -0
- package/util/version.js +1 -1
- package/linter/rules/1-deprecated-functions.d.ts +0 -34
- package/linter/rules/1-deprecated-functions.js +0 -54
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultCfgSimplificationOrder = void 0;
|
|
3
|
+
exports.DefaultCfgSimplificationOrder = exports.CfgSimplificationPasses = void 0;
|
|
4
4
|
exports.simplifyControlFlowInformation = simplifyControlFlowInformation;
|
|
5
|
-
const simple_visitor_1 = require("./simple-visitor");
|
|
6
5
|
const cfg_to_basic_blocks_1 = require("./cfg-to-basic-blocks");
|
|
7
|
-
const
|
|
6
|
+
const simple_visitor_1 = require("./simple-visitor");
|
|
7
|
+
const cfg_dead_code_1 = require("./cfg-dead-code");
|
|
8
|
+
exports.CfgSimplificationPasses = {
|
|
8
9
|
'unique-cf-sets': uniqueControlFlowSets,
|
|
10
|
+
'analyze-dead-code': cfg_dead_code_1.cfgAnalyzeDeadCode,
|
|
9
11
|
'remove-dead-code': cfgRemoveDeadCode,
|
|
10
12
|
'to-basic-blocks': toBasicBlocks
|
|
11
13
|
};
|
|
@@ -18,25 +20,17 @@ exports.DefaultCfgSimplificationOrder = [
|
|
|
18
20
|
* Simplify the control flow information by applying the given passes.
|
|
19
21
|
* This may reduce the vertex count, in- and outgoing edges, entry and exit points, etc.
|
|
20
22
|
*/
|
|
21
|
-
function simplifyControlFlowInformation(cfg, passes = exports.DefaultCfgSimplificationOrder) {
|
|
23
|
+
function simplifyControlFlowInformation(cfg, info, passes = exports.DefaultCfgSimplificationOrder) {
|
|
22
24
|
for (const pass of passes) {
|
|
23
|
-
const passFn = CfgSimplificationPasses[pass];
|
|
24
|
-
cfg = passFn(cfg);
|
|
25
|
+
const passFn = exports.CfgSimplificationPasses[pass];
|
|
26
|
+
cfg = passFn(cfg, info);
|
|
25
27
|
}
|
|
26
28
|
return cfg;
|
|
27
29
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
exitPoints: [...new Set(cfg.exitPoints)],
|
|
33
|
-
breaks: [...new Set(cfg.breaks)],
|
|
34
|
-
nexts: [...new Set(cfg.nexts)],
|
|
35
|
-
graph: cfg.graph
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/* currently this does not do work on function definitions */
|
|
39
|
-
function cfgRemoveDeadCode(cfg) {
|
|
30
|
+
/**
|
|
31
|
+
* removes dead vertices and edges from the control flow graph.
|
|
32
|
+
*/
|
|
33
|
+
function cfgRemoveDeadCode(cfg, _info) {
|
|
40
34
|
// remove every root level node and accompanying vertices that can not be reached from the entry points
|
|
41
35
|
const reachable = new Set();
|
|
42
36
|
(0, simple_visitor_1.visitCfgInOrder)(cfg.graph, cfg.entryPoints, node => {
|
|
@@ -49,7 +43,17 @@ function cfgRemoveDeadCode(cfg) {
|
|
|
49
43
|
}
|
|
50
44
|
return cfg;
|
|
51
45
|
}
|
|
52
|
-
function
|
|
46
|
+
function uniqueControlFlowSets(cfg, _info) {
|
|
47
|
+
return {
|
|
48
|
+
returns: [...new Set(cfg.returns)],
|
|
49
|
+
entryPoints: [...new Set(cfg.entryPoints)],
|
|
50
|
+
exitPoints: [...new Set(cfg.exitPoints)],
|
|
51
|
+
breaks: [...new Set(cfg.breaks)],
|
|
52
|
+
nexts: [...new Set(cfg.nexts)],
|
|
53
|
+
graph: cfg.graph
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function toBasicBlocks(cfg, _info) {
|
|
53
57
|
return (0, cfg_to_basic_blocks_1.convertCfgToBasicBlocks)(cfg);
|
|
54
58
|
}
|
|
55
59
|
//# sourceMappingURL=cfg-simplification.js.map
|
|
@@ -67,10 +67,11 @@ export interface CfgBasicBlockVertex extends CfgBaseVertex {
|
|
|
67
67
|
*/
|
|
68
68
|
export type CfgSimpleVertex = CfgStatementVertex | CfgExpressionVertex | CfgBasicBlockVertex | CfgMidMarkerVertex | CfgEndMarkerVertex;
|
|
69
69
|
export declare function equalVertex(a: CfgSimpleVertex, b: CfgSimpleVertex): boolean;
|
|
70
|
+
export declare function isMarkerVertex(vertex: CfgSimpleVertex): vertex is CfgMidMarkerVertex | CfgEndMarkerVertex;
|
|
70
71
|
interface CfgFlowDependencyEdge extends MergeableRecord {
|
|
71
72
|
label: CfgEdgeType.Fd;
|
|
72
73
|
}
|
|
73
|
-
interface CfgControlDependencyEdge extends MergeableRecord {
|
|
74
|
+
export interface CfgControlDependencyEdge extends MergeableRecord {
|
|
74
75
|
label: CfgEdgeType.Cd;
|
|
75
76
|
/** the id which caused the control dependency */
|
|
76
77
|
caused: NodeId;
|
|
@@ -166,6 +167,7 @@ export interface ReadOnlyControlFlowGraph {
|
|
|
166
167
|
*/
|
|
167
168
|
export declare class ControlFlowGraph<Vertex extends CfgSimpleVertex = CfgSimpleVertex> implements ReadOnlyControlFlowGraph {
|
|
168
169
|
private readonly rootVertices;
|
|
170
|
+
/** Nesting-Independent vertex information, mapping the id to the vertex */
|
|
169
171
|
private readonly vertexInformation;
|
|
170
172
|
/** the basic block children map contains a mapping of ids to all vertices that are nested in basic blocks, mapping them to the Id of the block they appear in */
|
|
171
173
|
private readonly bbChildren;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ControlFlowGraph = exports.CfgVertexType = void 0;
|
|
4
4
|
exports.edgeTypeToString = edgeTypeToString;
|
|
5
5
|
exports.equalVertex = equalVertex;
|
|
6
|
+
exports.isMarkerVertex = isMarkerVertex;
|
|
6
7
|
exports.emptyControlFlowInformation = emptyControlFlowInformation;
|
|
7
8
|
const assert_1 = require("../util/assert");
|
|
8
9
|
var CfgVertexType;
|
|
@@ -43,6 +44,9 @@ function equalVertex(a, b) {
|
|
|
43
44
|
}
|
|
44
45
|
return true;
|
|
45
46
|
}
|
|
47
|
+
function isMarkerVertex(vertex) {
|
|
48
|
+
return vertex.type === CfgVertexType.MidMarker || vertex.type === CfgVertexType.EndMarker;
|
|
49
|
+
}
|
|
46
50
|
/**
|
|
47
51
|
* This class represents the control flow graph of an R program.
|
|
48
52
|
* The control flow may be hierarchical when confronted with function definitions (see {@link CfgSimpleVertex} and {@link CFG#rootVertexIds|rootVertexIds()}).
|
|
@@ -55,6 +59,7 @@ function equalVertex(a, b) {
|
|
|
55
59
|
*/
|
|
56
60
|
class ControlFlowGraph {
|
|
57
61
|
rootVertices = new Set();
|
|
62
|
+
/** Nesting-Independent vertex information, mapping the id to the vertex */
|
|
58
63
|
vertexInformation = new Map();
|
|
59
64
|
/** the basic block children map contains a mapping of ids to all vertices that are nested in basic blocks, mapping them to the Id of the block they appear in */
|
|
60
65
|
bbChildren = new Map();
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CfgBasicBlockVertex, type CfgEndMarkerVertex, type CfgExpressionVertex, type CfgSimpleVertex, type CfgStatementVertex, type ControlFlowInformation } from './control-flow-graph';
|
|
2
2
|
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
|
-
import type { DataflowInformation } from '../dataflow/info';
|
|
4
3
|
import type { DataflowGraphVertexArgument, DataflowGraphVertexFunctionCall, DataflowGraphVertexFunctionDefinition, DataflowGraphVertexUse, DataflowGraphVertexValue, DataflowGraphVertexVariableDefinition } from '../dataflow/graph/vertex';
|
|
5
4
|
import type { BasicCfgGuidedVisitorConfiguration } from './basic-cfg-guided-visitor';
|
|
6
5
|
import { BasicCfgGuidedVisitor } from './basic-cfg-guided-visitor';
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import type { DataflowGraph } from '../dataflow/graph/graph';
|
|
7
|
+
export interface DataflowCfgGuidedVisitorConfiguration<ControlFlow extends ControlFlowInformation = ControlFlowInformation, Dfg extends DataflowGraph = DataflowGraph> extends BasicCfgGuidedVisitorConfiguration<ControlFlow> {
|
|
8
|
+
readonly dfg: Dfg;
|
|
9
|
+
readonly defaultVisitingType?: 'entry' | 'exit';
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* This visitor extends on the {@link BasicCfgGuidedVisitor} by dispatching visitors based on the dataflow graph.
|
|
12
13
|
*
|
|
13
14
|
* Use {@link BasicCfgGuidedVisitor#start} to start the traversal.
|
|
14
15
|
*/
|
|
15
|
-
export declare class DataflowAwareCfgGuidedVisitor<
|
|
16
|
+
export declare class DataflowAwareCfgGuidedVisitor<ControlFlow extends ControlFlowInformation = ControlFlowInformation, Dfg extends DataflowGraph = DataflowGraph, Config extends DataflowCfgGuidedVisitorConfiguration<ControlFlow, Dfg> = DataflowCfgGuidedVisitorConfiguration<ControlFlow, Dfg>> extends BasicCfgGuidedVisitor<ControlFlow, Config> {
|
|
16
17
|
/**
|
|
17
18
|
* Get the dataflow graph vertex for the given id
|
|
18
19
|
*/
|
|
19
20
|
protected getDataflowGraph(id: NodeId): DataflowGraphVertexArgument | undefined;
|
|
20
21
|
protected onStatementNode(node: CfgStatementVertex): void;
|
|
21
22
|
protected onExpressionNode(node: CfgExpressionVertex): void;
|
|
22
|
-
|
|
23
|
+
protected onEndMarkerNode(node: CfgEndMarkerVertex): void;
|
|
24
|
+
protected visitDataflowNode(node: Exclude<CfgSimpleVertex, CfgBasicBlockVertex>): void;
|
|
23
25
|
/**
|
|
24
26
|
* called for every cfg vertex that has no corresponding dataflow vertex.
|
|
25
27
|
*/
|
|
26
|
-
protected visitUnknown(_vertex:
|
|
28
|
+
protected visitUnknown(_vertex: Exclude<CfgSimpleVertex, CfgBasicBlockVertex>): void;
|
|
27
29
|
protected visitValue(_val: DataflowGraphVertexValue): void;
|
|
28
30
|
protected visitVariableUse(_use: DataflowGraphVertexUse): void;
|
|
29
31
|
protected visitVariableDefinition(_def: DataflowGraphVertexVariableDefinition): void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataflowAwareCfgGuidedVisitor = void 0;
|
|
4
|
+
const control_flow_graph_1 = require("./control-flow-graph");
|
|
4
5
|
const vertex_1 = require("../dataflow/graph/vertex");
|
|
5
6
|
const basic_cfg_guided_visitor_1 = require("./basic-cfg-guided-visitor");
|
|
6
7
|
const assert_1 = require("../util/assert");
|
|
@@ -14,18 +15,28 @@ class DataflowAwareCfgGuidedVisitor extends basic_cfg_guided_visitor_1.BasicCfgG
|
|
|
14
15
|
* Get the dataflow graph vertex for the given id
|
|
15
16
|
*/
|
|
16
17
|
getDataflowGraph(id) {
|
|
17
|
-
return this.config.
|
|
18
|
+
return this.config.dfg.getVertex(id);
|
|
18
19
|
}
|
|
19
20
|
onStatementNode(node) {
|
|
20
21
|
super.onStatementNode(node);
|
|
21
|
-
this.
|
|
22
|
+
if (this.config.defaultVisitingType !== 'exit' || node.end === undefined) {
|
|
23
|
+
this.visitDataflowNode(node);
|
|
24
|
+
}
|
|
22
25
|
}
|
|
23
26
|
onExpressionNode(node) {
|
|
24
27
|
super.onExpressionNode(node);
|
|
25
|
-
this.
|
|
28
|
+
if (this.config.defaultVisitingType !== 'exit' || node.end === undefined) {
|
|
29
|
+
this.visitDataflowNode(node);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
onEndMarkerNode(node) {
|
|
33
|
+
super.onEndMarkerNode(node);
|
|
34
|
+
if (this.config.defaultVisitingType === 'exit') {
|
|
35
|
+
this.visitDataflowNode(node);
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
|
-
|
|
28
|
-
const dfgVertex = this.getDataflowGraph(node.id);
|
|
38
|
+
visitDataflowNode(node) {
|
|
39
|
+
const dfgVertex = this.getDataflowGraph((0, control_flow_graph_1.isMarkerVertex)(node) ? node.root : node.id);
|
|
29
40
|
if (!dfgVertex) {
|
|
30
41
|
this.visitUnknown(node);
|
|
31
42
|
return;
|
|
@@ -3,18 +3,20 @@ import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/
|
|
|
3
3
|
import type { DataflowGraph } from '../dataflow/graph/graph';
|
|
4
4
|
import type { ControlFlowInformation } from './control-flow-graph';
|
|
5
5
|
import type { CfgSimplificationPassName } from './cfg-simplification';
|
|
6
|
+
import type { FlowrConfigOptions } from '../config';
|
|
6
7
|
/**
|
|
7
8
|
* Given a normalized AST this approximates the control flow graph of the program.
|
|
8
|
-
* This
|
|
9
|
+
* This view is different from the computation of the dataflow graph and may differ,
|
|
9
10
|
* especially because it focuses on intra-procedural analysis.
|
|
10
11
|
*
|
|
11
12
|
* @param ast - the normalized AST
|
|
13
|
+
* @param config - the Flowr config
|
|
12
14
|
* @param graph - additional dataflow facts to consider by the control flow extraction
|
|
13
15
|
* @param simplifications - a list of simplification passes to apply to the control flow graph
|
|
14
16
|
*
|
|
15
17
|
* @see {@link extractSimpleCfg} - for a simplified version of this function
|
|
16
18
|
*/
|
|
17
|
-
export declare function extractCfg<Info = ParentInformation>(ast: NormalizedAst<Info>, graph?: DataflowGraph, simplifications?: readonly CfgSimplificationPassName[]): ControlFlowInformation;
|
|
19
|
+
export declare function extractCfg<Info = ParentInformation>(ast: NormalizedAst<Info & ParentInformation>, config: FlowrConfigOptions, graph?: DataflowGraph, simplifications?: readonly CfgSimplificationPassName[]): ControlFlowInformation;
|
|
18
20
|
/**
|
|
19
21
|
* Simplified version of {@link extractCfg} that is much quicker, but much simpler!
|
|
20
22
|
*/
|
|
@@ -53,17 +53,18 @@ function dataflowCfgFolds(dataflowGraph) {
|
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* Given a normalized AST this approximates the control flow graph of the program.
|
|
56
|
-
* This
|
|
56
|
+
* This view is different from the computation of the dataflow graph and may differ,
|
|
57
57
|
* especially because it focuses on intra-procedural analysis.
|
|
58
58
|
*
|
|
59
59
|
* @param ast - the normalized AST
|
|
60
|
+
* @param config - the Flowr config
|
|
60
61
|
* @param graph - additional dataflow facts to consider by the control flow extraction
|
|
61
62
|
* @param simplifications - a list of simplification passes to apply to the control flow graph
|
|
62
63
|
*
|
|
63
64
|
* @see {@link extractSimpleCfg} - for a simplified version of this function
|
|
64
65
|
*/
|
|
65
|
-
function extractCfg(ast, graph, simplifications) {
|
|
66
|
-
return (0, cfg_simplification_1.simplifyControlFlowInformation)((0, fold_1.foldAst)(ast.ast, graph ? dataflowCfgFolds(graph) : cfgFolds), simplifications);
|
|
66
|
+
function extractCfg(ast, config, graph, simplifications) {
|
|
67
|
+
return (0, cfg_simplification_1.simplifyControlFlowInformation)((0, fold_1.foldAst)(ast.ast, graph ? dataflowCfgFolds(graph) : cfgFolds), { ast, dfg: graph, config }, simplifications);
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
69
70
|
* Simplified version of {@link extractCfg} that is much quicker, but much simpler!
|
|
@@ -72,10 +73,8 @@ function extractSimpleCfg(ast) {
|
|
|
72
73
|
return (0, fold_1.foldAst)(ast.ast, cfgFolds);
|
|
73
74
|
}
|
|
74
75
|
function cfgLeaf(type) {
|
|
75
|
-
return (
|
|
76
|
-
|
|
77
|
-
graph.addVertex({ id: leaf.info.id, type });
|
|
78
|
-
return { graph, breaks: [], nexts: [], returns: [], exitPoints: [leaf.info.id], entryPoints: [leaf.info.id] };
|
|
76
|
+
return ({ info: { id } }) => {
|
|
77
|
+
return { graph: new control_flow_graph_1.ControlFlowGraph().addVertex({ id, type }), breaks: [], nexts: [], returns: [], exitPoints: [id], entryPoints: [id] };
|
|
79
78
|
};
|
|
80
79
|
}
|
|
81
80
|
function cfgBreak(leaf) {
|
|
@@ -91,40 +90,41 @@ function identifyMayStatementType(node) {
|
|
|
91
90
|
return node.info.role === "expr-list-child" /* RoleInParent.ExpressionListChild */ ? control_flow_graph_1.CfgVertexType.Statement : control_flow_graph_1.CfgVertexType.Expression;
|
|
92
91
|
}
|
|
93
92
|
function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
93
|
+
const ifId = ifNode.info.id;
|
|
94
94
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
95
|
-
graph.addVertex({ id:
|
|
96
|
-
graph.addVertex({ id:
|
|
97
|
-
graph.addVertex({ id:
|
|
95
|
+
graph.addVertex({ id: ifId, type: identifyMayStatementType(ifNode), mid: [ifId + '-condition'], end: [ifId + '-exit'] });
|
|
96
|
+
graph.addVertex({ id: ifId + '-condition', kind: 'condition', type: control_flow_graph_1.CfgVertexType.MidMarker, root: ifId });
|
|
97
|
+
graph.addVertex({ id: ifId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: ifId });
|
|
98
98
|
graph.mergeWith(condition.graph);
|
|
99
99
|
graph.mergeWith(then.graph);
|
|
100
100
|
if (otherwise) {
|
|
101
101
|
graph.mergeWith(otherwise.graph);
|
|
102
102
|
}
|
|
103
103
|
for (const exitPoint of condition.exitPoints) {
|
|
104
|
-
graph.addEdge(
|
|
104
|
+
graph.addEdge(ifId + '-condition', exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
|
|
105
105
|
}
|
|
106
106
|
for (const entryPoint of then.entryPoints) {
|
|
107
|
-
graph.addEdge(entryPoint,
|
|
107
|
+
graph.addEdge(entryPoint, ifId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: ifId });
|
|
108
108
|
}
|
|
109
109
|
for (const entryPoint of otherwise?.entryPoints ?? []) {
|
|
110
|
-
graph.addEdge(entryPoint,
|
|
110
|
+
graph.addEdge(entryPoint, ifId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
|
|
111
111
|
}
|
|
112
112
|
for (const entryPoint of condition.entryPoints) {
|
|
113
|
-
graph.addEdge(entryPoint,
|
|
113
|
+
graph.addEdge(entryPoint, ifId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
114
114
|
}
|
|
115
115
|
for (const exit of [...then.exitPoints, ...otherwise?.exitPoints ?? []]) {
|
|
116
|
-
graph.addEdge(
|
|
116
|
+
graph.addEdge(ifId + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
117
117
|
}
|
|
118
118
|
if (!otherwise) {
|
|
119
|
-
graph.addEdge(
|
|
119
|
+
graph.addEdge(ifId + '-exit', ifId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
|
|
120
120
|
}
|
|
121
121
|
return {
|
|
122
122
|
graph,
|
|
123
123
|
breaks: [...then.breaks, ...otherwise?.breaks ?? []],
|
|
124
124
|
nexts: [...then.nexts, ...otherwise?.nexts ?? []],
|
|
125
125
|
returns: [...then.returns, ...otherwise?.returns ?? []],
|
|
126
|
-
exitPoints: [
|
|
127
|
-
entryPoints: [
|
|
126
|
+
exitPoints: [ifId + '-exit'],
|
|
127
|
+
entryPoints: [ifId]
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
function cfgRepeat(repeat, body) {
|
|
@@ -144,110 +144,114 @@ function cfgRepeat(repeat, body) {
|
|
|
144
144
|
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [repeat.info.id + '-exit'], entryPoints: [repeat.info.id] };
|
|
145
145
|
}
|
|
146
146
|
function cfgWhile(whileLoop, condition, body) {
|
|
147
|
+
const whileId = whileLoop.info.id;
|
|
147
148
|
const graph = condition.graph;
|
|
148
|
-
graph.addVertex({ id:
|
|
149
|
-
graph.addVertex({ id:
|
|
150
|
-
graph.addVertex({ id:
|
|
149
|
+
graph.addVertex({ id: whileId, type: identifyMayStatementType(whileLoop), mid: [whileId + '-condition'], end: [whileId + '-exit'] });
|
|
150
|
+
graph.addVertex({ id: whileId + '-condition', kind: 'condition', type: control_flow_graph_1.CfgVertexType.MidMarker, root: whileId });
|
|
151
|
+
graph.addVertex({ id: whileId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: whileId });
|
|
151
152
|
graph.mergeWith(body.graph);
|
|
152
153
|
for (const entry of condition.entryPoints) {
|
|
153
|
-
graph.addEdge(entry,
|
|
154
|
+
graph.addEdge(entry, whileId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
154
155
|
}
|
|
155
156
|
for (const exit of condition.exitPoints) {
|
|
156
|
-
graph.addEdge(
|
|
157
|
+
graph.addEdge(whileId + '-condition', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
157
158
|
}
|
|
158
159
|
for (const entry of body.entryPoints) {
|
|
159
|
-
graph.addEdge(entry,
|
|
160
|
+
graph.addEdge(entry, whileId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: whileId });
|
|
160
161
|
}
|
|
161
162
|
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
162
|
-
graph.addEdge(
|
|
163
|
+
graph.addEdge(whileId, next, { label: 0 /* CfgEdgeType.Fd */ });
|
|
163
164
|
}
|
|
164
165
|
for (const breakPoint of body.breaks) {
|
|
165
|
-
graph.addEdge(
|
|
166
|
+
graph.addEdge(whileId + '-exit', breakPoint, { label: 0 /* CfgEdgeType.Fd */ });
|
|
166
167
|
}
|
|
167
168
|
// while can break on the condition as well
|
|
168
|
-
graph.addEdge(
|
|
169
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [
|
|
169
|
+
graph.addEdge(whileId + '-exit', whileId + '-condition', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: whileId });
|
|
170
|
+
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [whileId + '-exit'], entryPoints: [whileId] };
|
|
170
171
|
}
|
|
171
172
|
function cfgFor(forLoop, variable, vector, body) {
|
|
173
|
+
const forLoopId = forLoop.info.id;
|
|
172
174
|
const graph = variable.graph;
|
|
173
|
-
graph.addVertex({ id:
|
|
175
|
+
graph.addVertex({ id: forLoopId, type: identifyMayStatementType(forLoop), end: [forLoopId + '-exit'], mid: [forLoopId + '-head'] });
|
|
174
176
|
graph.mergeWith(vector.graph);
|
|
175
177
|
graph.mergeWith(body.graph);
|
|
176
178
|
for (const entry of vector.entryPoints) {
|
|
177
|
-
graph.addEdge(entry,
|
|
179
|
+
graph.addEdge(entry, forLoopId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
178
180
|
}
|
|
179
181
|
for (const exit of vector.exitPoints) {
|
|
180
182
|
for (const entry of variable.entryPoints) {
|
|
181
183
|
graph.addEdge(entry, exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
182
184
|
}
|
|
183
185
|
}
|
|
184
|
-
graph.addVertex({ id:
|
|
186
|
+
graph.addVertex({ id: forLoopId + '-head', type: control_flow_graph_1.CfgVertexType.MidMarker, root: forLoopId, kind: 'head' });
|
|
185
187
|
for (const exit of variable.exitPoints) {
|
|
186
|
-
graph.addEdge(
|
|
188
|
+
graph.addEdge(forLoopId + '-head', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
187
189
|
}
|
|
188
190
|
for (const entry of body.entryPoints) {
|
|
189
|
-
graph.addEdge(entry,
|
|
191
|
+
graph.addEdge(entry, forLoopId + '-head', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: forLoopId });
|
|
190
192
|
}
|
|
191
193
|
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
192
|
-
graph.addEdge(
|
|
194
|
+
graph.addEdge(forLoopId, next, { label: 0 /* CfgEdgeType.Fd */ });
|
|
193
195
|
}
|
|
194
196
|
for (const breakPoint of body.breaks) {
|
|
195
|
-
graph.addEdge(
|
|
197
|
+
graph.addEdge(forLoopId + '-exit', breakPoint, { label: 0 /* CfgEdgeType.Fd */ });
|
|
196
198
|
}
|
|
197
199
|
const isNotEndless = body.exitPoints.length > 0 || body.breaks.length > 0;
|
|
198
200
|
if (isNotEndless) {
|
|
199
201
|
graph.addVertex({
|
|
200
|
-
id:
|
|
202
|
+
id: forLoopId + '-exit',
|
|
201
203
|
type: control_flow_graph_1.CfgVertexType.EndMarker,
|
|
202
|
-
root:
|
|
204
|
+
root: forLoopId
|
|
203
205
|
});
|
|
204
|
-
graph.addEdge(
|
|
206
|
+
graph.addEdge(forLoopId + '-exit', forLoopId + '-head', { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: forLoopId });
|
|
205
207
|
}
|
|
206
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [
|
|
208
|
+
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [forLoopId + '-exit'] : [], entryPoints: [forLoopId] };
|
|
207
209
|
}
|
|
208
210
|
function cfgFunctionDefinition(fn, params, body) {
|
|
211
|
+
const fnId = fn.info.id;
|
|
209
212
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
210
|
-
const children = [
|
|
211
|
-
graph.addVertex({ id:
|
|
212
|
-
graph.addVertex({ id:
|
|
213
|
-
graph.addVertex({ id:
|
|
213
|
+
const children = [fnId + '-params', fnId + '-exit'];
|
|
214
|
+
graph.addVertex({ id: fnId + '-params', kind: 'parameters', type: control_flow_graph_1.CfgVertexType.MidMarker, root: fnId }, false);
|
|
215
|
+
graph.addVertex({ id: fnId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: fnId }, false);
|
|
216
|
+
graph.addVertex({ id: fnId, children, type: identifyMayStatementType(fn), mid: [fnId + '-params'], end: [fnId + '-exit'] });
|
|
214
217
|
graph.mergeWith(body.graph, true);
|
|
215
218
|
children.push(...body.graph.rootIds());
|
|
216
219
|
for (const param of params) {
|
|
217
220
|
graph.mergeWith(param.graph, true);
|
|
218
221
|
children.push(...param.graph.rootIds());
|
|
219
222
|
for (const entry of param.entryPoints) {
|
|
220
|
-
graph.addEdge(entry,
|
|
223
|
+
graph.addEdge(entry, fnId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
221
224
|
}
|
|
222
225
|
for (const exit of param.exitPoints) {
|
|
223
|
-
graph.addEdge(
|
|
226
|
+
graph.addEdge(fnId + '-params', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
224
227
|
}
|
|
225
228
|
}
|
|
226
229
|
if (params.length === 0) {
|
|
227
|
-
graph.addEdge(
|
|
230
|
+
graph.addEdge(fnId + '-params', fnId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
228
231
|
}
|
|
229
232
|
for (const entry of body.entryPoints) {
|
|
230
|
-
graph.addEdge(entry,
|
|
233
|
+
graph.addEdge(entry, fnId + '-params', { label: 0 /* CfgEdgeType.Fd */ });
|
|
231
234
|
}
|
|
232
|
-
// breaks and nexts should be illegal but safe is safe
|
|
233
|
-
for (const next of
|
|
234
|
-
graph.addEdge(
|
|
235
|
+
// breaks and nexts should be illegal but safe is safe, I guess
|
|
236
|
+
for (const next of body.returns.concat(body.breaks, body.nexts, body.exitPoints)) {
|
|
237
|
+
graph.addEdge(fnId + '-exit', next, { label: 0 /* CfgEdgeType.Fd */ });
|
|
235
238
|
}
|
|
236
|
-
return { graph: graph, breaks: [], nexts: [], returns: [], exitPoints: [
|
|
239
|
+
return { graph: graph, breaks: [], nexts: [], returns: [], exitPoints: [fnId], entryPoints: [fnId] };
|
|
237
240
|
}
|
|
238
241
|
function cfgFunctionCall(call, name, args, exit = 'exit') {
|
|
242
|
+
const callId = call.info.id;
|
|
239
243
|
const graph = name.graph;
|
|
240
|
-
const info = { graph, breaks: [...name.breaks], nexts: [...name.nexts], returns: [...name.returns], exitPoints: [
|
|
241
|
-
graph.addVertex({ id:
|
|
244
|
+
const info = { graph, breaks: [...name.breaks], nexts: [...name.nexts], returns: [...name.returns], exitPoints: [callId + '-' + exit], entryPoints: [callId] };
|
|
245
|
+
graph.addVertex({ id: callId, type: identifyMayStatementType(call), mid: [callId + '-name'], end: [callId + '-' + exit] });
|
|
242
246
|
for (const entryPoint of name.entryPoints) {
|
|
243
|
-
graph.addEdge(entryPoint,
|
|
247
|
+
graph.addEdge(entryPoint, callId, { label: 0 /* CfgEdgeType.Fd */ });
|
|
244
248
|
}
|
|
245
|
-
graph.addVertex({ id:
|
|
249
|
+
graph.addVertex({ id: callId + '-name', kind: 'name', type: control_flow_graph_1.CfgVertexType.MidMarker, root: callId });
|
|
246
250
|
for (const exitPoint of name.exitPoints) {
|
|
247
|
-
graph.addEdge(
|
|
251
|
+
graph.addEdge(callId + '-name', exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
|
|
248
252
|
}
|
|
249
|
-
graph.addVertex({ id:
|
|
250
|
-
let lastArgExits = [
|
|
253
|
+
graph.addVertex({ id: callId + '-' + exit, type: control_flow_graph_1.CfgVertexType.EndMarker, root: callId });
|
|
254
|
+
let lastArgExits = [callId + '-name'];
|
|
251
255
|
for (const arg of args) {
|
|
252
256
|
if (arg === r_function_call_1.EmptyArgument) {
|
|
253
257
|
continue;
|
|
@@ -264,7 +268,7 @@ function cfgFunctionCall(call, name, args, exit = 'exit') {
|
|
|
264
268
|
lastArgExits = arg.exitPoints;
|
|
265
269
|
}
|
|
266
270
|
for (const exit of lastArgExits) {
|
|
267
|
-
graph.addEdge(
|
|
271
|
+
graph.addEdge(callId + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
|
|
268
272
|
}
|
|
269
273
|
// should not contain any breaks, nexts, or returns, (except for the body if something like 'break()')
|
|
270
274
|
return info;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { CfgExpressionVertex, CfgStatementVertex, ControlFlowInformation } from './control-flow-graph';
|
|
2
|
-
import type { DataflowInformation } from '../dataflow/info';
|
|
3
2
|
import type { DataflowCfgGuidedVisitorConfiguration } from './dfg-cfg-guided-visitor';
|
|
4
3
|
import { DataflowAwareCfgGuidedVisitor } from './dfg-cfg-guided-visitor';
|
|
5
4
|
import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
@@ -10,12 +9,14 @@ import type { DataflowGraphVertexFunctionCall, DataflowGraphVertexFunctionDefini
|
|
|
10
9
|
import type { RString } from '../r-bridge/lang-4.x/ast/model/nodes/r-string';
|
|
11
10
|
import type { RNumber } from '../r-bridge/lang-4.x/ast/model/nodes/r-number';
|
|
12
11
|
import type { RLogical } from '../r-bridge/lang-4.x/ast/model/nodes/r-logical';
|
|
13
|
-
import type { FunctionArgument } from '../dataflow/graph/graph';
|
|
12
|
+
import type { DataflowGraph, FunctionArgument } from '../dataflow/graph/graph';
|
|
14
13
|
import type { NoInfo, RNode } from '../r-bridge/lang-4.x/ast/model/model';
|
|
15
14
|
import type { RSymbol } from '../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
16
15
|
import type { BuiltInProcessorMapper } from '../dataflow/environments/built-in';
|
|
17
16
|
import type { RExpressionList } from '../r-bridge/lang-4.x/ast/model/nodes/r-expression-list';
|
|
18
|
-
|
|
17
|
+
import type { FlowrConfigOptions } from '../config';
|
|
18
|
+
export interface SemanticCfgGuidedVisitorConfiguration<OtherInfo = NoInfo, ControlFlow extends ControlFlowInformation = ControlFlowInformation, Ast extends NormalizedAst<OtherInfo> = NormalizedAst<OtherInfo>, Dfg extends DataflowGraph = DataflowGraph> extends DataflowCfgGuidedVisitorConfiguration<ControlFlow, Dfg>, SyntaxCfgGuidedVisitorConfiguration<OtherInfo, ControlFlow, Ast> {
|
|
19
|
+
readonly flowrConfig: FlowrConfigOptions;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
22
|
* This visitor extends on the {@link DataflowAwareCfgGuidedVisitor} by dispatching visitors for separate function calls as well,
|
|
@@ -40,7 +41,7 @@ export interface SemanticCfgGuidedVisitorConfiguration<OtherInfo = NoInfo, Cfg e
|
|
|
40
41
|
*
|
|
41
42
|
* Use {@link BasicCfgGuidedVisitor#start} to start the traversal.
|
|
42
43
|
*/
|
|
43
|
-
export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo,
|
|
44
|
+
export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, ControlFlow extends ControlFlowInformation = ControlFlowInformation, Ast extends NormalizedAst<OtherInfo> = NormalizedAst<OtherInfo>, Dfg extends DataflowGraph = DataflowGraph, Config extends SemanticCfgGuidedVisitorConfiguration<OtherInfo, ControlFlow, Ast, Dfg> = SemanticCfgGuidedVisitorConfiguration<OtherInfo, ControlFlow, Ast, Dfg>> extends DataflowAwareCfgGuidedVisitor<ControlFlow, Dfg, Config> {
|
|
44
45
|
/**
|
|
45
46
|
* A helper function to get the normalized AST node for the given id or fail if it does not exist.
|
|
46
47
|
*/
|
|
@@ -117,12 +118,21 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, Cfg extends Co
|
|
|
117
118
|
* @protected
|
|
118
119
|
*/
|
|
119
120
|
protected onDispatchFunctionCallOrigin(call: DataflowGraphVertexFunctionCall, origin: keyof typeof BuiltInProcessorMapper | string): void;
|
|
121
|
+
/**
|
|
122
|
+
* This event is called for the root program node, i.e., the program that is being analyzed.
|
|
123
|
+
*
|
|
124
|
+
* @protected
|
|
125
|
+
*/
|
|
120
126
|
protected onProgram(_data: RExpressionList<OtherInfo>): void;
|
|
121
127
|
/**
|
|
122
128
|
* A helper function to request the {@link getOriginInDfg|origins} of the given node.
|
|
123
129
|
*/
|
|
124
130
|
protected getOrigins(id: NodeId): Origin[] | undefined;
|
|
125
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* Called for every occurrence of a `NULL` in the program.
|
|
133
|
+
*
|
|
134
|
+
* For other symbols that are not referenced as a variable, see {@link SemanticCfgGuidedVisitor#onSymbolConstant|`onSymbolConstant`}.
|
|
135
|
+
*/
|
|
126
136
|
protected onNullConstant(_data: {
|
|
127
137
|
vertex: DataflowGraphVertexValue;
|
|
128
138
|
node: RSymbol<OtherInfo & ParentInformation, 'NULL'>;
|
|
@@ -154,6 +164,18 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, Cfg extends Co
|
|
|
154
164
|
vertex: DataflowGraphVertexValue;
|
|
155
165
|
node: RLogical;
|
|
156
166
|
}): void;
|
|
167
|
+
/**
|
|
168
|
+
* Called for every constant symbol value in the program.
|
|
169
|
+
*
|
|
170
|
+
* For example, `foo` in `library(foo)` or `a` in `l$a`. This most likely happens as part of non-standard-evaluation, i.e., the symbol is not evaluated to a value,
|
|
171
|
+
* but used as a symbol in and of itself.
|
|
172
|
+
*
|
|
173
|
+
* Please note, that due to its special behaviors, `NULL` is handled in {@link SemanticCfgGuidedVisitor#onNullConstant|`onNullConstant`} and not here.
|
|
174
|
+
*/
|
|
175
|
+
protected onSymbolConstant(_data: {
|
|
176
|
+
vertex: DataflowGraphVertexValue;
|
|
177
|
+
node: RSymbol;
|
|
178
|
+
}): void;
|
|
157
179
|
/**
|
|
158
180
|
* Called for every variable that is read within the program.
|
|
159
181
|
* You can use {@link getOrigins} to get the origins of the variable.
|
|
@@ -180,6 +202,7 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, Cfg extends Co
|
|
|
180
202
|
*/
|
|
181
203
|
protected onFunctionDefinition(_data: {
|
|
182
204
|
vertex: DataflowGraphVertexFunctionDefinition;
|
|
205
|
+
parameters?: readonly NodeId[];
|
|
183
206
|
}): void;
|
|
184
207
|
/**
|
|
185
208
|
* This event triggers for every anonymous call within the program.
|
|
@@ -211,7 +234,7 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, Cfg extends Co
|
|
|
211
234
|
*
|
|
212
235
|
* This explicitly will not trigger for scenarios in which the function has no name (i.e., if it is anonymous).
|
|
213
236
|
* For such cases, you may rely on the {@link SemanticCfgGuidedVisitor#onUnnamedCall|`onUnnamedCall`} event.
|
|
214
|
-
* The main reason for this separation is part of flowR's handling of these functions, as
|
|
237
|
+
* The main reason for this separation is part of flowR's handling of these functions, as anonymous calls cannot be resolved using the active environment.
|
|
215
238
|
*
|
|
216
239
|
* @protected
|
|
217
240
|
*/
|
|
@@ -282,9 +305,9 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, Cfg extends Co
|
|
|
282
305
|
*/
|
|
283
306
|
protected onIfThenElseCall(_data: {
|
|
284
307
|
call: DataflowGraphVertexFunctionCall;
|
|
285
|
-
condition:
|
|
286
|
-
then:
|
|
287
|
-
else:
|
|
308
|
+
condition: NodeId | undefined;
|
|
309
|
+
then: NodeId | undefined;
|
|
310
|
+
else: NodeId | undefined;
|
|
288
311
|
}): void;
|
|
289
312
|
/**
|
|
290
313
|
* This event triggers for every call to the `get` function, which is used to access variables in the global environment.
|
|
@@ -346,6 +369,8 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, Cfg extends Co
|
|
|
346
369
|
*/
|
|
347
370
|
protected onSpecialBinaryOpCall(_data: {
|
|
348
371
|
call: DataflowGraphVertexFunctionCall;
|
|
372
|
+
lhs?: FunctionArgument;
|
|
373
|
+
rhs?: FunctionArgument;
|
|
349
374
|
}): void;
|
|
350
375
|
/**
|
|
351
376
|
* This event triggers for every call to R's pipe operator, i.e., for every call to `|>`.
|
|
@@ -354,6 +379,8 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, Cfg extends Co
|
|
|
354
379
|
*/
|
|
355
380
|
protected onPipeCall(_data: {
|
|
356
381
|
call: DataflowGraphVertexFunctionCall;
|
|
382
|
+
lhs?: FunctionArgument;
|
|
383
|
+
rhs?: FunctionArgument;
|
|
357
384
|
}): void;
|
|
358
385
|
/**
|
|
359
386
|
* This event triggers for every call to the `quote` function, which is used to quote expressions.
|