diff -r df065f8356d7 -r e4ba5414c8b4 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Mon Dec 03 12:35:27 2018 +0530 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Mon Dec 03 10:37:36 2018 +0100 @@ -63,6 +63,7 @@ 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, @@ -3362,14 +3363,29 @@ } 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 cases) { //expand multiple label cases: - ListBuffer cases = new ListBuffer<>(); - - for (JCCase c : tree.cases) { + ListBuffer convertedCases = new ListBuffer<>(); + + 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: ... @@ -3379,19 +3395,19 @@ //case C3: ... List 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; @@ -3399,58 +3415,75 @@ } } - tree.cases = cases.toList(); - - Type selsuper = types.supertype(tree.selector.type); + cases = convertedCases.toList(); + + 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 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 cases = new ListBuffer<>(); - for (JCCase c : tree.cases) { + ListBuffer 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 caseList = tree.getCases(); + public JCTree visitStringSwitch(JCTree tree, JCExpression selector, List 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 @@ -3551,7 +3584,7 @@ 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()), @@ -3601,12 +3634,7 @@ // position map. ListBuffer 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) @@ -3617,85 +3645,44 @@ } lb.append(make.Case(JCCase.STATEMENT, caseExpr == null ? List.nil() : List.of(caseExpr), - oneCase.getStatements(), null)); + oneCase.stats, null)); } - switch2.cases = lb.toList(); - stmtList.append(switch2); - - return make.Block(0L, stmtList.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()); + + // Rewire up old unlabeled break statements to the + // replacement switch being created. + patchTargets(switch2, tree, switch2); + + switch2.setType(tree.type); + + LetExpr res = make.LetExpr(stmtList.toList(), switch2); + + res.needsCond = true; + res.setType(tree.type); + + return res; + } } } @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); - - ListBuffer stmtList = new ListBuffer<>(); - - 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); + public void visitBreak(JCBreak tree) { + if (tree.isValueBreak()) { + tree.value = translate(tree.value, tree.target.type); } - - stmtList.append(translate(switchStatement)); - - result = make.LetExpr(stmtList.toList(), make.Ident(dollar_switchexpr)) - .setType(dollar_switchexpr.type); + result = tree; } - //where: - private JCCase convertCase(VarSymbol dollar_switchexpr, JCSwitch switchStatement, - JCSwitchExpression switchExpr, JCCase c) { - make.at(c.pos()); - ListBuffer 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; - } - } - }.translate(c.stats)); - return make.Case(JCCase.STATEMENT, c.pats, statements.toList(), null); - } public void visitNewArray(JCNewArray tree) { tree.elemtype = translate(tree.elemtype);