< prev index next >
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
Print this page
rev 52724 : imported patch 8214031
@@ -61,10 +61,11 @@
import com.sun.tools.javac.tree.JCTree.JCBreak;
import com.sun.tools.javac.tree.JCTree.JCCase;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;
+import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
/** This pass translates away some syntactic sugar: inner classes,
* class literals, assertions, foreach loops, etc.
*
@@ -3360,99 +3361,131 @@
.restype.type));
result = tree;
}
public void visitSwitch(JCSwitch tree) {
+ handleSwitch(tree, tree.selector, tree.cases);
+ }
+
+ @Override
+ public void visitSwitchExpression(JCSwitchExpression tree) {
+ if (tree.cases.stream().noneMatch(c -> c.pats.isEmpty())) {
+ JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType,
+ List.nil()));
+ JCCase c = make.Case(JCCase.STATEMENT, List.nil(), List.of(thr), null);
+ tree.cases = tree.cases.append(c);
+ }
+ handleSwitch(tree, tree.selector, tree.cases);
+ }
+
+ private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
//expand multiple label cases:
- ListBuffer<JCCase> cases = new ListBuffer<>();
+ ListBuffer<JCCase> convertedCases = new ListBuffer<>();
- for (JCCase c : tree.cases) {
+ for (JCCase c : cases) {
switch (c.pats.size()) {
case 0: //default
case 1: //single label
- cases.append(c);
+ convertedCases.append(c);
break;
default: //multiple labels, expand:
//case C1, C2, C3: ...
//=>
//case C1:
//case C2:
//case C3: ...
List<JCExpression> patterns = c.pats;
while (patterns.tail.nonEmpty()) {
- cases.append(make_at(c.pos()).Case(JCCase.STATEMENT,
+ convertedCases.append(make_at(c.pos()).Case(JCCase.STATEMENT,
List.of(patterns.head),
List.nil(),
null));
patterns = patterns.tail;
}
c.pats = patterns;
- cases.append(c);
+ convertedCases.append(c);
break;
}
}
- for (JCCase c : cases) {
+ for (JCCase c : convertedCases) {
if (c.caseKind == JCCase.RULE && c.completesNormally) {
JCBreak b = make_at(c.pos()).Break(null);
b.target = tree;
c.stats = c.stats.append(b);
}
}
- tree.cases = cases.toList();
+ cases = convertedCases.toList();
- Type selsuper = types.supertype(tree.selector.type);
+ Type selsuper = types.supertype(selector.type);
boolean enumSwitch = selsuper != null &&
- (tree.selector.type.tsym.flags() & ENUM) != 0;
+ (selector.type.tsym.flags() & ENUM) != 0;
boolean stringSwitch = selsuper != null &&
- types.isSameType(tree.selector.type, syms.stringType);
- Type target = enumSwitch ? tree.selector.type :
+ types.isSameType(selector.type, syms.stringType);
+ Type target = enumSwitch ? selector.type :
(stringSwitch? syms.stringType : syms.intType);
- tree.selector = translate(tree.selector, target);
- tree.cases = translateCases(tree.cases);
+ selector = translate(selector, target);
+ cases = translateCases(cases);
+ if (tree.hasTag(SWITCH)) {
+ ((JCSwitch) tree).selector = selector;
+ ((JCSwitch) tree).cases = cases;
+ } else if (tree.hasTag(SWITCH_EXPRESSION)) {
+ ((JCSwitchExpression) tree).selector = selector;
+ ((JCSwitchExpression) tree).cases = cases;
+ } else {
+ Assert.error();
+ }
if (enumSwitch) {
- result = visitEnumSwitch(tree);
+ result = visitEnumSwitch(tree, selector, cases);
} else if (stringSwitch) {
- result = visitStringSwitch(tree);
+ result = visitStringSwitch(tree, selector, cases);
} else {
result = tree;
}
}
- public JCTree visitEnumSwitch(JCSwitch tree) {
- TypeSymbol enumSym = tree.selector.type.tsym;
+ public JCTree visitEnumSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
+ TypeSymbol enumSym = selector.type.tsym;
EnumMapping map = mapForEnum(tree.pos(), enumSym);
make_at(tree.pos());
Symbol ordinalMethod = lookupMethod(tree.pos(),
names.ordinal,
- tree.selector.type,
+ selector.type,
List.nil());
- JCArrayAccess selector = make.Indexed(map.mapVar,
- make.App(make.Select(tree.selector,
+ JCArrayAccess newSelector = make.Indexed(map.mapVar,
+ make.App(make.Select(selector,
ordinalMethod)));
- ListBuffer<JCCase> cases = new ListBuffer<>();
- for (JCCase c : tree.cases) {
+ ListBuffer<JCCase> newCases = new ListBuffer<>();
+ for (JCCase c : cases) {
if (c.pats.nonEmpty()) {
VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pats.head);
JCLiteral pat = map.forConstant(label);
- cases.append(make.Case(JCCase.STATEMENT, List.of(pat), c.stats, null));
+ newCases.append(make.Case(JCCase.STATEMENT, List.of(pat), c.stats, null));
} else {
- cases.append(c);
+ newCases.append(c);
}
}
- JCSwitch enumSwitch = make.Switch(selector, cases.toList());
+ JCTree enumSwitch;
+ if (tree.hasTag(SWITCH)) {
+ enumSwitch = make.Switch(newSelector, newCases.toList());
+ } else if (tree.hasTag(SWITCH_EXPRESSION)) {
+ enumSwitch = make.SwitchExpression(newSelector, newCases.toList());
+ enumSwitch.setType(tree.type);
+ } else {
+ Assert.error();
+ throw new AssertionError();
+ }
patchTargets(enumSwitch, tree, enumSwitch);
return enumSwitch;
}
- public JCTree visitStringSwitch(JCSwitch tree) {
- List<JCCase> caseList = tree.getCases();
+ public JCTree visitStringSwitch(JCTree tree, JCExpression selector, List<JCCase> caseList) {
int alternatives = caseList.size();
- if (alternatives == 0) { // Strange but legal possibility
- return make.at(tree.pos()).Exec(attr.makeNullCheck(tree.getExpression()));
+ if (alternatives == 0) { // Strange but legal possibility (only legal for switch statement)
+ return make.at(tree.pos()).Exec(attr.makeNullCheck(selector));
} else {
/*
* The general approach used is to translate a single
* string switch statement into a series of two chained
* switch statements: the first a synthesized statement
@@ -3549,11 +3582,11 @@
VarSymbol dollar_s = new VarSymbol(FINAL|SYNTHETIC,
names.fromString("s" + tree.pos + target.syntheticNameChar()),
syms.stringType,
currentMethodSym);
- stmtList.append(make.at(tree.pos()).VarDef(dollar_s, tree.getExpression()).setType(dollar_s.type));
+ stmtList.append(make.at(tree.pos()).VarDef(dollar_s, selector).setType(dollar_s.type));
VarSymbol dollar_tmp = new VarSymbol(SYNTHETIC,
names.fromString("tmp" + tree.pos + target.syntheticNameChar()),
syms.intType,
currentMethodSym);
@@ -3599,104 +3632,58 @@
// Make isomorphic switch tree replacing string labels
// with corresponding integer ones from the label to
// position map.
ListBuffer<JCCase> lb = new ListBuffer<>();
- JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
for(JCCase oneCase : caseList ) {
- // Rewire up old unlabeled break statements to the
- // replacement switch being created.
- patchTargets(oneCase, tree, switch2);
-
boolean isDefault = (oneCase.pats.isEmpty());
JCExpression caseExpr;
if (isDefault)
caseExpr = null;
else {
caseExpr = make.Literal(caseLabelToPosition.get((String)TreeInfo.skipParens(oneCase.pats.head).
type.constValue()));
}
lb.append(make.Case(JCCase.STATEMENT, caseExpr == null ? List.nil() : List.of(caseExpr),
- oneCase.getStatements(), null));
+ oneCase.stats, null));
}
- switch2.cases = lb.toList();
+ if (tree.hasTag(SWITCH)) {
+ JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
+ // Rewire up old unlabeled break statements to the
+ // replacement switch being created.
+ patchTargets(switch2, tree, switch2);
+
stmtList.append(switch2);
return make.Block(0L, stmtList.toList());
- }
- }
+ } else {
+ JCSwitchExpression switch2 = make.SwitchExpression(make.Ident(dollar_tmp), lb.toList());
- @Override
- public void visitSwitchExpression(JCSwitchExpression tree) {
- //translates switch expression to statement switch:
- //switch (selector) {
- // case C: break value;
- // ...
- //}
- //=>
- //(letexpr T exprswitch$;
- // switch (selector) {
- // case C: { exprswitch$ = value; break; }
- // }
- // exprswitch$
- //)
- VarSymbol dollar_switchexpr = new VarSymbol(Flags.FINAL|Flags.SYNTHETIC,
- names.fromString("exprswitch" + tree.pos + target.syntheticNameChar()),
- tree.type,
- currentMethodSym);
+ // Rewire up old unlabeled break statements to the
+ // replacement switch being created.
+ patchTargets(switch2, tree, switch2);
- ListBuffer<JCStatement> stmtList = new ListBuffer<>();
+ switch2.setType(tree.type);
- stmtList.append(make.at(tree.pos()).VarDef(dollar_switchexpr, null).setType(dollar_switchexpr.type));
- JCSwitch switchStatement = make.Switch(tree.selector, null);
- switchStatement.cases =
- tree.cases.stream()
- .map(c -> convertCase(dollar_switchexpr, switchStatement, tree, c))
- .collect(List.collector());
- if (tree.cases.stream().noneMatch(c -> c.pats.isEmpty())) {
- JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType,
- List.nil()));
- JCCase c = make.Case(JCCase.STATEMENT, List.nil(), List.of(thr), null);
- switchStatement.cases = switchStatement.cases.append(c);
- }
+ LetExpr res = make.LetExpr(stmtList.toList(), switch2);
- stmtList.append(translate(switchStatement));
+ res.needsCond = true;
+ res.setType(tree.type);
- result = make.LetExpr(stmtList.toList(), make.Ident(dollar_switchexpr))
- .setType(dollar_switchexpr.type);
+ return res;
}
- //where:
- private JCCase convertCase(VarSymbol dollar_switchexpr, JCSwitch switchStatement,
- JCSwitchExpression switchExpr, JCCase c) {
- make.at(c.pos());
- ListBuffer<JCStatement> statements = new ListBuffer<>();
- statements.addAll(new TreeTranslator() {
- @Override
- public void visitLambda(JCLambda tree) {}
- @Override
- public void visitClassDef(JCClassDecl tree) {}
- @Override
- public void visitMethodDef(JCMethodDecl tree) {}
+ }
+ }
+
@Override
public void visitBreak(JCBreak tree) {
- if (tree.target == switchExpr) {
- tree.target = switchStatement;
- JCExpressionStatement assignment =
- make.Exec(make.Assign(make.Ident(dollar_switchexpr),
- translate(tree.value))
- .setType(dollar_switchexpr.type));
- result = make.Block(0, List.of(assignment,
- tree));
- tree.value = null;
- } else {
- result = tree;
- }
+ if (tree.isValueBreak()) {
+ tree.value = translate(tree.value, tree.target.type);
}
- }.translate(c.stats));
- return make.Case(JCCase.STATEMENT, c.pats, statements.toList(), null);
+ result = tree;
}
public void visitNewArray(JCNewArray tree) {
tree.elemtype = translate(tree.elemtype);
for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
< prev index next >