Skip to content

Commit

Permalink
Move default case reordering to MethodProcessor
Browse files Browse the repository at this point in the history
This way it also fixes it for old-style switches.
  • Loading branch information
jpenilla committed May 5, 2024
1 parent 28970fe commit 773d4f6
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 195 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ public static RootStatement codeToJava(StructClass cl, StructMethod mt, MethodDe
}

if (changed) {
SwitchHelper.ensureDefaultCaseLast(root);
continue;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,45 @@
import java.util.stream.Collectors;

public final class SwitchHelper {
public static void ensureDefaultCaseLast(Statement stat) {
for (Statement st : new ArrayList<>(stat.getStats())) {
ensureDefaultCaseLast(st);
}

if (stat instanceof SwitchStatement switchStmt) {
ensureDefaultCaseLast(switchStmt);
}
}

private static void ensureDefaultCaseLast(final SwitchStatement stat) {
// Ensure default case is last. Mostly needed when edges are merged and it loses it's initial ending position.
int defaultIdx = -1;
// First, find default case if it exists.
for (int i = 0; i < stat.getCaseStatements().size(); i++) {
List<StatEdge> edges = stat.getCaseEdges().get(i);

// As switch expressions can be compiled to a tableswitch, any gaps will contain a jump to the default element.
// Switch expressions cannot have a case point to the same statement as the default, so we check for default first and don't check for cases if it exists [TestConstructorSwitchExpression1]

for (StatEdge edge : edges) {
if (edge == stat.getDefaultEdge()) {
defaultIdx = i;
break;
}
}
}
// Shift found default statement to end if needed
if (defaultIdx != -1 && defaultIdx != stat.getCaseEdges().size() - 1) {
stat.getCaseStatements().add(stat.getCaseStatements().remove(defaultIdx));
stat.getCaseEdges().add(stat.getCaseEdges().remove(defaultIdx));
stat.getCaseValues().add(stat.getCaseValues().remove(defaultIdx));
Exprent removedGuard = stat.getCaseGuards().size() > defaultIdx ? stat.getCaseGuards().remove(defaultIdx) : null;
if (removedGuard != null) {
stat.getCaseGuards().add(removedGuard);
}
}
}

public static boolean simplifySwitches(Statement stat, StructMethod mt, RootStatement root) {
boolean ret = false;
if (stat instanceof SwitchStatement) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,6 @@ public TextBuffer toJava(int indent) {

buf.append(this.backing.getHeadexprent().toJava(indent)).append(" {").appendLineSeparator();

// Ensure default case is last. Mostly needed when edges are merged and it loses it's initial ending position.
int defaultIdx = -1;
// First, find default case if it exists.
for (int i = 0; i < this.backing.getCaseStatements().size(); i++) {
List<StatEdge> edges = this.backing.getCaseEdges().get(i);

// As switch expressions can be compiled to a tableswitch, any gaps will contain a jump to the default element.
// Switch expressions cannot have a case point to the same statement as the default, so we check for default first and don't check for cases if it exists [TestConstructorSwitchExpression1]

for (StatEdge edge : edges) {
if (edge == this.backing.getDefaultEdge()) {
if (isExhaustive) {
if (isSyntheticThrowEdge(edge)) {
break; // just don't mark as default
}
}
defaultIdx = i;
break;
}
}
}
// Shift found default statement to end if needed
if (defaultIdx != -1 && defaultIdx != this.backing.getCaseEdges().size() - 1) {
this.backing.getCaseStatements().add(this.backing.getCaseStatements().remove(defaultIdx));
this.backing.getCaseEdges().add(this.backing.getCaseEdges().remove(defaultIdx));
this.backing.getCaseValues().add(this.backing.getCaseValues().remove(defaultIdx));
Exprent removedGuard = this.backing.getCaseGuards().size() > defaultIdx ? this.backing.getCaseGuards().remove(defaultIdx) : null;
if (removedGuard != null) {
this.backing.getCaseGuards().add(removedGuard);
}
}

for (int i = 0; i < this.backing.getCaseStatements().size(); i++) {
Statement stat = this.backing.getCaseStatements().get(i);
List<StatEdge> edges = this.backing.getCaseEdges().get(i);
Expand Down
151 changes: 75 additions & 76 deletions testData/results/pkg/TestSwitchPatternMatching19.dec
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ public class TestSwitchPatternMatching19 {
static void test(TestSwitchPatternMatching19.XXX s) {
<unknown> var1;
switch (s) {// 5
case null:
default:
System.out.println("f");// 11
break;
case X1:
System.out.println("x1");// 6
break;
Expand All @@ -22,6 +18,10 @@ public class TestSwitchPatternMatching19 {
System.out.println("d");
break;
case TestSwitchPatternMatching19.XXX var11 when false:
break;
case null:
default:
System.out.println("f");// 11
}
}// 13

Expand Down Expand Up @@ -114,73 +114,72 @@ class 'pkg/TestSwitchPatternMatching19' {
2d 6
2e 6
2f 6
30 12
31 12
32 12
33 12
34 12
35 12
36 12
37 12
38 13
3b 14
3d 14
3e 14
3f 14
40 14
41 14
42 14
43 14
49 15
4a 15
4b 15
4c 15
4d 15
4e 15
4f 15
50 15
51 16
54 17
57 17
58 17
59 17
5a 17
5b 17
64 18
65 18
66 18
67 18
68 18
69 18
6a 18
6b 18
6c 19
6f 20
72 20
73 20
74 20
75 20
76 20
77 20
78 20
7e 21
7f 21
80 21
81 21
82 21
83 21
84 21
85 21
86 22
94 9
95 9
96 9
97 9
98 9
99 9
9a 9
9b 9
9c 10
30 8
31 8
32 8
33 8
34 8
35 8
36 8
37 8
38 9
3b 10
3d 10
3e 10
3f 10
40 10
41 10
42 10
43 10
49 11
4a 11
4b 11
4c 11
4d 11
4e 11
4f 11
50 11
51 12
54 13
57 13
58 13
59 13
5a 13
5b 13
64 14
65 14
66 14
67 14
68 14
69 14
6a 14
6b 14
6c 15
6f 16
72 16
73 16
74 16
75 16
76 16
77 16
78 16
7e 17
7f 17
80 17
81 17
82 17
83 17
84 17
85 17
86 18
94 23
95 23
96 23
97 23
98 23
99 23
9a 23
9b 23
9f 25
}

Expand Down Expand Up @@ -262,11 +261,11 @@ class 'pkg/TestSwitchPatternMatching19' {

Lines mapping:
5 <-> 7
6 <-> 13
7 <-> 15
8 <-> 18
9 <-> 21
11 <-> 10
6 <-> 9
7 <-> 11
8 <-> 14
9 <-> 17
11 <-> 24
13 <-> 26
16 <-> 29
17 <-> 35
Expand Down
Loading

0 comments on commit 773d4f6

Please sign in to comment.