< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page
rev 51104 : imported patch switch

*** 24,34 **** --- 24,38 ---- */ package com.sun.tools.javac.comp; import java.util.*; + import java.util.Map.Entry; + import java.util.function.Function; + import java.util.stream.Stream; + import com.sun.source.tree.CaseTree.CaseKind; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Kinds.KindSelector; import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.main.Option.PkgInfo;
*** 52,61 **** --- 56,69 ---- import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.DEREF; import static com.sun.tools.javac.jvm.ByteCodes.*; + 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 static com.sun.tools.javac.tree.JCTree.Tag.*; /** This pass translates away some syntactic sugar: inner classes, * class literals, assertions, foreach loops, etc.
*** 362,371 **** --- 370,386 ---- outerThisStack.head != null) visitSymbol(outerThisStack.head); } super.visitApply(tree); } + + @Override + public void visitBreak(JCBreak tree) { + if (tree.isValueBreak()) + scan(tree.value); + } + } ClassSymbol ownerToCopyFreeVarsFrom(ClassSymbol c) { if (!c.isLocal()) { return null;
*** 3338,3347 **** --- 3353,3396 ---- .restype.type)); result = tree; } public void visitSwitch(JCSwitch tree) { + //expand multiple label cases: + ListBuffer<JCCase> cases = new ListBuffer<>(); + + for (JCCase c : tree.cases) { + switch (c.pats.size()) { + case 0: //default + case 1: //single label + cases.append(c); + break; + default: //multiple labels, expand: + List<JCExpression> patterns = c.pats; + while (patterns.tail.nonEmpty()) { + cases.append(make_at(c.pos()).Case(JCCase.STATEMENT, + List.of(patterns.head), + List.nil(), + null)); + patterns = patterns.tail; + } + c.pats = patterns; + cases.append(c); + break; + } + } + + for (JCCase c : cases) { + 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(); + Type selsuper = types.supertype(tree.selector.type); boolean enumSwitch = selsuper != null && (tree.selector.type.tsym.flags() & ENUM) != 0; boolean stringSwitch = selsuper != null && types.isSameType(tree.selector.type, syms.stringType);
*** 3369,3382 **** JCArrayAccess selector = make.Indexed(map.mapVar, make.App(make.Select(tree.selector, ordinalMethod))); ListBuffer<JCCase> cases = new ListBuffer<>(); for (JCCase c : tree.cases) { ! if (c.pat != null) { ! VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pat); JCLiteral pat = map.forConstant(label); ! cases.append(make.Case(pat, c.stats)); } else { cases.append(c); } } JCSwitch enumSwitch = make.Switch(selector, cases.toList()); --- 3418,3431 ---- JCArrayAccess selector = make.Indexed(map.mapVar, make.App(make.Select(tree.selector, ordinalMethod))); ListBuffer<JCCase> cases = new ListBuffer<>(); for (JCCase c : tree.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)); } else { cases.append(c); } } JCSwitch enumSwitch = make.Switch(selector, cases.toList());
*** 3440,3453 **** // Map of hash codes to the string case labels having that hashCode. Map<Integer, Set<String>> hashToString = new LinkedHashMap<>(alternatives + 1, 1.0f); int casePosition = 0; - for(JCCase oneCase : caseList) { - JCExpression expression = oneCase.getExpression(); ! if (expression != null) { // expression for a "default" case is null String labelExpr = (String) expression.type.constValue(); Integer mapping = caseLabelToPosition.put(labelExpr, casePosition); Assert.checkNull(mapping); int hashCode = labelExpr.hashCode(); --- 3489,3502 ---- // Map of hash codes to the string case labels having that hashCode. Map<Integer, Set<String>> hashToString = new LinkedHashMap<>(alternatives + 1, 1.0f); int casePosition = 0; ! for(JCCase oneCase : caseList) { ! if (oneCase.pats.nonEmpty()) { // pats is empty for a "default" case ! JCExpression expression = oneCase.pats.head; String labelExpr = (String) expression.type.constValue(); Integer mapping = caseLabelToPosition.put(labelExpr, casePosition); Assert.checkNull(mapping); int hashCode = labelExpr.hashCode();
*** 3527,3537 **** ListBuffer<JCStatement> lb = new ListBuffer<>(); JCBreak breakStmt = make.Break(null); breakStmt.target = switch1; lb.append(elsepart).append(breakStmt); ! caseBuffer.append(make.Case(make.Literal(hashCode), lb.toList())); } switch1.cases = caseBuffer.toList(); stmtList.append(switch1); --- 3576,3586 ---- ListBuffer<JCStatement> lb = new ListBuffer<>(); JCBreak breakStmt = make.Break(null); breakStmt.target = switch1; lb.append(elsepart).append(breakStmt); ! caseBuffer.append(make.Case(JCCase.STATEMENT, List.of(make.Literal(hashCode)), lb.toList(), null)); } switch1.cases = caseBuffer.toList(); stmtList.append(switch1);
*** 3544,3574 **** for(JCCase oneCase : caseList ) { // Rewire up old unlabeled break statements to the // replacement switch being created. patchTargets(oneCase, tree, switch2); ! boolean isDefault = (oneCase.getExpression() == null); JCExpression caseExpr; if (isDefault) caseExpr = null; else { ! caseExpr = make.Literal(caseLabelToPosition.get((String)TreeInfo.skipParens(oneCase. ! getExpression()). type.constValue())); } ! lb.append(make.Case(caseExpr, ! oneCase.getStatements())); } switch2.cases = lb.toList(); stmtList.append(switch2); return make.Block(0L, stmtList.toList()); } } public void visitNewArray(JCNewArray tree) { tree.elemtype = translate(tree.elemtype); for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail) if (t.head != null) t.head = translate(t.head, syms.intType); tree.elems = translate(tree.elems, types.elemtype(tree.type)); --- 3593,3680 ---- 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)); } switch2.cases = lb.toList(); stmtList.append(switch2); return make.Block(0L, stmtList.toList()); } } + @Override + public void visitSwitchExpression(JCSwitchExpression tree) { + VarSymbol dollar_switchexpr = new VarSymbol(Flags.FINAL|Flags.SYNTHETIC, + names.fromString("exprswitch" + tree.pos + target.syntheticNameChar()), + tree.type, + currentMethodSym); + + ListBuffer<JCStatement> 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); + } + + stmtList.append(translate(switchStatement)); + + result = make.LetExpr(stmtList.toList(), make.Ident(dollar_switchexpr)) + .setType(dollar_switchexpr.type); + } + //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; + } + } + }.translate(c.stats)); + return make.Case(JCCase.STATEMENT, c.pats, statements.toList(), null); + } + public void visitNewArray(JCNewArray tree) { tree.elemtype = translate(tree.elemtype); for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail) if (t.head != null) t.head = translate(t.head, syms.intType); tree.elems = translate(tree.elems, types.elemtype(tree.type));
*** 3600,3610 **** else result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); } public void visitLetExpr(LetExpr tree) { ! tree.defs = translateVarDefs(tree.defs); tree.expr = translate(tree.expr, tree.type); result = tree; } // There ought to be nothing to rewrite here; --- 3706,3716 ---- else result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); } public void visitLetExpr(LetExpr tree) { ! tree.defs = translate(tree.defs); tree.expr = translate(tree.expr, tree.type); result = tree; } // There ought to be nothing to rewrite here;
< prev index next >