[FIR] Add renderer to .dot for control flow graph tests
This commit is contained in:
@@ -38,7 +38,8 @@ class Flow(
|
||||
to: DataFlowVariable,
|
||||
transform: ((UnapprovedFirDataFlowInfo) -> UnapprovedFirDataFlowInfo)? = null
|
||||
): Flow {
|
||||
if (isFrozen) copyForBuilding().copyNotApprovedFacts(from, to)
|
||||
if (isFrozen)
|
||||
return copyForBuilding().copyNotApprovedFacts(from, to, transform)
|
||||
var facts = if (from.isSynthetic) {
|
||||
notApprovedFacts.removeAll(from)
|
||||
} else {
|
||||
|
||||
+9
-3
@@ -22,8 +22,11 @@ import org.jetbrains.kotlin.utils.DFS
|
||||
private const val INDENT = " "
|
||||
private const val DEAD = "[DEAD]"
|
||||
|
||||
fun ControlFlowGraph.renderToStringBuilder(builder: StringBuilder) {
|
||||
val sortedNodes: List<CFGNode<*>> = DFS.topologicalOrder(
|
||||
|
||||
fun List<CFGNode<*>>.indicesMap(): Map<CFGNode<*>, Int> = mapIndexed { i, node -> node to i }.toMap()
|
||||
|
||||
fun ControlFlowGraph.sortNodes(): List<CFGNode<*>> {
|
||||
return DFS.topologicalOrder(
|
||||
nodes
|
||||
) {
|
||||
val result = if (it !is WhenBranchConditionExitNode || it.followingNodes.size < 2) {
|
||||
@@ -33,9 +36,12 @@ fun ControlFlowGraph.renderToStringBuilder(builder: StringBuilder) {
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fun ControlFlowGraph.renderToStringBuilder(builder: StringBuilder) {
|
||||
val sortedNodes = sortNodes()
|
||||
|
||||
val indices = sortedNodes.mapIndexed { i, node -> node to i }.toMap()
|
||||
val indices = sortedNodes.indicesMap()
|
||||
val notVisited = sortedNodes.toMutableSet()
|
||||
val maxLineNumberSize = sortedNodes.size.toString().length
|
||||
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
digraph binaryOperations_kt {
|
||||
subgraph test_1 {
|
||||
0 [shape=box label="Enter function test_1"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Enter when"];
|
||||
3 [shape=box label="Enter when branch condition "];
|
||||
4 [shape=box label="Enter ||"];
|
||||
5 [shape=box label="Access variable R|<local>/b1|"];
|
||||
6 [shape=box label="Exit left part of ||"];
|
||||
7 [shape=box label="Access variable R|<local>/b2|"];
|
||||
8 [shape=box label="Exit ||"];
|
||||
9 [shape=box label="Exit when branch condition"];
|
||||
10 [shape=box label="Enter block"];
|
||||
11 [shape=box label="Const: Int(1)"];
|
||||
12 [shape=box label="Exit block"];
|
||||
13 [shape=box label="Exit when branch result"];
|
||||
14 [shape=box label="Enter when branch condition else"];
|
||||
15 [shape=box label="Exit when branch condition"];
|
||||
16 [shape=box label="Enter block"];
|
||||
17 [shape=box label="Exit block"];
|
||||
18 [shape=box label="Exit when branch result"];
|
||||
19 [shape=box label="Exit when"];
|
||||
20 [shape=box label="Exit block"];
|
||||
21 [shape=box label="Exit function test_1"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {4};
|
||||
4 -> {5 8};
|
||||
5 -> {8 6};
|
||||
6 -> {7};
|
||||
7 -> {8};
|
||||
8 -> {9};
|
||||
9 -> {10 14};
|
||||
10 -> {11};
|
||||
11 -> {12};
|
||||
12 -> {13};
|
||||
13 -> {19};
|
||||
14 -> {15};
|
||||
15 -> {16};
|
||||
16 -> {17};
|
||||
17 -> {18};
|
||||
18 -> {19};
|
||||
19 -> {20};
|
||||
20 -> {21};
|
||||
}
|
||||
|
||||
subgraph test_2 {
|
||||
22 [shape=box label="Enter function test_2"];
|
||||
23 [shape=box label="Enter block"];
|
||||
24 [shape=box label="Enter when"];
|
||||
25 [shape=box label="Enter when branch condition "];
|
||||
26 [shape=box label="Enter &&"];
|
||||
27 [shape=box label="Access variable R|<local>/b1|"];
|
||||
28 [shape=box label="Access variable R|<local>/b2|"];
|
||||
29 [shape=box label="Exit &&"];
|
||||
30 [shape=box label="Exit when branch condition"];
|
||||
31 [shape=box label="Enter block"];
|
||||
32 [shape=box label="Const: Int(1)"];
|
||||
33 [shape=box label="Exit block"];
|
||||
34 [shape=box label="Exit when branch result"];
|
||||
35 [shape=box label="Enter when branch condition else"];
|
||||
36 [shape=box label="Exit when branch condition"];
|
||||
37 [shape=box label="Enter block"];
|
||||
38 [shape=box label="Exit block"];
|
||||
39 [shape=box label="Exit when branch result"];
|
||||
40 [shape=box label="Exit when"];
|
||||
41 [shape=box label="Exit block"];
|
||||
42 [shape=box label="Exit function test_2"];
|
||||
|
||||
22 -> {23};
|
||||
23 -> {24};
|
||||
24 -> {25};
|
||||
25 -> {26};
|
||||
26 -> {27};
|
||||
27 -> {29 28};
|
||||
28 -> {29};
|
||||
29 -> {30};
|
||||
30 -> {31 35};
|
||||
31 -> {32};
|
||||
32 -> {33};
|
||||
33 -> {34};
|
||||
34 -> {40};
|
||||
35 -> {36};
|
||||
36 -> {37};
|
||||
37 -> {38};
|
||||
38 -> {39};
|
||||
39 -> {40};
|
||||
40 -> {41};
|
||||
41 -> {42};
|
||||
}
|
||||
|
||||
subgraph test_3 {
|
||||
43 [shape=box label="Enter function test_3"];
|
||||
44 [shape=box label="Enter block"];
|
||||
45 [shape=box label="Enter when"];
|
||||
46 [shape=box label="Enter when branch condition "];
|
||||
47 [shape=box label="Enter ||"];
|
||||
48 [shape=box label="Enter &&"];
|
||||
49 [shape=box label="Access variable R|<local>/b1|"];
|
||||
50 [shape=box label="Access variable R|<local>/b2|"];
|
||||
51 [shape=box label="Exit &&"];
|
||||
52 [shape=box label="Exit left part of ||"];
|
||||
53 [shape=box label="Access variable R|<local>/b3|"];
|
||||
54 [shape=box label="Exit ||"];
|
||||
55 [shape=box label="Exit when branch condition"];
|
||||
56 [shape=box label="Enter block"];
|
||||
57 [shape=box label="Const: Int(1)"];
|
||||
58 [shape=box label="Exit block"];
|
||||
59 [shape=box label="Exit when branch result"];
|
||||
60 [shape=box label="Enter when branch condition else"];
|
||||
61 [shape=box label="Exit when branch condition"];
|
||||
62 [shape=box label="Enter block"];
|
||||
63 [shape=box label="Exit block"];
|
||||
64 [shape=box label="Exit when branch result"];
|
||||
65 [shape=box label="Exit when"];
|
||||
66 [shape=box label="Exit block"];
|
||||
67 [shape=box label="Exit function test_3"];
|
||||
|
||||
43 -> {44};
|
||||
44 -> {45};
|
||||
45 -> {46};
|
||||
46 -> {47};
|
||||
47 -> {48 54};
|
||||
48 -> {49};
|
||||
49 -> {51 50};
|
||||
50 -> {51};
|
||||
51 -> {54 52};
|
||||
52 -> {53};
|
||||
53 -> {54};
|
||||
54 -> {55};
|
||||
55 -> {56 60};
|
||||
56 -> {57};
|
||||
57 -> {58};
|
||||
58 -> {59};
|
||||
59 -> {65};
|
||||
60 -> {61};
|
||||
61 -> {62};
|
||||
62 -> {63};
|
||||
63 -> {64};
|
||||
64 -> {65};
|
||||
65 -> {66};
|
||||
66 -> {67};
|
||||
}
|
||||
|
||||
subgraph test_4 {
|
||||
68 [shape=box label="Enter function test_4"];
|
||||
69 [shape=box label="Enter block"];
|
||||
70 [shape=box label="Enter when"];
|
||||
71 [shape=box label="Enter when branch condition "];
|
||||
72 [shape=box label="Enter ||"];
|
||||
73 [shape=box label="Access variable R|<local>/b1|"];
|
||||
74 [shape=box label="Exit left part of ||"];
|
||||
75 [shape=box label="Enter &&"];
|
||||
76 [shape=box label="Access variable R|<local>/b2|"];
|
||||
77 [shape=box label="Access variable R|<local>/b3|"];
|
||||
78 [shape=box label="Exit &&"];
|
||||
79 [shape=box label="Exit ||"];
|
||||
80 [shape=box label="Exit when branch condition"];
|
||||
81 [shape=box label="Enter block"];
|
||||
82 [shape=box label="Const: Int(1)"];
|
||||
83 [shape=box label="Exit block"];
|
||||
84 [shape=box label="Exit when branch result"];
|
||||
85 [shape=box label="Enter when branch condition else"];
|
||||
86 [shape=box label="Exit when branch condition"];
|
||||
87 [shape=box label="Enter block"];
|
||||
88 [shape=box label="Exit block"];
|
||||
89 [shape=box label="Exit when branch result"];
|
||||
90 [shape=box label="Exit when"];
|
||||
91 [shape=box label="Exit block"];
|
||||
92 [shape=box label="Exit function test_4"];
|
||||
|
||||
68 -> {69};
|
||||
69 -> {70};
|
||||
70 -> {71};
|
||||
71 -> {72};
|
||||
72 -> {73 79};
|
||||
73 -> {79 74};
|
||||
74 -> {75};
|
||||
75 -> {76};
|
||||
76 -> {78 77};
|
||||
77 -> {78};
|
||||
78 -> {79};
|
||||
79 -> {80};
|
||||
80 -> {81 85};
|
||||
81 -> {82};
|
||||
82 -> {83};
|
||||
83 -> {84};
|
||||
84 -> {90};
|
||||
85 -> {86};
|
||||
86 -> {87};
|
||||
87 -> {88};
|
||||
88 -> {89};
|
||||
89 -> {90};
|
||||
90 -> {91};
|
||||
91 -> {92};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
digraph complex_kt {
|
||||
subgraph fetchPluginReleaseDate {
|
||||
0 [shape=box label="Enter function fetchPluginReleaseDate"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Const: String(https://plugins.jetbrains.com/api/plugins/)"];
|
||||
3 [shape=box label="Access variable R|<local>/pluginId|"];
|
||||
4 [shape=box label="Access variable <Unresolved name: idString>#"];
|
||||
5 [shape=box label="Const: String(/updates?version=)"];
|
||||
6 [shape=box label="Access variable R|<local>/version|"];
|
||||
7 [shape=box label="Variable declaration: lval url: R|kotlin/String|"];
|
||||
8 [shape=box label="Try expression enter"];
|
||||
9 [shape=box label="Try main block enter"];
|
||||
10 [shape=box label="Enter block"];
|
||||
11 [shape=box label="Access variable <Unresolved name: HttpRequests>#"];
|
||||
12 [shape=box label="Access variable R|<local>/url|"];
|
||||
13 [shape=box label="Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|)"];
|
||||
14 [shape=box label="Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|).<Unresolved name: connect>#(<L> = connect@fun <implicit>.<anonymous>(): <implicit> {
|
||||
GsonBuilder#().create#().fromJson#(it#.inputStream#.reader#(), <getClass>(Array#<R|class error: Symbol not found, for `PluginDTO`|>()).java#)
|
||||
}
|
||||
)"];
|
||||
15 [shape=box label="Exit block"];
|
||||
16 [shape=box label="Try main block exit"];
|
||||
17 [shape=box label="Catch enter"];
|
||||
18 [shape=box label="Enter block"];
|
||||
19 [shape=box label="Const: String(Can't parse json response)"];
|
||||
20 [shape=box label="Access variable R|<local>/syntaxException|"];
|
||||
21 [shape=box label="Function call: <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
|
||||
22 [shape=box label="Throw: throw <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
|
||||
23 [shape=box label="Stub[DEAD]"];
|
||||
24 [shape=box label="Exit block[DEAD]"];
|
||||
25 [shape=box label="Catch exit[DEAD]"];
|
||||
26 [shape=box label="Catch enter"];
|
||||
27 [shape=box label="Enter block"];
|
||||
28 [shape=box label="Access variable R|<local>/ioException|"];
|
||||
29 [shape=box label="Function call: <Unresolved name: IOException>#(R|<local>/ioException|)"];
|
||||
30 [shape=box label="Throw: throw <Unresolved name: IOException>#(R|<local>/ioException|)"];
|
||||
31 [shape=box label="Stub[DEAD]"];
|
||||
32 [shape=box label="Exit block[DEAD]"];
|
||||
33 [shape=box label="Catch exit[DEAD]"];
|
||||
34 [shape=box label="Try expression exit"];
|
||||
35 [shape=box label="Variable declaration: lval pluginDTOs: R|kotlin/Array<class error: Symbol not found, for `PluginDTO`>|"];
|
||||
36 [shape=box label="Exit block"];
|
||||
37 [shape=box label="Enter annotation"];
|
||||
38 [shape=box label="Access variable <Unresolved name: IOException>#"];
|
||||
39 [shape=box label="Access variable <Unresolved name: ResponseParseException>#"];
|
||||
40 [shape=box label="Exit annotation"];
|
||||
41 [shape=box label="Exit function fetchPluginReleaseDate"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {4};
|
||||
4 -> {5};
|
||||
5 -> {6};
|
||||
6 -> {7};
|
||||
7 -> {8};
|
||||
8 -> {9};
|
||||
9 -> {41 26 17 10};
|
||||
10 -> {11};
|
||||
11 -> {12};
|
||||
12 -> {13};
|
||||
13 -> {14};
|
||||
14 -> {15};
|
||||
15 -> {16};
|
||||
16 -> {34};
|
||||
17 -> {41 18};
|
||||
18 -> {19};
|
||||
19 -> {20};
|
||||
20 -> {21};
|
||||
21 -> {22};
|
||||
22 -> {41};
|
||||
22 -> {23} [style=dotted];
|
||||
23 -> {24} [style=dotted];
|
||||
24 -> {25} [style=dotted];
|
||||
25 -> {34} [style=dotted];
|
||||
26 -> {41 27};
|
||||
27 -> {28};
|
||||
28 -> {29};
|
||||
29 -> {30};
|
||||
30 -> {41};
|
||||
30 -> {31} [style=dotted];
|
||||
31 -> {32} [style=dotted];
|
||||
32 -> {33} [style=dotted];
|
||||
33 -> {34} [style=dotted];
|
||||
34 -> {35};
|
||||
35 -> {36};
|
||||
36 -> {37};
|
||||
37 -> {38};
|
||||
38 -> {39};
|
||||
39 -> {40};
|
||||
40 -> {41};
|
||||
}
|
||||
|
||||
}
|
||||
+45
-20
@@ -1,21 +1,46 @@
|
||||
0: Enter function "foo" -> 1
|
||||
0: Enter function "fetchPluginReleaseDate" -> 1
|
||||
1: Enter block -> 2 | <- 0
|
||||
2: Try expression enter -> 3 | <- 1
|
||||
3: Try main block enter -> 4, 8, 20 | <- 2
|
||||
4: Enter block -> 5 | <- 3
|
||||
5: Const: Int(1) -> 6 | <- 4
|
||||
6: Exit block -> 7 | <- 5
|
||||
7: Try main block exit -> 14 | <- 6
|
||||
8: Catch enter -> 9, 20 | <- 3
|
||||
9: Enter block -> 10 | <- 8
|
||||
10: Jump: ^foo Unit -> 11[DEAD], 20 | <- 9
|
||||
11: Stub[DEAD] -> 12 | <- 10
|
||||
12: Exit block[DEAD] -> 13 | <- 11
|
||||
13: Catch exit[DEAD] -> 14 | <- 12
|
||||
14: Try expression exit -> 15 | <- 7, 13[DEAD]
|
||||
15: Variable declaration: lval x: R|kotlin/Int| -> 16 | <- 14
|
||||
16: Access variable R|<local>/x| -> 17 | <- 15
|
||||
17: Const: Int(1) -> 18 | <- 16
|
||||
18: Function call: R|<local>/x|.R|kotlin/Int.plus|(Int(1)) -> 19 | <- 17
|
||||
19: Exit block -> 20 | <- 18
|
||||
20: Exit function "foo" -> | <- 3, 8, 10, 19
|
||||
2: Const: String(https://plugins.jetbrains.com/api/plugins/) -> 3 | <- 1
|
||||
3: Access variable R|<local>/pluginId| -> 4 | <- 2
|
||||
4: Access variable <Unresolved name: idString># -> 5 | <- 3
|
||||
5: Const: String(/updates?version=) -> 6 | <- 4
|
||||
6: Access variable R|<local>/version| -> 7 | <- 5
|
||||
7: Variable declaration: lval url: R|kotlin/String| -> 8 | <- 6
|
||||
8: Try expression enter -> 9 | <- 7
|
||||
9: Try main block enter -> 10, 17, 26, 41 | <- 8
|
||||
10: Enter block -> 11 | <- 9
|
||||
11: Access variable <Unresolved name: HttpRequests># -> 12 | <- 10
|
||||
12: Access variable R|<local>/url| -> 13 | <- 11
|
||||
13: Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|) -> 14 | <- 12
|
||||
14: Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|).<Unresolved name: connect>#(<L> = connect@fun <implicit>.<anonymous>(): <implicit> {
|
||||
GsonBuilder#().create#().fromJson#(it#.inputStream#.reader#(), <getClass>(Array#<R|class error: Symbol not found, for `PluginDTO`|>()).java#)
|
||||
}
|
||||
) -> 15 | <- 13
|
||||
15: Exit block -> 16 | <- 14
|
||||
16: Try main block exit -> 34 | <- 15
|
||||
17: Catch enter -> 18, 41 | <- 9
|
||||
18: Enter block -> 19 | <- 17
|
||||
19: Const: String(Can't parse json response) -> 20 | <- 18
|
||||
20: Access variable R|<local>/syntaxException| -> 21 | <- 19
|
||||
21: Function call: <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|) -> 22 | <- 20
|
||||
22: Throw: throw <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|) -> 23[DEAD], 41 | <- 21
|
||||
23: Stub[DEAD] -> 24 | <- 22
|
||||
24: Exit block[DEAD] -> 25 | <- 23
|
||||
25: Catch exit[DEAD] -> 34 | <- 24
|
||||
26: Catch enter -> 27, 41 | <- 9
|
||||
27: Enter block -> 28 | <- 26
|
||||
28: Access variable R|<local>/ioException| -> 29 | <- 27
|
||||
29: Function call: <Unresolved name: IOException>#(R|<local>/ioException|) -> 30 | <- 28
|
||||
30: Throw: throw <Unresolved name: IOException>#(R|<local>/ioException|) -> 31[DEAD], 41 | <- 29
|
||||
31: Stub[DEAD] -> 32 | <- 30
|
||||
32: Exit block[DEAD] -> 33 | <- 31
|
||||
33: Catch exit[DEAD] -> 34 | <- 32
|
||||
34: Try expression exit -> 35 | <- 16, 25[DEAD], 33[DEAD]
|
||||
35: Variable declaration: lval pluginDTOs: R|kotlin/Array<class error: Symbol not found, for `PluginDTO`>| -> 36 | <- 34
|
||||
36: Exit block -> 37 | <- 35
|
||||
37: Enter annotation -> 38 | <- 36
|
||||
38: Access variable <Unresolved name: IOException># -> 39 | <- 37
|
||||
39: Access variable <Unresolved name: ResponseParseException># -> 40 | <- 38
|
||||
40: Exit annotation -> 41 | <- 39
|
||||
41: Exit function "fetchPluginReleaseDate" -> | <- 9, 17, 22, 26, 30, 40
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
FILE: complex.kt
|
||||
@R|kotlin/jvm/Throws|(<getClass>(<Unresolved name: IOException>#), <getClass>(<Unresolved name: ResponseParseException>#)) public final fun fetchPluginReleaseDate(pluginId: R|class error: Symbol not found, for `PluginId`|, version: R|kotlin/String|, channel: R|kotlin/String?|): R|class error: Symbol not found, for `LocalDate?`| {
|
||||
lval url: R|kotlin/String| = <strcat>(String(https://plugins.jetbrains.com/api/plugins/), R|<local>/pluginId|.<Unresolved name: idString>#, String(/updates?version=), R|<local>/version|)
|
||||
lval pluginDTOs: R|kotlin/Array<class error: Symbol not found, for `PluginDTO`>| = try {
|
||||
<Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|).<Unresolved name: connect>#(<L> = connect@fun <implicit>.<anonymous>(): <implicit> {
|
||||
GsonBuilder#().create#().fromJson#(it#.inputStream#.reader#(), <getClass>(Array#<R|class error: Symbol not found, for `PluginDTO`|>()).java#)
|
||||
}
|
||||
)
|
||||
}
|
||||
catch (ioException: R|class error: Symbol not found, for `JsonIOException`|) {
|
||||
throw <Unresolved name: IOException>#(R|<local>/ioException|)
|
||||
}
|
||||
catch (syntaxException: R|class error: Symbol not found, for `JsonSyntaxException`|) {
|
||||
throw <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
digraph initBlock_kt {
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
digraph jumps_kt {
|
||||
subgraph test_1 {
|
||||
0 [shape=box label="Enter function test_1"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Enter when"];
|
||||
3 [shape=box label="Enter when branch condition "];
|
||||
4 [shape=box label="Access variable R|<local>/x|"];
|
||||
5 [shape=box label="Const: Null(null)"];
|
||||
6 [shape=box label="Operator =="];
|
||||
7 [shape=box label="Exit when branch condition"];
|
||||
8 [shape=box label="Enter block"];
|
||||
9 [shape=box label="Function call: R|kotlin/KotlinNullPointerException.KotlinNullPointerException|()"];
|
||||
10 [shape=box label="Throw: throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|()"];
|
||||
11 [shape=box label="Stub[DEAD]"];
|
||||
12 [shape=box label="Exit block[DEAD]"];
|
||||
13 [shape=box label="Exit when branch result[DEAD]"];
|
||||
14 [shape=box label="Enter when branch condition else"];
|
||||
15 [shape=box label="Exit when branch condition"];
|
||||
16 [shape=box label="Enter block"];
|
||||
17 [shape=box label="Access variable R|<local>/x|"];
|
||||
18 [shape=box label="Exit block"];
|
||||
19 [shape=box label="Exit when branch result"];
|
||||
20 [shape=box label="Exit when"];
|
||||
21 [shape=box label="Variable declaration: lval y: R|kotlin/Int|"];
|
||||
22 [shape=box label="Access variable R|<local>/y|"];
|
||||
23 [shape=box label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
|
||||
24 [shape=box label="Exit block"];
|
||||
25 [shape=box label="Exit function test_1"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {4};
|
||||
4 -> {5};
|
||||
5 -> {6};
|
||||
6 -> {7};
|
||||
7 -> {8 14};
|
||||
8 -> {9};
|
||||
9 -> {10};
|
||||
10 -> {25};
|
||||
10 -> {11} [style=dotted];
|
||||
11 -> {12} [style=dotted];
|
||||
12 -> {13} [style=dotted];
|
||||
13 -> {20} [style=dotted];
|
||||
14 -> {15};
|
||||
15 -> {16};
|
||||
16 -> {17};
|
||||
17 -> {18};
|
||||
18 -> {19};
|
||||
19 -> {20};
|
||||
20 -> {21};
|
||||
21 -> {22};
|
||||
22 -> {23};
|
||||
23 -> {24};
|
||||
24 -> {25};
|
||||
}
|
||||
|
||||
subgraph test_2 {
|
||||
26 [shape=box label="Enter function test_2"];
|
||||
27 [shape=box label="Enter block"];
|
||||
28 [shape=box label="Enter when"];
|
||||
29 [shape=box label="Enter when branch condition "];
|
||||
30 [shape=box label="Access variable R|<local>/x|"];
|
||||
31 [shape=box label="Const: Null(null)"];
|
||||
32 [shape=box label="Operator =="];
|
||||
33 [shape=box label="Exit when branch condition"];
|
||||
34 [shape=box label="Enter block"];
|
||||
35 [shape=box label="Access variable R|<local>/x|"];
|
||||
36 [shape=box label="Exit block"];
|
||||
37 [shape=box label="Exit when branch result"];
|
||||
38 [shape=box label="Enter when branch condition else"];
|
||||
39 [shape=box label="Exit when branch condition"];
|
||||
40 [shape=box label="Enter block"];
|
||||
41 [shape=box label="Access variable R|<local>/x|"];
|
||||
42 [shape=box label="Exit block"];
|
||||
43 [shape=box label="Exit when branch result"];
|
||||
44 [shape=box label="Exit when"];
|
||||
45 [shape=box label="Variable declaration: lval y: R|kotlin/Int?|"];
|
||||
46 [shape=box label="Access variable R|<local>/y|"];
|
||||
47 [shape=box label="Function call: R|<local>/y|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()"];
|
||||
48 [shape=box label="Exit block"];
|
||||
49 [shape=box label="Exit function test_2"];
|
||||
|
||||
26 -> {27};
|
||||
27 -> {28};
|
||||
28 -> {29};
|
||||
29 -> {30};
|
||||
30 -> {31};
|
||||
31 -> {32};
|
||||
32 -> {33};
|
||||
33 -> {34 38};
|
||||
34 -> {35};
|
||||
35 -> {36};
|
||||
36 -> {37};
|
||||
37 -> {44};
|
||||
38 -> {39};
|
||||
39 -> {40};
|
||||
40 -> {41};
|
||||
41 -> {42};
|
||||
42 -> {43};
|
||||
43 -> {44};
|
||||
44 -> {45};
|
||||
45 -> {46};
|
||||
46 -> {47};
|
||||
47 -> {48};
|
||||
48 -> {49};
|
||||
}
|
||||
|
||||
subgraph test_3 {
|
||||
50 [shape=box label="Enter function test_3"];
|
||||
51 [shape=box label="Enter block"];
|
||||
52 [shape=box label="Enter while loop"];
|
||||
53 [shape=box label="Enter loop condition"];
|
||||
54 [shape=box label="Const: Boolean(true)"];
|
||||
55 [shape=box label="Exit loop condition"];
|
||||
56 [shape=box label="Enter loop block"];
|
||||
57 [shape=box label="Enter block"];
|
||||
58 [shape=box label="Access variable R|<local>/x|"];
|
||||
59 [shape=box label="Type operator: x as Int"];
|
||||
60 [shape=box label="Jump: break@@@[Boolean(true)] "];
|
||||
61 [shape=box label="Stub[DEAD]"];
|
||||
62 [shape=box label="Exit block[DEAD]"];
|
||||
63 [shape=box label="Exit loop block[DEAD]"];
|
||||
64 [shape=box label="Exit whileloop"];
|
||||
65 [shape=box label="Access variable R|<local>/x|"];
|
||||
66 [shape=box label="Function call: R|<local>/x|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()"];
|
||||
67 [shape=box label="Exit block"];
|
||||
68 [shape=box label="Exit function test_3"];
|
||||
|
||||
50 -> {51};
|
||||
51 -> {52};
|
||||
52 -> {53};
|
||||
53 -> {54};
|
||||
54 -> {55};
|
||||
55 -> {64 56};
|
||||
56 -> {57};
|
||||
57 -> {58};
|
||||
58 -> {59};
|
||||
59 -> {60};
|
||||
60 -> {64};
|
||||
60 -> {61} [style=dotted];
|
||||
61 -> {62} [style=dotted];
|
||||
62 -> {63} [style=dotted];
|
||||
63 -> {53} [style=dotted];
|
||||
64 -> {65};
|
||||
65 -> {66};
|
||||
66 -> {67};
|
||||
67 -> {68};
|
||||
}
|
||||
|
||||
subgraph test_4 {
|
||||
69 [shape=box label="Enter function test_4"];
|
||||
70 [shape=box label="Enter block"];
|
||||
71 [shape=box label="Enter do-while loop"];
|
||||
72 [shape=box label="Enter loop block"];
|
||||
73 [shape=box label="Enter block"];
|
||||
74 [shape=box label="Access variable R|<local>/x|"];
|
||||
75 [shape=box label="Type operator: x as int"];
|
||||
76 [shape=box label="Jump: break@@@[Boolean(true)] "];
|
||||
77 [shape=box label="Stub[DEAD]"];
|
||||
78 [shape=box label="Exit block[DEAD]"];
|
||||
79 [shape=box label="Exit loop block[DEAD]"];
|
||||
80 [shape=box label="Enter loop condition[DEAD]"];
|
||||
81 [shape=box label="Const: Boolean(true)[DEAD]"];
|
||||
82 [shape=box label="Exit loop condition[DEAD]"];
|
||||
83 [shape=box label="Exit do-whileloop[DEAD]"];
|
||||
84 [shape=box label="Access variable R|<local>/x|[DEAD]"];
|
||||
85 [shape=box label="Function call: R|<local>/x|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()[DEAD]"];
|
||||
86 [shape=box label="Exit block[DEAD]"];
|
||||
87 [shape=box label="Exit function test_4[DEAD]"];
|
||||
|
||||
69 -> {70};
|
||||
70 -> {71};
|
||||
71 -> {72};
|
||||
72 -> {73};
|
||||
73 -> {74};
|
||||
74 -> {75};
|
||||
75 -> {76};
|
||||
76 -> {83 77} [style=dotted];
|
||||
77 -> {78} [style=dotted];
|
||||
78 -> {79} [style=dotted];
|
||||
79 -> {80} [style=dotted];
|
||||
80 -> {81} [style=dotted];
|
||||
81 -> {82} [style=dotted];
|
||||
82 -> {72 83} [style=dotted];
|
||||
83 -> {84} [style=dotted];
|
||||
84 -> {85} [style=dotted];
|
||||
85 -> {86} [style=dotted];
|
||||
86 -> {87} [style=dotted];
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -19,9 +19,9 @@
|
||||
18: Exit block -> 19 | <- 17
|
||||
19: Exit when branch result -> 20 | <- 18
|
||||
20: Exit when -> 21 | <- 13[DEAD], 19
|
||||
21: Variable declaration: lval y: R|kotlin/Int?| -> 22 | <- 20
|
||||
21: Variable declaration: lval y: R|kotlin/Int| -> 22 | <- 20
|
||||
22: Access variable R|<local>/y| -> 23 | <- 21
|
||||
23: Function call: R|<local>/y|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#() -> 24 | <- 22
|
||||
23: Function call: R|<local>/y|.R|kotlin/Int.inc|() -> 24 | <- 22
|
||||
24: Exit block -> 25 | <- 23
|
||||
25: Exit function "test_1" -> | <- 10, 24
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
FILE: jumps.kt
|
||||
public final fun test_1(x: R|kotlin/Int?|): R|kotlin/Unit| {
|
||||
lval y: R|kotlin/Int?| = when () {
|
||||
lval y: R|kotlin/Int| = when () {
|
||||
==(R|<local>/x|, Null(null)) -> {
|
||||
throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|()
|
||||
}
|
||||
@@ -9,7 +9,7 @@ FILE: jumps.kt
|
||||
}
|
||||
}
|
||||
|
||||
R|<local>/y|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()
|
||||
R|<local>/y|.R|kotlin/Int.inc|()
|
||||
}
|
||||
public final fun test_2(x: R|kotlin/Int?|): R|kotlin/Unit| {
|
||||
lval y: R|kotlin/Int?| = when () {
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
digraph loops_kt {
|
||||
subgraph testWhile {
|
||||
0 [shape=box label="Enter function testWhile"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Enter while loop"];
|
||||
3 [shape=box label="Enter loop condition"];
|
||||
4 [shape=box label="Access variable R|<local>/b|"];
|
||||
5 [shape=box label="Exit loop condition"];
|
||||
6 [shape=box label="Enter loop block"];
|
||||
7 [shape=box label="Enter block"];
|
||||
8 [shape=box label="Access variable R|<local>/x|"];
|
||||
9 [shape=box label="Type operator: x is String"];
|
||||
10 [shape=box label="Variable declaration: lval y: R|kotlin/Boolean|"];
|
||||
11 [shape=box label="Exit block"];
|
||||
12 [shape=box label="Exit loop block"];
|
||||
13 [shape=box label="Exit whileloop"];
|
||||
14 [shape=box label="Access variable R|<local>/x|"];
|
||||
15 [shape=box label="Type operator: x is String"];
|
||||
16 [shape=box label="Exit block"];
|
||||
17 [shape=box label="Exit function testWhile"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {4};
|
||||
4 -> {5};
|
||||
5 -> {13 6};
|
||||
6 -> {7};
|
||||
7 -> {8};
|
||||
8 -> {9};
|
||||
9 -> {10};
|
||||
10 -> {11};
|
||||
11 -> {12};
|
||||
12 -> {3};
|
||||
13 -> {14};
|
||||
14 -> {15};
|
||||
15 -> {16};
|
||||
16 -> {17};
|
||||
}
|
||||
|
||||
subgraph testDoWhile {
|
||||
18 [shape=box label="Enter function testDoWhile"];
|
||||
19 [shape=box label="Enter block"];
|
||||
20 [shape=box label="Enter do-while loop"];
|
||||
21 [shape=box label="Enter loop block"];
|
||||
22 [shape=box label="Enter block"];
|
||||
23 [shape=box label="Access variable R|<local>/x|"];
|
||||
24 [shape=box label="Type operator: x is String"];
|
||||
25 [shape=box label="Variable declaration: lval y: R|kotlin/Boolean|"];
|
||||
26 [shape=box label="Exit block"];
|
||||
27 [shape=box label="Exit loop block"];
|
||||
28 [shape=box label="Enter loop condition"];
|
||||
29 [shape=box label="Access variable R|<local>/b|"];
|
||||
30 [shape=box label="Exit loop condition"];
|
||||
31 [shape=box label="Exit do-whileloop"];
|
||||
32 [shape=box label="Access variable R|<local>/x|"];
|
||||
33 [shape=box label="Type operator: x is String"];
|
||||
34 [shape=box label="Exit block"];
|
||||
35 [shape=box label="Exit function testDoWhile"];
|
||||
|
||||
18 -> {19};
|
||||
19 -> {20};
|
||||
20 -> {21};
|
||||
21 -> {22};
|
||||
22 -> {23};
|
||||
23 -> {24};
|
||||
24 -> {25};
|
||||
25 -> {26};
|
||||
26 -> {27};
|
||||
27 -> {28};
|
||||
28 -> {29};
|
||||
29 -> {30};
|
||||
30 -> {21 31};
|
||||
31 -> {32};
|
||||
32 -> {33};
|
||||
33 -> {34};
|
||||
34 -> {35};
|
||||
}
|
||||
|
||||
subgraph testFor {
|
||||
36 [shape=box label="Enter function testFor"];
|
||||
37 [shape=box label="Enter block"];
|
||||
38 [shape=box label="Const: Int(0)"];
|
||||
39 [shape=box label="Const: Int(5)"];
|
||||
40 [shape=box label="Function call: Int(0).R|kotlin/Int.rangeTo|(Int(5))"];
|
||||
41 [shape=box label="Variable declaration: lval <range>: R|kotlin/ranges/IntRange|"];
|
||||
42 [shape=box label="Access variable R|<local>/<range>|"];
|
||||
43 [shape=box label="Function call: R|<local>/<range>|.R|kotlin/ranges/IntProgression.iterator|()"];
|
||||
44 [shape=box label="Variable declaration: lval <iterator>: R|kotlin/collections/IntIterator|"];
|
||||
45 [shape=box label="Enter while loop"];
|
||||
46 [shape=box label="Enter loop condition"];
|
||||
47 [shape=box label="Access variable R|<local>/<iterator>|"];
|
||||
48 [shape=box label="Function call: R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.hasNext: R|kotlin/Boolean|>|()"];
|
||||
49 [shape=box label="Exit loop condition"];
|
||||
50 [shape=box label="Enter loop block"];
|
||||
51 [shape=box label="Enter block"];
|
||||
52 [shape=box label="Access variable R|<local>/<iterator>|"];
|
||||
53 [shape=box label="Function call: R|<local>/<iterator>|.R|kotlin/collections/IntIterator.next|()"];
|
||||
54 [shape=box label="Variable declaration: lval i: R|kotlin/Int|"];
|
||||
55 [shape=box label="Access variable R|<local>/x|"];
|
||||
56 [shape=box label="Type operator: x is String"];
|
||||
57 [shape=box label="Variable declaration: lval y: R|kotlin/Boolean|"];
|
||||
58 [shape=box label="Exit block"];
|
||||
59 [shape=box label="Exit loop block"];
|
||||
60 [shape=box label="Exit whileloop"];
|
||||
61 [shape=box label="Access variable R|<local>/x|"];
|
||||
62 [shape=box label="Type operator: x is String"];
|
||||
63 [shape=box label="Exit block"];
|
||||
64 [shape=box label="Exit function testFor"];
|
||||
|
||||
36 -> {37};
|
||||
37 -> {38};
|
||||
38 -> {39};
|
||||
39 -> {40};
|
||||
40 -> {41};
|
||||
41 -> {42};
|
||||
42 -> {43};
|
||||
43 -> {44};
|
||||
44 -> {45};
|
||||
45 -> {46};
|
||||
46 -> {47};
|
||||
47 -> {48};
|
||||
48 -> {49};
|
||||
49 -> {60 50};
|
||||
50 -> {51};
|
||||
51 -> {52};
|
||||
52 -> {53};
|
||||
53 -> {54};
|
||||
54 -> {55};
|
||||
55 -> {56};
|
||||
56 -> {57};
|
||||
57 -> {58};
|
||||
58 -> {59};
|
||||
59 -> {46};
|
||||
60 -> {61};
|
||||
61 -> {62};
|
||||
62 -> {63};
|
||||
63 -> {64};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
digraph propertiesAndInitBlocks_kt {
|
||||
subgraph run {
|
||||
0 [shape=box label="Enter function run"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
|
||||
3 [shape=box label="Exit block"];
|
||||
4 [shape=box label="Exit function run"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {4};
|
||||
}
|
||||
|
||||
subgraph val_x1 {
|
||||
5 [shape=box label="Enter property"];
|
||||
6 [shape=box label="Const: Int(1)"];
|
||||
7 [shape=box label="Exit property"];
|
||||
|
||||
5 -> {6};
|
||||
6 -> {7};
|
||||
}
|
||||
|
||||
subgraph <getter> {
|
||||
8 [shape=box label="Enter function getter"];
|
||||
9 [shape=box label="Enter block"];
|
||||
10 [shape=box label="Const: Int(1)"];
|
||||
11 [shape=box label="Jump: ^ Int(1)"];
|
||||
12 [shape=box label="Stub[DEAD]"];
|
||||
13 [shape=box label="Exit block[DEAD]"];
|
||||
14 [shape=box label="Exit function getter[DEAD]"];
|
||||
|
||||
8 -> {9};
|
||||
9 -> {10};
|
||||
10 -> {11};
|
||||
11 -> {14 12} [style=dotted];
|
||||
12 -> {13} [style=dotted];
|
||||
13 -> {14} [style=dotted];
|
||||
}
|
||||
|
||||
subgraph <setter> {
|
||||
15 [shape=box label="Enter function setter"];
|
||||
16 [shape=box label="Enter block"];
|
||||
17 [shape=box label="Const: Int(1)"];
|
||||
18 [shape=box label="Assignmenet: F|/x2|"];
|
||||
19 [shape=box label="Exit block"];
|
||||
20 [shape=box label="Exit function setter"];
|
||||
|
||||
15 -> {16};
|
||||
16 -> {17};
|
||||
17 -> {18};
|
||||
18 -> {19};
|
||||
19 -> {20};
|
||||
}
|
||||
|
||||
subgraph val_x2 {
|
||||
21 [shape=box label="Enter property"];
|
||||
22 [shape=box label="Const: Int(1)"];
|
||||
23 [shape=box label="Exit property"];
|
||||
|
||||
21 -> {22};
|
||||
22 -> {23};
|
||||
}
|
||||
|
||||
subgraph <anonymous> {
|
||||
24 [shape=box label="Enter init block"];
|
||||
25 [shape=box label="Enter block"];
|
||||
26 [shape=box label="Function call: <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
27 [shape=box label="Throw: throw <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
28 [shape=box label="Stub[DEAD]"];
|
||||
29 [shape=box label="Const: Int(1)[DEAD]"];
|
||||
30 [shape=box label="Exit block[DEAD]"];
|
||||
31 [shape=box label="Exit init block[DEAD]"];
|
||||
32 [shape=box label="Enter function anonymousFunction"];
|
||||
33 [shape=box label="Enter block"];
|
||||
34 [shape=box label="Function call: <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
35 [shape=box label="Throw: throw <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
36 [shape=box label="Stub[DEAD]"];
|
||||
37 [shape=box label="Exit block[DEAD]"];
|
||||
38 [shape=box label="Exit function anonymousFunction[DEAD]"];
|
||||
|
||||
24 -> {25};
|
||||
25 -> {26};
|
||||
26 -> {27};
|
||||
27 -> {31 28} [style=dotted];
|
||||
28 -> {29} [style=dotted];
|
||||
29 -> {30} [style=dotted];
|
||||
30 -> {31} [style=dotted];
|
||||
32 -> {33};
|
||||
33 -> {34};
|
||||
34 -> {35};
|
||||
35 -> {38 36} [style=dotted];
|
||||
36 -> {37} [style=dotted];
|
||||
37 -> {38} [style=dotted];
|
||||
}
|
||||
|
||||
subgraph foo {
|
||||
39 [shape=box label="Enter function foo"];
|
||||
40 [shape=box label="Enter block"];
|
||||
41 [shape=box label="Const: Int(1)"];
|
||||
42 [shape=box label="Const: Int(1)"];
|
||||
43 [shape=box label="Function call: Int(1).R|kotlin/Int.plus|(Int(1))"];
|
||||
44 [shape=box label="Variable declaration: lval c: R|kotlin/Int|"];
|
||||
45 [shape=box label="Function call: <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
46 [shape=box label="Throw: throw <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
47 [shape=box label="Stub[DEAD]"];
|
||||
48 [shape=box label="Exit block[DEAD]"];
|
||||
49 [shape=box label="Exit function foo[DEAD]"];
|
||||
|
||||
39 -> {40};
|
||||
40 -> {41};
|
||||
41 -> {42};
|
||||
42 -> {43};
|
||||
43 -> {44};
|
||||
44 -> {45};
|
||||
45 -> {46};
|
||||
46 -> {49 47} [style=dotted];
|
||||
47 -> {48} [style=dotted];
|
||||
48 -> {49} [style=dotted];
|
||||
}
|
||||
|
||||
subgraph <getter> {
|
||||
50 [shape=box label="Enter init block"];
|
||||
51 [shape=box label="Enter block"];
|
||||
52 [shape=box label="Function call: <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
53 [shape=box label="Throw: throw <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()"];
|
||||
54 [shape=box label="Stub[DEAD]"];
|
||||
55 [shape=box label="Exit block[DEAD]"];
|
||||
56 [shape=box label="Exit init block[DEAD]"];
|
||||
57 [shape=box label="Enter function getter"];
|
||||
58 [shape=box label="Enter block"];
|
||||
59 [shape=box label="Exit block"];
|
||||
60 [shape=box label="Exit function getter"];
|
||||
|
||||
50 -> {51};
|
||||
51 -> {52};
|
||||
52 -> {53};
|
||||
53 -> {56 54} [style=dotted];
|
||||
54 -> {55} [style=dotted];
|
||||
55 -> {56} [style=dotted];
|
||||
57 -> {58};
|
||||
58 -> {59};
|
||||
59 -> {60};
|
||||
}
|
||||
|
||||
subgraph val_x3 {
|
||||
61 [shape=box label="Enter property"];
|
||||
62 [shape=box label="Function call: R|/run|(<L> = run@fun <anonymous>(): R|kotlin/Unit| {
|
||||
local final fun foo(): R|kotlin/Unit| {
|
||||
lval c: R|kotlin/Int| = Int(1).R|kotlin/Int.plus|(Int(1))
|
||||
throw <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()
|
||||
}
|
||||
|
||||
local final class LocalClass : R|kotlin/Any| {
|
||||
public constructor(): R|LocalClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
init {
|
||||
throw <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()
|
||||
Int(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw <Ambiguity: Exception, [java/lang/Exception.Exception, java/lang/Exception.Exception]>#()
|
||||
}
|
||||
)"];
|
||||
63 [shape=box label="Exit property"];
|
||||
|
||||
61 -> {62};
|
||||
62 -> {63};
|
||||
}
|
||||
|
||||
subgraph val_x4 {
|
||||
64 [shape=box label="Enter property"];
|
||||
65 [shape=box label="Try expression enter"];
|
||||
66 [shape=box label="Try main block enter"];
|
||||
67 [shape=box label="Enter block"];
|
||||
68 [shape=box label="Const: Int(1)"];
|
||||
69 [shape=box label="Exit block"];
|
||||
70 [shape=box label="Try main block exit"];
|
||||
71 [shape=box label="Enter finally"];
|
||||
72 [shape=box label="Enter block"];
|
||||
73 [shape=box label="Const: Int(0)"];
|
||||
74 [shape=box label="Exit block"];
|
||||
75 [shape=box label="Exit finally"];
|
||||
76 [shape=box label="Catch enter"];
|
||||
77 [shape=box label="Enter block"];
|
||||
78 [shape=box label="Const: Int(2)"];
|
||||
79 [shape=box label="Exit block"];
|
||||
80 [shape=box label="Catch exit"];
|
||||
81 [shape=box label="Try expression exit"];
|
||||
82 [shape=box label="Exit property"];
|
||||
|
||||
64 -> {65};
|
||||
65 -> {66};
|
||||
66 -> {82 76 71 67};
|
||||
67 -> {68};
|
||||
68 -> {69};
|
||||
69 -> {70};
|
||||
70 -> {81};
|
||||
71 -> {72};
|
||||
72 -> {73};
|
||||
73 -> {74};
|
||||
74 -> {75};
|
||||
75 -> {81};
|
||||
76 -> {82 77};
|
||||
77 -> {78};
|
||||
78 -> {79};
|
||||
79 -> {80};
|
||||
80 -> {81};
|
||||
81 -> {82};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
digraph simple_kt {
|
||||
subgraph foo {
|
||||
0 [shape=box label="Enter function foo"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Exit block"];
|
||||
3 [shape=box label="Exit function foo"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
}
|
||||
|
||||
subgraph test {
|
||||
4 [shape=box label="Enter function test"];
|
||||
5 [shape=box label="Enter block"];
|
||||
6 [shape=box label="Const: Int(1)"];
|
||||
7 [shape=box label="Variable declaration: lval x: R|kotlin/Int|"];
|
||||
8 [shape=box label="Access variable R|<local>/x|"];
|
||||
9 [shape=box label="Const: Int(1)"];
|
||||
10 [shape=box label="Function call: R|<local>/x|.R|kotlin/Int.plus|(Int(1))"];
|
||||
11 [shape=box label="Variable declaration: lval y: R|kotlin/Int|"];
|
||||
12 [shape=box label="Function call: R|/foo|()"];
|
||||
13 [shape=box label="Exit block"];
|
||||
14 [shape=box label="Exit function test"];
|
||||
|
||||
4 -> {5};
|
||||
5 -> {6};
|
||||
6 -> {7};
|
||||
7 -> {8};
|
||||
8 -> {9};
|
||||
9 -> {10};
|
||||
10 -> {11};
|
||||
11 -> {12};
|
||||
12 -> {13};
|
||||
13 -> {14};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
digraph tryCatch_kt {
|
||||
subgraph test_1 {
|
||||
0 [shape=box label="Enter function test_1"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Try expression enter"];
|
||||
3 [shape=box label="Try main block enter"];
|
||||
4 [shape=box label="Enter block"];
|
||||
5 [shape=box label="Const: Int(1)"];
|
||||
6 [shape=box label="Variable declaration: lval x: R|kotlin/Int|"];
|
||||
7 [shape=box label="Exit block"];
|
||||
8 [shape=box label="Try main block exit"];
|
||||
9 [shape=box label="Catch enter"];
|
||||
10 [shape=box label="Enter block"];
|
||||
11 [shape=box label="Const: Int(3)"];
|
||||
12 [shape=box label="Variable declaration: lval z: R|kotlin/Int|"];
|
||||
13 [shape=box label="Exit block"];
|
||||
14 [shape=box label="Catch exit"];
|
||||
15 [shape=box label="Catch enter"];
|
||||
16 [shape=box label="Enter block"];
|
||||
17 [shape=box label="Const: Int(2)"];
|
||||
18 [shape=box label="Variable declaration: lval y: R|kotlin/Int|"];
|
||||
19 [shape=box label="Exit block"];
|
||||
20 [shape=box label="Catch exit"];
|
||||
21 [shape=box label="Try expression exit"];
|
||||
22 [shape=box label="Exit block"];
|
||||
23 [shape=box label="Exit function test_1"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {23 15 9 4};
|
||||
4 -> {5};
|
||||
5 -> {6};
|
||||
6 -> {7};
|
||||
7 -> {8};
|
||||
8 -> {21};
|
||||
9 -> {23 10};
|
||||
10 -> {11};
|
||||
11 -> {12};
|
||||
12 -> {13};
|
||||
13 -> {14};
|
||||
14 -> {21};
|
||||
15 -> {23 16};
|
||||
16 -> {17};
|
||||
17 -> {18};
|
||||
18 -> {19};
|
||||
19 -> {20};
|
||||
20 -> {21};
|
||||
21 -> {22};
|
||||
22 -> {23};
|
||||
}
|
||||
|
||||
subgraph test_2 {
|
||||
24 [shape=box label="Enter function test_2"];
|
||||
25 [shape=box label="Enter block"];
|
||||
26 [shape=box label="Try expression enter"];
|
||||
27 [shape=box label="Try main block enter"];
|
||||
28 [shape=box label="Enter block"];
|
||||
29 [shape=box label="Const: Int(1)"];
|
||||
30 [shape=box label="Exit block"];
|
||||
31 [shape=box label="Try main block exit"];
|
||||
32 [shape=box label="Catch enter"];
|
||||
33 [shape=box label="Enter block"];
|
||||
34 [shape=box label="Const: Int(2)"];
|
||||
35 [shape=box label="Exit block"];
|
||||
36 [shape=box label="Catch exit"];
|
||||
37 [shape=box label="Try expression exit"];
|
||||
38 [shape=box label="Variable declaration: lval x: R|kotlin/Int|"];
|
||||
39 [shape=box label="Exit block"];
|
||||
40 [shape=box label="Exit function test_2"];
|
||||
|
||||
24 -> {25};
|
||||
25 -> {26};
|
||||
26 -> {27};
|
||||
27 -> {40 32 28};
|
||||
28 -> {29};
|
||||
29 -> {30};
|
||||
30 -> {31};
|
||||
31 -> {37};
|
||||
32 -> {40 33};
|
||||
33 -> {34};
|
||||
34 -> {35};
|
||||
35 -> {36};
|
||||
36 -> {37};
|
||||
37 -> {38};
|
||||
38 -> {39};
|
||||
39 -> {40};
|
||||
}
|
||||
|
||||
subgraph test_3 {
|
||||
41 [shape=box label="Enter function test_3"];
|
||||
42 [shape=box label="Enter block"];
|
||||
43 [shape=box label="Enter while loop"];
|
||||
44 [shape=box label="Enter loop condition"];
|
||||
45 [shape=box label="Const: Boolean(true)"];
|
||||
46 [shape=box label="Exit loop condition"];
|
||||
47 [shape=box label="Enter loop block"];
|
||||
48 [shape=box label="Enter block"];
|
||||
49 [shape=box label="Try expression enter"];
|
||||
50 [shape=box label="Try main block enter"];
|
||||
51 [shape=box label="Enter block"];
|
||||
52 [shape=box label="Enter when"];
|
||||
53 [shape=box label="Enter when branch condition "];
|
||||
54 [shape=box label="Access variable R|<local>/b|"];
|
||||
55 [shape=box label="Exit when branch condition"];
|
||||
56 [shape=box label="Enter block"];
|
||||
57 [shape=box label="Jump: ^test_3 Unit"];
|
||||
58 [shape=box label="Stub[DEAD]"];
|
||||
59 [shape=box label="Exit block[DEAD]"];
|
||||
60 [shape=box label="Exit when branch result[DEAD]"];
|
||||
61 [shape=box label="Enter when branch condition else"];
|
||||
62 [shape=box label="Exit when branch condition"];
|
||||
63 [shape=box label="Enter block"];
|
||||
64 [shape=box label="Exit block"];
|
||||
65 [shape=box label="Exit when branch result"];
|
||||
66 [shape=box label="Exit when"];
|
||||
67 [shape=box label="Const: Int(1)"];
|
||||
68 [shape=box label="Variable declaration: lval x: R|kotlin/Int|"];
|
||||
69 [shape=box label="Enter when"];
|
||||
70 [shape=box label="Enter when branch condition "];
|
||||
71 [shape=box label="Access variable R|<local>/b|"];
|
||||
72 [shape=box label="Function call: R|<local>/b|.R|kotlin/Boolean.not|()"];
|
||||
73 [shape=box label="Exit when branch condition"];
|
||||
74 [shape=box label="Enter block"];
|
||||
75 [shape=box label="Jump: break@@@[Boolean(true)] "];
|
||||
76 [shape=box label="Stub[DEAD]"];
|
||||
77 [shape=box label="Exit block[DEAD]"];
|
||||
78 [shape=box label="Exit when branch result[DEAD]"];
|
||||
79 [shape=box label="Enter when branch condition else"];
|
||||
80 [shape=box label="Exit when branch condition"];
|
||||
81 [shape=box label="Enter block"];
|
||||
82 [shape=box label="Exit block"];
|
||||
83 [shape=box label="Exit when branch result"];
|
||||
84 [shape=box label="Exit when"];
|
||||
85 [shape=box label="Exit block"];
|
||||
86 [shape=box label="Try main block exit"];
|
||||
87 [shape=box label="Catch enter"];
|
||||
88 [shape=box label="Enter block"];
|
||||
89 [shape=box label="Jump: break@@@[Boolean(true)] "];
|
||||
90 [shape=box label="Stub[DEAD]"];
|
||||
91 [shape=box label="Exit block[DEAD]"];
|
||||
92 [shape=box label="Catch exit[DEAD]"];
|
||||
93 [shape=box label="Catch enter"];
|
||||
94 [shape=box label="Enter block"];
|
||||
95 [shape=box label="Jump: continue@@@[Boolean(true)] "];
|
||||
96 [shape=box label="Stub[DEAD]"];
|
||||
97 [shape=box label="Exit block[DEAD]"];
|
||||
98 [shape=box label="Catch exit[DEAD]"];
|
||||
99 [shape=box label="Try expression exit"];
|
||||
100 [shape=box label="Const: Int(2)"];
|
||||
101 [shape=box label="Variable declaration: lval y: R|kotlin/Int|"];
|
||||
102 [shape=box label="Exit block"];
|
||||
103 [shape=box label="Exit loop block"];
|
||||
104 [shape=box label="Exit whileloop"];
|
||||
105 [shape=box label="Const: Int(3)"];
|
||||
106 [shape=box label="Variable declaration: lval z: R|kotlin/Int|"];
|
||||
107 [shape=box label="Exit block"];
|
||||
108 [shape=box label="Exit function test_3"];
|
||||
|
||||
41 -> {42};
|
||||
42 -> {43};
|
||||
43 -> {44};
|
||||
44 -> {45};
|
||||
45 -> {46};
|
||||
46 -> {104 47};
|
||||
47 -> {48};
|
||||
48 -> {49};
|
||||
49 -> {50};
|
||||
50 -> {108 93 87 51};
|
||||
51 -> {52};
|
||||
52 -> {53};
|
||||
53 -> {54};
|
||||
54 -> {55};
|
||||
55 -> {56 61};
|
||||
56 -> {57};
|
||||
57 -> {108};
|
||||
57 -> {58} [style=dotted];
|
||||
58 -> {59} [style=dotted];
|
||||
59 -> {60} [style=dotted];
|
||||
60 -> {66} [style=dotted];
|
||||
61 -> {62};
|
||||
62 -> {63};
|
||||
63 -> {64};
|
||||
64 -> {65};
|
||||
65 -> {66};
|
||||
66 -> {67};
|
||||
67 -> {68};
|
||||
68 -> {69};
|
||||
69 -> {70};
|
||||
70 -> {71};
|
||||
71 -> {72};
|
||||
72 -> {73};
|
||||
73 -> {74 79};
|
||||
74 -> {75};
|
||||
75 -> {104};
|
||||
75 -> {76} [style=dotted];
|
||||
76 -> {77} [style=dotted];
|
||||
77 -> {78} [style=dotted];
|
||||
78 -> {84} [style=dotted];
|
||||
79 -> {80};
|
||||
80 -> {81};
|
||||
81 -> {82};
|
||||
82 -> {83};
|
||||
83 -> {84};
|
||||
84 -> {85};
|
||||
85 -> {86};
|
||||
86 -> {99};
|
||||
87 -> {108 88};
|
||||
88 -> {89};
|
||||
89 -> {104};
|
||||
89 -> {90} [style=dotted];
|
||||
90 -> {91} [style=dotted];
|
||||
91 -> {92} [style=dotted];
|
||||
92 -> {99} [style=dotted];
|
||||
93 -> {108 94};
|
||||
94 -> {95};
|
||||
95 -> {44};
|
||||
95 -> {96} [style=dotted];
|
||||
96 -> {97} [style=dotted];
|
||||
97 -> {98} [style=dotted];
|
||||
98 -> {99} [style=dotted];
|
||||
99 -> {100};
|
||||
100 -> {101};
|
||||
101 -> {102};
|
||||
102 -> {103};
|
||||
103 -> {44};
|
||||
104 -> {105};
|
||||
105 -> {106};
|
||||
106 -> {107};
|
||||
107 -> {108};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
digraph when_kt {
|
||||
subgraph test_1 {
|
||||
0 [shape=box label="Enter function test_1"];
|
||||
1 [shape=box label="Enter block"];
|
||||
2 [shape=box label="Enter when"];
|
||||
3 [shape=box label="Enter when branch condition "];
|
||||
4 [shape=box label="Access variable R|<local>/x|"];
|
||||
5 [shape=box label="Const: Int(1)"];
|
||||
6 [shape=box label="Operator =="];
|
||||
7 [shape=box label="Exit when branch condition"];
|
||||
8 [shape=box label="Enter block"];
|
||||
9 [shape=box label="Const: Int(10)"];
|
||||
10 [shape=box label="Exit block"];
|
||||
11 [shape=box label="Exit when branch result"];
|
||||
12 [shape=box label="Enter when branch condition "];
|
||||
13 [shape=box label="Access variable R|<local>/x|"];
|
||||
14 [shape=box label="Const: Int(2)"];
|
||||
15 [shape=box label="Function call: R|<local>/x|.R|kotlin/Int.rem|(Int(2))"];
|
||||
16 [shape=box label="Const: Int(0)"];
|
||||
17 [shape=box label="Operator =="];
|
||||
18 [shape=box label="Exit when branch condition"];
|
||||
19 [shape=box label="Enter block"];
|
||||
20 [shape=box label="Const: Int(20)"];
|
||||
21 [shape=box label="Exit block"];
|
||||
22 [shape=box label="Exit when branch result"];
|
||||
23 [shape=box label="Enter when branch condition "];
|
||||
24 [shape=box label="Const: Int(1)"];
|
||||
25 [shape=box label="Const: Int(1)"];
|
||||
26 [shape=box label="Function call: Int(1).R|kotlin/Int.minus|(Int(1))"];
|
||||
27 [shape=box label="Const: Int(0)"];
|
||||
28 [shape=box label="Operator =="];
|
||||
29 [shape=box label="Exit when branch condition"];
|
||||
30 [shape=box label="Enter block"];
|
||||
31 [shape=box label="Jump: ^test_1 Unit"];
|
||||
32 [shape=box label="Stub[DEAD]"];
|
||||
33 [shape=box label="Exit block[DEAD]"];
|
||||
34 [shape=box label="Exit when branch result[DEAD]"];
|
||||
35 [shape=box label="Enter when branch condition else"];
|
||||
36 [shape=box label="Exit when branch condition"];
|
||||
37 [shape=box label="Enter block"];
|
||||
38 [shape=box label="Const: Int(5)"];
|
||||
39 [shape=box label="Exit block"];
|
||||
40 [shape=box label="Exit when branch result"];
|
||||
41 [shape=box label="Exit when"];
|
||||
42 [shape=box label="Variable declaration: lval y: R|kotlin/Int|"];
|
||||
43 [shape=box label="Exit block"];
|
||||
44 [shape=box label="Exit function test_1"];
|
||||
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {4};
|
||||
4 -> {5};
|
||||
5 -> {6};
|
||||
6 -> {7};
|
||||
7 -> {8 12};
|
||||
8 -> {9};
|
||||
9 -> {10};
|
||||
10 -> {11};
|
||||
11 -> {41};
|
||||
12 -> {13};
|
||||
13 -> {14};
|
||||
14 -> {15};
|
||||
15 -> {16};
|
||||
16 -> {17};
|
||||
17 -> {18};
|
||||
18 -> {19 23};
|
||||
19 -> {20};
|
||||
20 -> {21};
|
||||
21 -> {22};
|
||||
22 -> {41};
|
||||
23 -> {24};
|
||||
24 -> {25};
|
||||
25 -> {26};
|
||||
26 -> {27};
|
||||
27 -> {28};
|
||||
28 -> {29};
|
||||
29 -> {30 35};
|
||||
30 -> {31};
|
||||
31 -> {44};
|
||||
31 -> {32} [style=dotted];
|
||||
32 -> {33} [style=dotted];
|
||||
33 -> {34} [style=dotted];
|
||||
34 -> {41} [style=dotted];
|
||||
35 -> {36};
|
||||
36 -> {37};
|
||||
37 -> {38};
|
||||
38 -> {39};
|
||||
39 -> {40};
|
||||
40 -> {41};
|
||||
41 -> {42};
|
||||
42 -> {43};
|
||||
43 -> {44};
|
||||
}
|
||||
|
||||
subgraph test_2 {
|
||||
45 [shape=box label="Enter function test_2"];
|
||||
46 [shape=box label="Enter block"];
|
||||
47 [shape=box label="Enter when"];
|
||||
48 [shape=box label="Enter when branch condition "];
|
||||
49 [shape=box label="Enter &&"];
|
||||
50 [shape=box label="Access variable R|<local>/x|"];
|
||||
51 [shape=box label="Type operator: x is A"];
|
||||
52 [shape=box label="Access variable R|<local>/x|"];
|
||||
53 [shape=box label="Type operator: x is B"];
|
||||
54 [shape=box label="Exit &&"];
|
||||
55 [shape=box label="Exit when branch condition"];
|
||||
56 [shape=box label="Enter block"];
|
||||
57 [shape=box label="Access variable R|<local>/x|"];
|
||||
58 [shape=box label="Type operator: x is A"];
|
||||
59 [shape=box label="Exit block"];
|
||||
60 [shape=box label="Exit when branch result"];
|
||||
61 [shape=box label="Enter when branch condition else"];
|
||||
62 [shape=box label="Exit when branch condition"];
|
||||
63 [shape=box label="Enter block"];
|
||||
64 [shape=box label="Exit block"];
|
||||
65 [shape=box label="Exit when branch result"];
|
||||
66 [shape=box label="Exit when"];
|
||||
67 [shape=box label="Exit block"];
|
||||
68 [shape=box label="Exit function test_2"];
|
||||
|
||||
45 -> {46};
|
||||
46 -> {47};
|
||||
47 -> {48};
|
||||
48 -> {49};
|
||||
49 -> {50};
|
||||
50 -> {51};
|
||||
51 -> {54 52};
|
||||
52 -> {53};
|
||||
53 -> {54};
|
||||
54 -> {55};
|
||||
55 -> {56 61};
|
||||
56 -> {57};
|
||||
57 -> {58};
|
||||
58 -> {59};
|
||||
59 -> {60};
|
||||
60 -> {66};
|
||||
61 -> {62};
|
||||
62 -> {63};
|
||||
63 -> {64};
|
||||
64 -> {65};
|
||||
65 -> {66};
|
||||
66 -> {67};
|
||||
67 -> {68};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.renderToStringBuilder
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
@@ -25,18 +25,83 @@ abstract class AbstractFirCfgBuildingTest : AbstractFirResolveTestCase() {
|
||||
}
|
||||
|
||||
fun checkCfg(path: String, firFiles: List<FirFile>) {
|
||||
val firFileDump = StringBuilder().also { firFiles.first().accept(FirControlFlowGraphRenderVisitor(it), null) }.toString()
|
||||
val expectedPath = path.replace(".kt", ".cfg.txt")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
||||
val simpleBuilder = StringBuilder()
|
||||
val dotBuilder = StringBuilder()
|
||||
|
||||
firFiles.first().accept(FirControlFlowGraphRenderVisitor(simpleBuilder, dotBuilder), null)
|
||||
|
||||
val dotCfgDump = dotBuilder.toString()
|
||||
val dotExpectedPath = path.replace(".kt", ".cfg.dot")
|
||||
KotlinTestUtils.assertEqualsToFile(File(dotExpectedPath), dotCfgDump)
|
||||
}
|
||||
|
||||
private class FirControlFlowGraphRenderVisitor(private val builder: StringBuilder) : FirVisitorVoid() {
|
||||
private class FirControlFlowGraphRenderVisitor(
|
||||
private val simpleBuilder: StringBuilder,
|
||||
private val dotBuilder: StringBuilder
|
||||
) : FirVisitorVoid() {
|
||||
private var indexOffset = 0
|
||||
|
||||
override fun visitFile(file: FirFile) {
|
||||
dotBuilder.appendln("digraph ${file.name.replace(".", "_")} {")
|
||||
super.visitFile(file)
|
||||
dotBuilder.appendln("}")
|
||||
}
|
||||
|
||||
override fun visitElement(element: FirElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitControlFlowGraphReference(controlFlowGraphReference: FirControlFlowGraphReference) {
|
||||
(controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph?.renderToStringBuilder(builder)
|
||||
val controlFlowGraph = (controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph ?: return
|
||||
controlFlowGraph.renderToStringBuilder(simpleBuilder)
|
||||
indexOffset = controlFlowGraph.dotRenderToStringBuilder(dotBuilder, indexOffset)
|
||||
dotBuilder.appendln()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val EDGE = " -> "
|
||||
private const val INDENT = " "
|
||||
|
||||
fun ControlFlowGraph.dotRenderToStringBuilder(builder: StringBuilder, indexOffset: Int): Int {
|
||||
with(builder) {
|
||||
val sortedNodes = sortNodes()
|
||||
val indices = sortedNodes.indicesMap().mapValues { (_, index) -> index + indexOffset }
|
||||
appendln("subgraph ${name.replace(" ", "_")} {")
|
||||
|
||||
fun CFGNode<*>.splitEdges(): Pair<List<CFGNode<*>>, List<CFGNode<*>>> =
|
||||
if (isDead) emptyList<CFGNode<*>>() to followingNodes
|
||||
else followingNodes.filter { !it.isDead } to followingNodes.filter { it.isDead }
|
||||
|
||||
sortedNodes.forEach {
|
||||
append(INDENT)
|
||||
append(indices.getValue(it))
|
||||
appendln(" [shape=box label=\"${it.render().replace("\"", "")}\"];")
|
||||
}
|
||||
appendln()
|
||||
|
||||
sortedNodes.forEachIndexed { i, node ->
|
||||
if (node.followingNodes.isEmpty()) return@forEachIndexed
|
||||
val (aliveEdges, deadEdges) = node.splitEdges()
|
||||
|
||||
fun renderEdges(edges: List<CFGNode<*>>, isDead: Boolean) {
|
||||
if (edges.isEmpty()) return
|
||||
append(INDENT)
|
||||
append(i + indexOffset)
|
||||
append(EDGE)
|
||||
append(edges.joinToString(prefix = "{", postfix = "}", separator = " ") { indices.getValue(it).toString() })
|
||||
if (isDead) {
|
||||
append(" [style=dotted]")
|
||||
}
|
||||
appendln(";")
|
||||
}
|
||||
|
||||
renderEdges(aliveEdges, false)
|
||||
renderEdges(deadEdges, true)
|
||||
}
|
||||
|
||||
appendln("}")
|
||||
|
||||
return indexOffset + sortedNodes.size
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user