@eagleoutice/flowr 2.2.12 → 2.2.13
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 +82 -20
- package/benchmark/slicer.js +2 -2
- package/benchmark/summarizer/first-phase/input.js +1 -1
- package/benchmark/summarizer/first-phase/process.js +3 -3
- package/benchmark/summarizer/second-phase/process.js +1 -1
- package/benchmark/summarizer/summarizer.js +1 -1
- package/cli/common/options.js +4 -4
- package/cli/common/script.js +1 -1
- package/cli/flowr.js +1 -1
- package/cli/repl/commands/repl-cfg.d.ts +2 -0
- package/cli/repl/commands/repl-cfg.js +38 -24
- package/cli/repl/commands/repl-commands.js +4 -2
- package/cli/repl/commands/repl-dataflow.js +3 -3
- package/cli/repl/commands/repl-execute.js +1 -1
- package/cli/repl/commands/repl-main.d.ts +1 -1
- package/cli/repl/commands/repl-main.js +1 -1
- package/cli/repl/commands/repl-normalize.js +1 -1
- package/cli/repl/commands/repl-query.js +2 -2
- package/cli/repl/core.js +1 -1
- package/cli/repl/prompt.js +1 -1
- package/cli/repl/server/connection.js +4 -4
- package/cli/repl/server/messages/message-analysis.d.ts +1 -1
- package/cli/script-core/statistics-core.js +1 -1
- package/cli/script-core/statistics-helper-core.js +4 -4
- package/config.d.ts +47 -24
- package/config.js +3 -3
- package/control-flow/basic-cfg-guided-visitor.d.ts +39 -0
- package/control-flow/basic-cfg-guided-visitor.js +114 -0
- package/control-flow/cfg-properties.d.ts +26 -0
- package/control-flow/cfg-properties.js +100 -0
- package/control-flow/cfg-simplification.d.ts +18 -0
- package/control-flow/cfg-simplification.js +55 -0
- package/control-flow/cfg-to-basic-blocks.d.ts +5 -0
- package/control-flow/cfg-to-basic-blocks.js +81 -0
- package/control-flow/control-flow-graph.d.ts +247 -0
- package/control-flow/control-flow-graph.js +290 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +32 -0
- package/control-flow/dfg-cfg-guided-visitor.js +71 -0
- package/control-flow/diff-cfg.d.ts +11 -0
- package/control-flow/diff-cfg.js +161 -0
- package/control-flow/extract-cfg.d.ts +30 -0
- package/control-flow/extract-cfg.js +475 -0
- package/control-flow/happens-before.d.ts +7 -0
- package/{util/cfg → control-flow}/happens-before.js +3 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +452 -0
- package/control-flow/semantic-cfg-guided-visitor.js +492 -0
- package/control-flow/simple-visitor.d.ts +25 -0
- package/control-flow/simple-visitor.js +80 -0
- package/control-flow/syntax-cfg-guided-visitor.d.ts +128 -0
- package/control-flow/syntax-cfg-guided-visitor.js +166 -0
- package/core/print/print.d.ts +1 -1
- package/core/print/slice-diff-ansi.js +1 -1
- package/core/steps/pipeline/create-pipeline.js +1 -1
- package/dataflow/environments/built-in-config.js +9 -6
- package/dataflow/environments/built-in.d.ts +8 -4
- package/dataflow/environments/built-in.js +47 -5
- package/dataflow/environments/default-builtin-config.d.ts +2 -0
- package/dataflow/environments/default-builtin-config.js +81 -14
- package/dataflow/environments/resolve-by-name.js +15 -4
- package/dataflow/extractor.js +2 -2
- package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
- package/dataflow/graph/dataflowgraph-builder.js +4 -2
- package/dataflow/graph/diff-dataflow-graph.d.ts +16 -0
- package/dataflow/graph/{diff.js → diff-dataflow-graph.js} +30 -56
- package/dataflow/graph/graph.d.ts +11 -3
- package/dataflow/graph/graph.js +27 -12
- package/dataflow/graph/vertex.d.ts +17 -2
- package/dataflow/internal/linker.d.ts +3 -2
- package/dataflow/internal/linker.js +33 -24
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +1 -1
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +12 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +84 -16
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +23 -16
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +5 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +15 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-get.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-library.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +9 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +19 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +19 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +3 -3
- package/dataflow/internal/process/functions/call/common.d.ts +4 -1
- package/dataflow/internal/process/functions/call/common.js +5 -3
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +3 -2
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
- package/dataflow/internal/process/functions/call/named-call-handling.js +1 -1
- package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -0
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -4
- package/dataflow/internal/process/process-named-call.d.ts +1 -1
- package/dataflow/internal/process/process-named-call.js +5 -5
- package/dataflow/origin/dfg-get-origin.d.ts +82 -0
- package/dataflow/origin/dfg-get-origin.js +116 -0
- package/documentation/doc-util/doc-cfg.d.ts +13 -6
- package/documentation/doc-util/doc-cfg.js +19 -14
- package/documentation/doc-util/doc-cli-option.js +4 -2
- package/documentation/doc-util/doc-dfg.js +3 -3
- package/documentation/doc-util/doc-escape.d.ts +7 -0
- package/documentation/doc-util/doc-escape.js +19 -0
- package/documentation/doc-util/doc-files.d.ts +1 -0
- package/documentation/doc-util/doc-files.js +2 -1
- package/documentation/doc-util/doc-normalized-ast.js +3 -3
- package/documentation/doc-util/doc-query.js +2 -2
- package/documentation/doc-util/doc-repl.js +1 -1
- package/documentation/doc-util/doc-search.js +1 -1
- package/documentation/doc-util/doc-server-message.js +2 -2
- package/documentation/doc-util/doc-structure.d.ts +1 -0
- package/documentation/doc-util/doc-structure.js +5 -0
- package/documentation/doc-util/doc-types.d.ts +7 -1
- package/documentation/doc-util/doc-types.js +13 -2
- package/documentation/print-capabilities-markdown.js +27 -1
- package/documentation/print-cfg-wiki.js +505 -17
- package/documentation/print-dataflow-graph-wiki.js +180 -25
- package/documentation/print-engines-wiki.js +1 -1
- package/documentation/print-faq-wiki.d.ts +1 -0
- package/documentation/print-faq-wiki.js +75 -0
- package/documentation/print-interface-wiki.js +1 -1
- package/documentation/print-linting-and-testing-wiki.js +52 -36
- package/documentation/print-normalized-ast-wiki.js +1 -1
- package/documentation/print-onboarding-wiki.d.ts +1 -0
- package/documentation/print-onboarding-wiki.js +42 -0
- package/documentation/print-query-wiki.js +21 -1
- package/documentation/print-readme.js +10 -3
- package/package.json +9 -6
- package/queries/catalog/call-context-query/call-context-query-executor.js +5 -5
- 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 +2 -2
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -2
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +24 -21
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
- package/queries/catalog/cluster-query/cluster-query-format.js +1 -1
- package/queries/catalog/config-query/config-query-format.d.ts +1 -1
- package/queries/catalog/config-query/config-query-format.js +2 -2
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +2 -2
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.js +2 -2
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -2
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -2
- package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-executor.js +4 -4
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-format.js +2 -2
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.js +2 -2
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.js +2 -2
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +1 -1
- package/queries/catalog/location-map-query/location-map-query-format.js +2 -2
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +2 -2
- package/queries/catalog/origin-query/origin-query-executor.d.ts +5 -0
- package/queries/catalog/origin-query/origin-query-executor.js +33 -0
- package/queries/catalog/origin-query/origin-query-format.d.ts +71 -0
- package/queries/catalog/origin-query/origin-query-format.js +27 -0
- package/queries/catalog/project-query/project-query-format.d.ts +1 -1
- package/queries/catalog/project-query/project-query-format.js +2 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -2
- package/queries/catalog/search-query/search-query-format.d.ts +1 -1
- package/queries/catalog/search-query/search-query-format.js +2 -2
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-format.js +2 -2
- package/queries/query-print.d.ts +1 -1
- package/queries/query-print.js +4 -4
- package/queries/query.d.ts +61 -2
- package/queries/query.js +3 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +5 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +5 -0
- package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/model/processing/decorate.js +1 -1
- package/r-bridge/lang-4.x/ast/model/processing/fold.js +3 -1
- package/r-bridge/lang-4.x/ast/model/processing/stateful-fold.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-call.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-definition.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/normalize-access.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-binary.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-symbol.js +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +2 -2
- 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.js +26 -8
- package/r-bridge/retriever.js +1 -1
- package/search/search-executor/search-generators.d.ts +1 -1
- package/search/search-executor/search-transformer.d.ts +1 -1
- package/slicing/criterion/collect-all.js +1 -1
- package/slicing/static/slice-call.js +13 -3
- package/statistics/features/supported/assignments/post-process.js +1 -1
- package/statistics/features/supported/defined-functions/post-process.js +2 -2
- package/statistics/features/supported/used-functions/post-process.js +1 -1
- package/statistics/features/supported/used-packages/post-process.js +2 -2
- package/statistics/features/supported/values/post-process.js +2 -2
- package/statistics/output/print-stats.js +2 -2
- package/statistics/summarizer/post-process/clusterer.d.ts +1 -1
- package/statistics/summarizer/post-process/clusterer.js +1 -1
- package/statistics/summarizer/post-process/histogram.js +3 -3
- package/statistics/summarizer/post-process/post-process-output.js +3 -3
- package/statistics/summarizer/second-phase/process.js +2 -2
- package/statistics/summarizer/summarizer.js +2 -2
- package/util/assert.js +36 -1
- package/util/cfg/cfg.d.ts +0 -80
- package/util/cfg/cfg.js +0 -549
- package/util/{arrays.d.ts → collections/arrays.d.ts} +1 -1
- package/util/{arrays.js → collections/arrays.js} +3 -3
- package/util/collections/set.js +17 -0
- package/util/diff-graph.d.ts +47 -0
- package/util/diff-graph.js +61 -0
- package/util/diff.d.ts +6 -6
- package/util/diff.js +1 -1
- package/util/mermaid/cfg.d.ts +9 -2
- package/util/mermaid/cfg.js +64 -12
- package/util/mermaid/dfg.d.ts +2 -1
- package/util/mermaid/dfg.js +26 -10
- package/util/mermaid/mermaid.d.ts +2 -0
- package/util/mermaid/mermaid.js +6 -0
- package/util/quads.js +1 -1
- package/util/schema.d.ts +1 -1
- package/util/schema.js +1 -1
- package/util/summarizer.js +1 -1
- package/util/{text.js → text/text.js} +1 -1
- package/util/{time.js → text/time.js} +1 -1
- package/util/version.js +1 -1
- package/dataflow/graph/diff.d.ts +0 -36
- package/util/cfg/happens-before.d.ts +0 -7
- package/util/cfg/visitor.d.ts +0 -9
- package/util/cfg/visitor.js +0 -30
- package/util/set.js +0 -31
- /package/util/{bimap.d.ts → collections/bimap.d.ts} +0 -0
- /package/util/{bimap.js → collections/bimap.js} +0 -0
- /package/util/{defaultmap.d.ts → collections/defaultmap.d.ts} +0 -0
- /package/util/{defaultmap.js → collections/defaultmap.js} +0 -0
- /package/util/{set.d.ts → collections/set.d.ts} +0 -0
- /package/util/{ansi.d.ts → text/ansi.d.ts} +0 -0
- /package/util/{ansi.js → text/ansi.js} +0 -0
- /package/util/{args.d.ts → text/args.d.ts} +0 -0
- /package/util/{args.js → text/args.js} +0 -0
- /package/util/{strings.d.ts → text/strings.d.ts} +0 -0
- /package/util/{strings.js → text/strings.js} +0 -0
- /package/util/{text.d.ts → text/text.d.ts} +0 -0
- /package/util/{time.d.ts → text/time.d.ts} +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
|
+
import type { MergeableRecord } from '../util/objects';
|
|
3
|
+
import type { RFalse, RTrue } from '../r-bridge/lang-4.x/convert-values';
|
|
4
|
+
export declare enum CfgVertexType {
|
|
5
|
+
/** Marks a break point in a construct (e.g., between the name and the value of an argument, or the formals and the body of a function) */
|
|
6
|
+
MidMarker = "mid",
|
|
7
|
+
/** The explicit exit-nodes to ensure the hammock property */
|
|
8
|
+
EndMarker = "end",
|
|
9
|
+
/** something like an if, assignment, ... even though in the classical sense of R they are still expressions */
|
|
10
|
+
Statement = "stm",
|
|
11
|
+
/** something like an addition, ... */
|
|
12
|
+
Expression = "expr",
|
|
13
|
+
/** a (as far as R allows this) 'basic' block */
|
|
14
|
+
Block = "blk"
|
|
15
|
+
}
|
|
16
|
+
export declare const enum CfgEdgeType {
|
|
17
|
+
/** a flow dependency */
|
|
18
|
+
Fd = 0,
|
|
19
|
+
/** a control dependency */
|
|
20
|
+
Cd = 1
|
|
21
|
+
}
|
|
22
|
+
export declare function edgeTypeToString(type: CfgEdgeType): string;
|
|
23
|
+
/**
|
|
24
|
+
* A plain vertex in the {@link ControlFlowGraph}.
|
|
25
|
+
* Please use {@link CfgSimpleVertex} to refer to all potential vertex types within the graph.
|
|
26
|
+
*/
|
|
27
|
+
interface CfgBaseVertex extends MergeableRecord {
|
|
28
|
+
/** the type of the vertex */
|
|
29
|
+
type: CfgVertexType;
|
|
30
|
+
/** the id of the vertex, for non-blocks this should directly relate to the AST node */
|
|
31
|
+
id: NodeId;
|
|
32
|
+
/** child nodes attached to this one */
|
|
33
|
+
children?: NodeId[];
|
|
34
|
+
/** if the vertex calls a function, this links all targets of this call */
|
|
35
|
+
callTargets?: Set<NodeId>;
|
|
36
|
+
}
|
|
37
|
+
interface CfgWithMarker extends CfgBaseVertex {
|
|
38
|
+
/** mid-markers linked to this statement */
|
|
39
|
+
mid?: NodeId[];
|
|
40
|
+
/** end-markers linked to this statement */
|
|
41
|
+
end?: NodeId[];
|
|
42
|
+
}
|
|
43
|
+
export interface CfgStatementVertex extends CfgWithMarker {
|
|
44
|
+
type: CfgVertexType.Statement;
|
|
45
|
+
}
|
|
46
|
+
export interface CfgExpressionVertex extends CfgWithMarker {
|
|
47
|
+
type: CfgVertexType.Expression;
|
|
48
|
+
}
|
|
49
|
+
export interface CfgWithRoot extends CfgBaseVertex {
|
|
50
|
+
/** the vertex for which this is a marker */
|
|
51
|
+
root: NodeId;
|
|
52
|
+
}
|
|
53
|
+
export interface CfgMidMarkerVertex extends CfgWithRoot {
|
|
54
|
+
type: CfgVertexType.MidMarker;
|
|
55
|
+
kind: string;
|
|
56
|
+
}
|
|
57
|
+
export interface CfgEndMarkerVertex extends CfgWithRoot {
|
|
58
|
+
type: CfgVertexType.EndMarker;
|
|
59
|
+
}
|
|
60
|
+
export interface CfgBasicBlockVertex extends CfgBaseVertex {
|
|
61
|
+
type: CfgVertexType.Block;
|
|
62
|
+
/** The vertices that are part of this block, only connected by FDs, vertices should never occur in multiple bbs */
|
|
63
|
+
elems: readonly Exclude<CfgSimpleVertex, CfgBasicBlockVertex>[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A vertex in the {@link ControlFlowGraph}.
|
|
67
|
+
*/
|
|
68
|
+
export type CfgSimpleVertex = CfgStatementVertex | CfgExpressionVertex | CfgBasicBlockVertex | CfgMidMarkerVertex | CfgEndMarkerVertex;
|
|
69
|
+
export declare function equalVertex(a: CfgSimpleVertex, b: CfgSimpleVertex): boolean;
|
|
70
|
+
interface CfgFlowDependencyEdge extends MergeableRecord {
|
|
71
|
+
label: CfgEdgeType.Fd;
|
|
72
|
+
}
|
|
73
|
+
interface CfgControlDependencyEdge extends MergeableRecord {
|
|
74
|
+
label: CfgEdgeType.Cd;
|
|
75
|
+
/** the id which caused the control dependency */
|
|
76
|
+
caused: NodeId;
|
|
77
|
+
/** is the control dependency satisfied with a true condition or is it negated (e.g., else-branch)? */
|
|
78
|
+
when: typeof RTrue | typeof RFalse;
|
|
79
|
+
}
|
|
80
|
+
export type CfgEdge = CfgFlowDependencyEdge | CfgControlDependencyEdge;
|
|
81
|
+
/**
|
|
82
|
+
* A read-only view of the {@link ControlFlowGraph}.
|
|
83
|
+
*/
|
|
84
|
+
export interface ReadOnlyControlFlowGraph {
|
|
85
|
+
/**
|
|
86
|
+
* Get all ids of the root vertices — vertices that are not part of
|
|
87
|
+
* any function definition or basic block and hence part of the "top-level" control flow.
|
|
88
|
+
*
|
|
89
|
+
* This is the pendant of {@link DataflowGraph#rootIds|rootIds()} on a {@link DataflowGraph}.
|
|
90
|
+
*
|
|
91
|
+
* @see {@link ReadOnlyControlFlowGraph#vertices|vertices()} - for a way to get all vertices in the graph.
|
|
92
|
+
* @see {@link ReadOnlyControlFlowGraph#getVertex|getVertex()} - for a way to get a specific vertex by its id.
|
|
93
|
+
* @see {@link ReadOnlyControlFlowGraph#edges|edges()} - for a way to get all edges in the graph.
|
|
94
|
+
*/
|
|
95
|
+
readonly rootIds: () => ReadonlySet<NodeId>;
|
|
96
|
+
/**
|
|
97
|
+
* Provide a view of all vertices in the graph.
|
|
98
|
+
*
|
|
99
|
+
* @param includeBasicBlockElements - if true, the elements of basic block elements are included in the result, otherwise this will only the basic blocks themselves
|
|
100
|
+
*
|
|
101
|
+
* @see {@link ReadOnlyControlFlowGraph#rootVertexIds|rootVertexIds()} - for a way to get the root vertices of the graph.
|
|
102
|
+
* @see {@link ReadOnlyControlFlowGraph#getVertex|getVertex()} - for a way to get a specific vertex by its id.
|
|
103
|
+
* @see {@link ReadOnlyControlFlowGraph#edges|edges()} - for a way to get all edges in the graph.
|
|
104
|
+
*/
|
|
105
|
+
readonly vertices: (includeBasicBlockElements: boolean) => ReadonlyMap<NodeId, CfgSimpleVertex>;
|
|
106
|
+
/**
|
|
107
|
+
* Get all edges in the graph, independent of their sources and targets.
|
|
108
|
+
* If you are only interested in the edges of a specific node, please use {@link ReadOnlyControlFlowGraph#outgoingEdges|outgoingEdges()} or {@link ReadOnlyControlFlowGraph#ingoingEdges|ingoingEdges()}.
|
|
109
|
+
*
|
|
110
|
+
* This is the pendant of {@link DataflowGraph#edges|edges()} on a {@link DataflowGraph}.
|
|
111
|
+
*/
|
|
112
|
+
readonly edges: () => ReadonlyMap<NodeId, ReadonlyMap<NodeId, CfgEdge>>;
|
|
113
|
+
/**
|
|
114
|
+
* Receive all outgoing edges of a given vertex.
|
|
115
|
+
*
|
|
116
|
+
* This is the pendant of {@link DataflowGraph#ingoingEdges|ingoingEdges()} on a {@link DataflowGraph}.
|
|
117
|
+
*
|
|
118
|
+
* @see {@link ReadOnlyControlFlowGraph#ingoingEdges|ingoingEdges()} - for a way to get all ingoing edges of a vertex.
|
|
119
|
+
*/
|
|
120
|
+
readonly outgoingEdges: (id: NodeId) => ReadonlyMap<NodeId, CfgEdge> | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* Receive all ingoing edges of a given vertex.
|
|
123
|
+
*
|
|
124
|
+
* This is the pendant of {@link DataflowGraph#outgoingEdges|outgoingEdges()} on a {@link DataflowGraph}.
|
|
125
|
+
*
|
|
126
|
+
* @see {@link ReadOnlyControlFlowGraph#outgoingEdges|outgoingEdges()} - for a way to get all outgoing edges of a vertex.
|
|
127
|
+
*/
|
|
128
|
+
readonly ingoingEdges: (id: NodeId) => ReadonlyMap<NodeId, CfgEdge> | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* Retrieve a vertex by its id.
|
|
131
|
+
*
|
|
132
|
+
* @param id - the id of the vertex to retrieve
|
|
133
|
+
* @param includeBlocks - if true, the elements of basic block elements are included in the result, otherwise this will only the basic blocks themselves
|
|
134
|
+
*
|
|
135
|
+
* This is the pendant of {@link DataflowGraph#getVertex|getVertex()} on a {@link DataflowGraph}.
|
|
136
|
+
*/
|
|
137
|
+
readonly getVertex: (id: NodeId, includeBlocks?: boolean) => CfgSimpleVertex | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* Check if a vertex with the given id exists in the graph.
|
|
140
|
+
*
|
|
141
|
+
* @param id - the id of the vertex to check
|
|
142
|
+
* @param includeBlocks - if true, the elements of basic block elements are included in the check, otherwise this will only check the basic blocks themselves
|
|
143
|
+
*
|
|
144
|
+
* This is the pendant of {@link DataflowGraph#hasVertex|hasVertex()} on a {@link DataflowGraph}.
|
|
145
|
+
*/
|
|
146
|
+
readonly hasVertex: (id: NodeId, includeBlocks?: boolean) => boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Obtain the basic block associated with the given element id (i.e. if this is an element within a basic block, return the blockit belongs to).
|
|
149
|
+
*/
|
|
150
|
+
readonly getBasicBlock: (elemId: NodeId) => CfgBasicBlockVertex | undefined;
|
|
151
|
+
/**
|
|
152
|
+
* Returns true if the graph may contain basic blocks and false if we know that it does not.
|
|
153
|
+
* This can be used for optimizations.
|
|
154
|
+
*/
|
|
155
|
+
readonly mayHaveBasicBlocks: () => boolean;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* This class represents the control flow graph of an R program.
|
|
159
|
+
* The control flow may be hierarchical when confronted with function definitions (see {@link CfgSimpleVertex} and {@link CFG#rootVertexIds|rootVertexIds()}).
|
|
160
|
+
*
|
|
161
|
+
* There are two very simple visitors to traverse a CFG:
|
|
162
|
+
* - {@link visitCfgInOrder} visits the graph in the order of the vertices
|
|
163
|
+
* - {@link visitCfgInReverseOrder} visits the graph in reverse order
|
|
164
|
+
*
|
|
165
|
+
* If you want to prohibit modification, please refer to the {@link ReadOnlyControlFlowGraph} interface.
|
|
166
|
+
*/
|
|
167
|
+
export declare class ControlFlowGraph<Vertex extends CfgSimpleVertex = CfgSimpleVertex> implements ReadOnlyControlFlowGraph {
|
|
168
|
+
private readonly rootVertices;
|
|
169
|
+
private readonly vertexInformation;
|
|
170
|
+
/** 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
|
+
private readonly bbChildren;
|
|
172
|
+
/** basic block agnostic edges */
|
|
173
|
+
private readonly edgeInformation;
|
|
174
|
+
/** used as an optimization to avoid unnecessary lookups */
|
|
175
|
+
private _mayHaveBasicBlocks;
|
|
176
|
+
/**
|
|
177
|
+
* Add a new vertex to the control flow graph.
|
|
178
|
+
*
|
|
179
|
+
* @see {@link ControlFlowGraph#addEdge|addEdge()} - to add an edge
|
|
180
|
+
*/
|
|
181
|
+
addVertex(vertex: Vertex, rootVertex?: boolean): this;
|
|
182
|
+
/**
|
|
183
|
+
* Add a new edge to the control flow graph.
|
|
184
|
+
*
|
|
185
|
+
* @see {@link ControlFlowGraph#addVertex|addVertex()} - to add vertices
|
|
186
|
+
* @see {@link ControlFlowGraph#addEdges|addEdges()} - to add multiple edges at once
|
|
187
|
+
*/
|
|
188
|
+
addEdge(from: NodeId, to: NodeId, edge: CfgEdge): this;
|
|
189
|
+
/**
|
|
190
|
+
* Add multiple edges from a given source vertex to the control flow graph.
|
|
191
|
+
*/
|
|
192
|
+
addEdges(from: NodeId, to: Map<NodeId, CfgEdge>): this;
|
|
193
|
+
outgoingEdges(node: NodeId): ReadonlyMap<NodeId, CfgEdge> | undefined;
|
|
194
|
+
ingoingEdges(id: NodeId): ReadonlyMap<NodeId, CfgEdge> | undefined;
|
|
195
|
+
rootIds(): ReadonlySet<NodeId>;
|
|
196
|
+
vertices(includeBasicBlockElements?: boolean): ReadonlyMap<NodeId, CfgSimpleVertex>;
|
|
197
|
+
getBasicBlock(elemId: NodeId): CfgBasicBlockVertex | undefined;
|
|
198
|
+
edges(): ReadonlyMap<NodeId, ReadonlyMap<NodeId, CfgEdge>>;
|
|
199
|
+
/**
|
|
200
|
+
* Retrieve a vertex by its id.
|
|
201
|
+
*/
|
|
202
|
+
getVertex(id: NodeId, includeBlocks?: boolean): CfgSimpleVertex | undefined;
|
|
203
|
+
hasVertex(id: NodeId, includeBlocks?: boolean): boolean;
|
|
204
|
+
mayHaveBasicBlocks(): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* This removes the vertex and all edges to and from it.
|
|
207
|
+
* @param id - the id of the vertex to remove
|
|
208
|
+
*
|
|
209
|
+
* @see {@link ControlFlowGraph#addVertex|addVertex()} - to add a vertex
|
|
210
|
+
* @see {@link ControlFlowGraph#removeEdge|removeEdge()} - to remove a specific edge
|
|
211
|
+
*/
|
|
212
|
+
removeVertex(id: NodeId): this;
|
|
213
|
+
/**
|
|
214
|
+
* Removes a all direct edges between `from` and `to` from the control flow graph.
|
|
215
|
+
*
|
|
216
|
+
* @see {@link ControlFlowGraph#addEdge|addEdge()} - to add an edge
|
|
217
|
+
* @see {@link ControlFlowGraph#removeVertex|removeVertex()} - to remove a vertex and all its edges
|
|
218
|
+
*/
|
|
219
|
+
removeEdge(from: NodeId, to: NodeId): this;
|
|
220
|
+
/** merges b into a */
|
|
221
|
+
mergeTwoBasicBlocks(a: NodeId, b: NodeId): this;
|
|
222
|
+
/**
|
|
223
|
+
* Merge another control flow graph into this one.
|
|
224
|
+
* @param other - the other control flow graph to merge into this one
|
|
225
|
+
* @param forceNested - should the other graph be assumed to be fully nested (e.g., within a function definition).
|
|
226
|
+
*
|
|
227
|
+
* This is the pendant of {@link DataflowGraph#mergeWith|mergeWith()} on a {@link DataflowGraph}.
|
|
228
|
+
*/
|
|
229
|
+
mergeWith(other: ControlFlowGraph<Vertex>, forceNested?: boolean): this;
|
|
230
|
+
}
|
|
231
|
+
/** Summarizes the control information of a program */
|
|
232
|
+
export interface ControlFlowInformation<Vertex extends CfgSimpleVertex = CfgSimpleVertex> extends MergeableRecord {
|
|
233
|
+
/** all active 'return'(-like) unconditional jumps */
|
|
234
|
+
returns: NodeId[];
|
|
235
|
+
/** all active 'break'(-like) unconditional jumps */
|
|
236
|
+
breaks: NodeId[];
|
|
237
|
+
/** all active 'next'(-like) unconditional jumps */
|
|
238
|
+
nexts: NodeId[];
|
|
239
|
+
/** intended to construct a hammock graph, with 0 exit points representing a block that should not be part of the CFG (like a comment) */
|
|
240
|
+
entryPoints: NodeId[];
|
|
241
|
+
/** See {@link ControlFlowInformation#entryPoints|entryPoints} */
|
|
242
|
+
exitPoints: NodeId[];
|
|
243
|
+
/** the control flow graph summarizing the flow information */
|
|
244
|
+
graph: ControlFlowGraph<Vertex>;
|
|
245
|
+
}
|
|
246
|
+
export declare function emptyControlFlowInformation(): ControlFlowInformation;
|
|
247
|
+
export {};
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ControlFlowGraph = exports.CfgVertexType = void 0;
|
|
4
|
+
exports.edgeTypeToString = edgeTypeToString;
|
|
5
|
+
exports.equalVertex = equalVertex;
|
|
6
|
+
exports.emptyControlFlowInformation = emptyControlFlowInformation;
|
|
7
|
+
const assert_1 = require("../util/assert");
|
|
8
|
+
var CfgVertexType;
|
|
9
|
+
(function (CfgVertexType) {
|
|
10
|
+
/** Marks a break point in a construct (e.g., between the name and the value of an argument, or the formals and the body of a function) */
|
|
11
|
+
CfgVertexType["MidMarker"] = "mid";
|
|
12
|
+
/** The explicit exit-nodes to ensure the hammock property */
|
|
13
|
+
CfgVertexType["EndMarker"] = "end";
|
|
14
|
+
/** something like an if, assignment, ... even though in the classical sense of R they are still expressions */
|
|
15
|
+
CfgVertexType["Statement"] = "stm";
|
|
16
|
+
/** something like an addition, ... */
|
|
17
|
+
CfgVertexType["Expression"] = "expr";
|
|
18
|
+
/** a (as far as R allows this) 'basic' block */
|
|
19
|
+
CfgVertexType["Block"] = "blk";
|
|
20
|
+
})(CfgVertexType || (exports.CfgVertexType = CfgVertexType = {}));
|
|
21
|
+
function edgeTypeToString(type) {
|
|
22
|
+
switch (type) {
|
|
23
|
+
case 0 /* CfgEdgeType.Fd */:
|
|
24
|
+
return 'FD';
|
|
25
|
+
case 1 /* CfgEdgeType.Cd */:
|
|
26
|
+
return 'CD';
|
|
27
|
+
default:
|
|
28
|
+
throw new Error(`Unknown edge type ${JSON.stringify(type)}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function equalVertex(a, b) {
|
|
32
|
+
if (a.type !== b.type || a.id !== b.id) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
else if (a.type === CfgVertexType.Block && b.type === CfgVertexType.Block) {
|
|
36
|
+
return a.elems.length === b.elems.length && a.elems.every((e, i) => e.id === b.elems[i].id);
|
|
37
|
+
}
|
|
38
|
+
else if (a.type === CfgVertexType.MidMarker && b.type === CfgVertexType.MidMarker) {
|
|
39
|
+
return a.kind === b.kind && a.root === b.root;
|
|
40
|
+
}
|
|
41
|
+
else if (a.type === CfgVertexType.EndMarker && b.type === CfgVertexType.EndMarker) {
|
|
42
|
+
return a.root === b.root;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* This class represents the control flow graph of an R program.
|
|
48
|
+
* The control flow may be hierarchical when confronted with function definitions (see {@link CfgSimpleVertex} and {@link CFG#rootVertexIds|rootVertexIds()}).
|
|
49
|
+
*
|
|
50
|
+
* There are two very simple visitors to traverse a CFG:
|
|
51
|
+
* - {@link visitCfgInOrder} visits the graph in the order of the vertices
|
|
52
|
+
* - {@link visitCfgInReverseOrder} visits the graph in reverse order
|
|
53
|
+
*
|
|
54
|
+
* If you want to prohibit modification, please refer to the {@link ReadOnlyControlFlowGraph} interface.
|
|
55
|
+
*/
|
|
56
|
+
class ControlFlowGraph {
|
|
57
|
+
rootVertices = new Set();
|
|
58
|
+
vertexInformation = new Map();
|
|
59
|
+
/** 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
|
+
bbChildren = new Map();
|
|
61
|
+
/** basic block agnostic edges */
|
|
62
|
+
edgeInformation = new Map();
|
|
63
|
+
/** used as an optimization to avoid unnecessary lookups */
|
|
64
|
+
_mayHaveBasicBlocks = false;
|
|
65
|
+
/**
|
|
66
|
+
* Add a new vertex to the control flow graph.
|
|
67
|
+
*
|
|
68
|
+
* @see {@link ControlFlowGraph#addEdge|addEdge()} - to add an edge
|
|
69
|
+
*/
|
|
70
|
+
addVertex(vertex, rootVertex = true) {
|
|
71
|
+
(0, assert_1.guard)(!this.vertexInformation.has(vertex.id), `Node with id ${vertex.id} already exists`);
|
|
72
|
+
if (vertex.type === CfgVertexType.Block) {
|
|
73
|
+
this._mayHaveBasicBlocks = true;
|
|
74
|
+
if (vertex.elems.some(e => this.bbChildren.has(e.id) || this.rootVertices.has(e.id))) {
|
|
75
|
+
throw new Error(`Vertex ${vertex.id} contains vertices that are already part of the graph`);
|
|
76
|
+
}
|
|
77
|
+
for (const elem of vertex.elems) {
|
|
78
|
+
this.bbChildren.set(elem.id, vertex.id);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
this.vertexInformation.set(vertex.id, vertex);
|
|
82
|
+
if (rootVertex) {
|
|
83
|
+
this.rootVertices.add(vertex.id);
|
|
84
|
+
}
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Add a new edge to the control flow graph.
|
|
89
|
+
*
|
|
90
|
+
* @see {@link ControlFlowGraph#addVertex|addVertex()} - to add vertices
|
|
91
|
+
* @see {@link ControlFlowGraph#addEdges|addEdges()} - to add multiple edges at once
|
|
92
|
+
*/
|
|
93
|
+
addEdge(from, to, edge) {
|
|
94
|
+
const edgesFrom = this.edgeInformation.get(from) ?? new Map();
|
|
95
|
+
if (!this.edgeInformation.has(from)) {
|
|
96
|
+
this.edgeInformation.set(from, edgesFrom);
|
|
97
|
+
}
|
|
98
|
+
edgesFrom.set(to, edge);
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Add multiple edges from a given source vertex to the control flow graph.
|
|
103
|
+
*/
|
|
104
|
+
addEdges(from, to) {
|
|
105
|
+
const edgesFrom = this.edgeInformation.get(from) ?? new Map();
|
|
106
|
+
if (!this.edgeInformation.has(from)) {
|
|
107
|
+
this.edgeInformation.set(from, edgesFrom);
|
|
108
|
+
}
|
|
109
|
+
for (const [toId, edge] of to) {
|
|
110
|
+
edgesFrom.set(toId, edge);
|
|
111
|
+
}
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
outgoingEdges(node) {
|
|
115
|
+
return this.edgeInformation.get(node);
|
|
116
|
+
}
|
|
117
|
+
ingoingEdges(id) {
|
|
118
|
+
const edges = new Map();
|
|
119
|
+
for (const [source, outgoing] of this.edgeInformation.entries()) {
|
|
120
|
+
if (outgoing.has(id)) {
|
|
121
|
+
edges.set(source, outgoing.get(id));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return edges;
|
|
125
|
+
}
|
|
126
|
+
rootIds() {
|
|
127
|
+
return this.rootVertices;
|
|
128
|
+
}
|
|
129
|
+
vertices(includeBasicBlockElements = true) {
|
|
130
|
+
if (includeBasicBlockElements) {
|
|
131
|
+
const all = new Map(this.vertexInformation);
|
|
132
|
+
for (const [id, block] of this.bbChildren.entries()) {
|
|
133
|
+
const blockVertex = all.get(block);
|
|
134
|
+
if (blockVertex === undefined || blockVertex.type !== CfgVertexType.Block) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const elem = blockVertex.elems.find(e => e.id === id);
|
|
138
|
+
if (elem !== undefined) {
|
|
139
|
+
all.set(id, elem);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return all;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
return this.vertexInformation;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
getBasicBlock(elemId) {
|
|
149
|
+
const block = this.bbChildren.get(elemId);
|
|
150
|
+
if (block === undefined) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
const blockVertex = this.vertexInformation.get(block);
|
|
154
|
+
if (blockVertex === undefined || blockVertex.type !== CfgVertexType.Block) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
return blockVertex;
|
|
158
|
+
}
|
|
159
|
+
edges() {
|
|
160
|
+
return this.edgeInformation;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Retrieve a vertex by its id.
|
|
164
|
+
*/
|
|
165
|
+
getVertex(id, includeBlocks = true) {
|
|
166
|
+
const res = this.vertexInformation.get(id);
|
|
167
|
+
if (res || !includeBlocks) {
|
|
168
|
+
return res;
|
|
169
|
+
}
|
|
170
|
+
const block = this.bbChildren.get(id);
|
|
171
|
+
if (block === undefined) {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
const blockVertex = this.vertexInformation.get(block);
|
|
175
|
+
if (blockVertex === undefined || blockVertex.type !== CfgVertexType.Block) {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
blockVertex.elems.find(e => e.id === id);
|
|
179
|
+
}
|
|
180
|
+
hasVertex(id, includeBlocks = true) {
|
|
181
|
+
return this.vertexInformation.has(id) || (this._mayHaveBasicBlocks && includeBlocks && this.bbChildren.has(id));
|
|
182
|
+
}
|
|
183
|
+
mayHaveBasicBlocks() {
|
|
184
|
+
return this._mayHaveBasicBlocks;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* This removes the vertex and all edges to and from it.
|
|
188
|
+
* @param id - the id of the vertex to remove
|
|
189
|
+
*
|
|
190
|
+
* @see {@link ControlFlowGraph#addVertex|addVertex()} - to add a vertex
|
|
191
|
+
* @see {@link ControlFlowGraph#removeEdge|removeEdge()} - to remove a specific edge
|
|
192
|
+
*/
|
|
193
|
+
removeVertex(id) {
|
|
194
|
+
this.vertexInformation.delete(id);
|
|
195
|
+
this.edgeInformation.delete(id);
|
|
196
|
+
this.bbChildren.delete(id);
|
|
197
|
+
// remove all bbChildren with id as target
|
|
198
|
+
for (const [a, b] of this.bbChildren.entries()) {
|
|
199
|
+
if (b === id) {
|
|
200
|
+
this.bbChildren.delete(a);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const edges of this.edgeInformation.values()) {
|
|
204
|
+
edges.delete(id);
|
|
205
|
+
}
|
|
206
|
+
this.rootVertices.delete(id);
|
|
207
|
+
return this;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Removes a all direct edges between `from` and `to` from the control flow graph.
|
|
211
|
+
*
|
|
212
|
+
* @see {@link ControlFlowGraph#addEdge|addEdge()} - to add an edge
|
|
213
|
+
* @see {@link ControlFlowGraph#removeVertex|removeVertex()} - to remove a vertex and all its edges
|
|
214
|
+
*/
|
|
215
|
+
removeEdge(from, to) {
|
|
216
|
+
const edges = this.edgeInformation.get(from);
|
|
217
|
+
if (edges) {
|
|
218
|
+
edges.delete(to);
|
|
219
|
+
if (edges.size === 0) {
|
|
220
|
+
this.edgeInformation.delete(from);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
/** merges b into a */
|
|
226
|
+
mergeTwoBasicBlocks(a, b) {
|
|
227
|
+
const aVertex = this.getVertex(a);
|
|
228
|
+
const bVertex = this.getVertex(b);
|
|
229
|
+
if (!aVertex || !bVertex || aVertex.type !== CfgVertexType.Block || bVertex.type !== CfgVertexType.Block) {
|
|
230
|
+
return this;
|
|
231
|
+
}
|
|
232
|
+
const bElems = bVertex.elems;
|
|
233
|
+
aVertex.elems = aVertex.elems.concat(bElems);
|
|
234
|
+
// update cache
|
|
235
|
+
for (const elem of bElems) {
|
|
236
|
+
this.bbChildren.set(elem.id, a);
|
|
237
|
+
}
|
|
238
|
+
// drop all edges from a to b
|
|
239
|
+
this.removeEdge(a, b);
|
|
240
|
+
const bOutgoing = this.outgoingEdges(b);
|
|
241
|
+
this.removeVertex(b);
|
|
242
|
+
// reroute all edge from b to a
|
|
243
|
+
for (const [to, edge] of bOutgoing ?? []) {
|
|
244
|
+
this.addEdge(a, to, edge);
|
|
245
|
+
}
|
|
246
|
+
return this;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Merge another control flow graph into this one.
|
|
250
|
+
* @param other - the other control flow graph to merge into this one
|
|
251
|
+
* @param forceNested - should the other graph be assumed to be fully nested (e.g., within a function definition).
|
|
252
|
+
*
|
|
253
|
+
* This is the pendant of {@link DataflowGraph#mergeWith|mergeWith()} on a {@link DataflowGraph}.
|
|
254
|
+
*/
|
|
255
|
+
mergeWith(other, forceNested = false) {
|
|
256
|
+
this._mayHaveBasicBlocks ||= other._mayHaveBasicBlocks;
|
|
257
|
+
const roots = other.rootVertices;
|
|
258
|
+
if (this._mayHaveBasicBlocks) {
|
|
259
|
+
for (const [id, node] of other.vertexInformation) {
|
|
260
|
+
this.addVertex(node, forceNested ? false : roots.has(id));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
for (const [id, node] of other.vertexInformation) {
|
|
265
|
+
this.vertexInformation.set(id, node);
|
|
266
|
+
}
|
|
267
|
+
if (!forceNested) {
|
|
268
|
+
for (const root of roots) {
|
|
269
|
+
this.rootVertices.add(root);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
for (const [from, edges] of other.edgeInformation) {
|
|
274
|
+
this.addEdges(from, edges);
|
|
275
|
+
}
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
exports.ControlFlowGraph = ControlFlowGraph;
|
|
280
|
+
function emptyControlFlowInformation() {
|
|
281
|
+
return {
|
|
282
|
+
returns: [],
|
|
283
|
+
breaks: [],
|
|
284
|
+
nexts: [],
|
|
285
|
+
entryPoints: [],
|
|
286
|
+
exitPoints: [],
|
|
287
|
+
graph: new ControlFlowGraph()
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=control-flow-graph.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CfgExpressionVertex, CfgStatementVertex, ControlFlowInformation } from './control-flow-graph';
|
|
2
|
+
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
|
+
import type { DataflowInformation } from '../dataflow/info';
|
|
4
|
+
import type { DataflowGraphVertexArgument, DataflowGraphVertexFunctionCall, DataflowGraphVertexFunctionDefinition, DataflowGraphVertexUse, DataflowGraphVertexValue, DataflowGraphVertexVariableDefinition } from '../dataflow/graph/vertex';
|
|
5
|
+
import type { BasicCfgGuidedVisitorConfiguration } from './basic-cfg-guided-visitor';
|
|
6
|
+
import { BasicCfgGuidedVisitor } from './basic-cfg-guided-visitor';
|
|
7
|
+
export interface DataflowCfgGuidedVisitorConfiguration<Cfg extends ControlFlowInformation = ControlFlowInformation, Dfg extends DataflowInformation = DataflowInformation> extends BasicCfgGuidedVisitorConfiguration<Cfg> {
|
|
8
|
+
readonly dataflow: Dfg;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* This visitor extends on the {@link BasicCfgGuidedVisitor} by dispatching visitors based on the dataflow graph.
|
|
12
|
+
*
|
|
13
|
+
* Use {@link BasicCfgGuidedVisitor#start} to start the traversal.
|
|
14
|
+
*/
|
|
15
|
+
export declare class DataflowAwareCfgGuidedVisitor<Cfg extends ControlFlowInformation = ControlFlowInformation, Dfg extends DataflowInformation = DataflowInformation, Config extends DataflowCfgGuidedVisitorConfiguration<Cfg, Dfg> = DataflowCfgGuidedVisitorConfiguration<Cfg, Dfg>> extends BasicCfgGuidedVisitor<Cfg, Config> {
|
|
16
|
+
/**
|
|
17
|
+
* Get the dataflow graph vertex for the given id
|
|
18
|
+
*/
|
|
19
|
+
protected getDataflowGraph(id: NodeId): DataflowGraphVertexArgument | undefined;
|
|
20
|
+
protected onStatementNode(node: CfgStatementVertex): void;
|
|
21
|
+
protected onExpressionNode(node: CfgExpressionVertex): void;
|
|
22
|
+
private onExprOrStmtNode;
|
|
23
|
+
/**
|
|
24
|
+
* called for every cfg vertex that has no corresponding dataflow vertex.
|
|
25
|
+
*/
|
|
26
|
+
protected visitUnknown(_vertex: CfgStatementVertex | CfgExpressionVertex): void;
|
|
27
|
+
protected visitValue(_val: DataflowGraphVertexValue): void;
|
|
28
|
+
protected visitVariableUse(_use: DataflowGraphVertexUse): void;
|
|
29
|
+
protected visitVariableDefinition(_def: DataflowGraphVertexVariableDefinition): void;
|
|
30
|
+
protected visitFunctionDefinition(_def: DataflowGraphVertexFunctionDefinition): void;
|
|
31
|
+
protected visitFunctionCall(_call: DataflowGraphVertexFunctionCall): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DataflowAwareCfgGuidedVisitor = void 0;
|
|
4
|
+
const vertex_1 = require("../dataflow/graph/vertex");
|
|
5
|
+
const basic_cfg_guided_visitor_1 = require("./basic-cfg-guided-visitor");
|
|
6
|
+
const assert_1 = require("../util/assert");
|
|
7
|
+
/**
|
|
8
|
+
* This visitor extends on the {@link BasicCfgGuidedVisitor} by dispatching visitors based on the dataflow graph.
|
|
9
|
+
*
|
|
10
|
+
* Use {@link BasicCfgGuidedVisitor#start} to start the traversal.
|
|
11
|
+
*/
|
|
12
|
+
class DataflowAwareCfgGuidedVisitor extends basic_cfg_guided_visitor_1.BasicCfgGuidedVisitor {
|
|
13
|
+
/**
|
|
14
|
+
* Get the dataflow graph vertex for the given id
|
|
15
|
+
*/
|
|
16
|
+
getDataflowGraph(id) {
|
|
17
|
+
return this.config.dataflow.graph.getVertex(id);
|
|
18
|
+
}
|
|
19
|
+
onStatementNode(node) {
|
|
20
|
+
super.onStatementNode(node);
|
|
21
|
+
this.onExprOrStmtNode(node);
|
|
22
|
+
}
|
|
23
|
+
onExpressionNode(node) {
|
|
24
|
+
super.onExpressionNode(node);
|
|
25
|
+
this.onExprOrStmtNode(node);
|
|
26
|
+
}
|
|
27
|
+
onExprOrStmtNode(node) {
|
|
28
|
+
const dfgVertex = this.getDataflowGraph(node.id);
|
|
29
|
+
if (!dfgVertex) {
|
|
30
|
+
this.visitUnknown(node);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const tag = dfgVertex.tag;
|
|
34
|
+
switch (tag) {
|
|
35
|
+
case vertex_1.VertexType.Use:
|
|
36
|
+
this.visitVariableUse(dfgVertex);
|
|
37
|
+
break;
|
|
38
|
+
case vertex_1.VertexType.VariableDefinition:
|
|
39
|
+
this.visitVariableDefinition(dfgVertex);
|
|
40
|
+
break;
|
|
41
|
+
case vertex_1.VertexType.FunctionDefinition:
|
|
42
|
+
this.visitFunctionDefinition(dfgVertex);
|
|
43
|
+
break;
|
|
44
|
+
case vertex_1.VertexType.FunctionCall:
|
|
45
|
+
this.visitFunctionCall(dfgVertex);
|
|
46
|
+
break;
|
|
47
|
+
case vertex_1.VertexType.Value:
|
|
48
|
+
this.visitValue(dfgVertex);
|
|
49
|
+
break;
|
|
50
|
+
default:
|
|
51
|
+
(0, assert_1.assertUnreachable)(tag);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* called for every cfg vertex that has no corresponding dataflow vertex.
|
|
56
|
+
*/
|
|
57
|
+
visitUnknown(_vertex) {
|
|
58
|
+
}
|
|
59
|
+
visitValue(_val) {
|
|
60
|
+
}
|
|
61
|
+
visitVariableUse(_use) {
|
|
62
|
+
}
|
|
63
|
+
visitVariableDefinition(_def) {
|
|
64
|
+
}
|
|
65
|
+
visitFunctionDefinition(_def) {
|
|
66
|
+
}
|
|
67
|
+
visitFunctionCall(_call) {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.DataflowAwareCfgGuidedVisitor = DataflowAwareCfgGuidedVisitor;
|
|
71
|
+
//# sourceMappingURL=dfg-cfg-guided-visitor.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { NamedGraph } from '../util/diff-graph';
|
|
2
|
+
import { GraphDifferenceReport } from '../util/diff-graph';
|
|
3
|
+
import type { GenericDiffConfiguration } from '../util/diff';
|
|
4
|
+
import type { ControlFlowGraph } from './control-flow-graph';
|
|
5
|
+
/**
|
|
6
|
+
* Compare two control flow graphs and return a report on the differences.
|
|
7
|
+
* If you simply want to check whether they equal, use {@link GraphDifferenceReport#isEqual|`<result>.isEqual()`}.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link diffOfDataflowGraphs} - for dataflow graphs
|
|
10
|
+
*/
|
|
11
|
+
export declare function diffOfControlFlowGraphs(left: NamedGraph<ControlFlowGraph>, right: NamedGraph<ControlFlowGraph>, config?: Partial<GenericDiffConfiguration>): GraphDifferenceReport;
|