@@ -127,7 +127,7 @@ object PatMat {
127127 override def toString = i " TypeTest( $scrutinee: $tpt) "
128128 }
129129
130- class EqualTest (scrut : Symbol , tree : Tree , ons : Node , onf : Node ) extends Test (scrut, ons, onf) {
130+ class EqualTest (scrut : Symbol , val tree : Tree , ons : Node , onf : Node ) extends Test (scrut, ons, onf) {
131131 def pos = tree.pos
132132 def condition = applyOverloaded(tree, nme.EQ , scrutinee :: Nil , Nil , defn.BooleanType )
133133 override def toString = i " EqualTest( $tree == $scrutinee) "
@@ -404,14 +404,54 @@ object PatMat {
404404
405405 val emitted = mutable.Set [Int ]()
406406
407+ /** Collect longest list of nodes that represent possible cases of
408+ * a switch, including a last default case, by starting with this
409+ * node on following onSuccess nodes.
410+ */
411+ def collectSwitchCases (node : Test ): List [Node ] = {
412+ def isSwitchableType (tpe : Type ): Boolean =
413+ (tpe isRef defn.IntClass ) ||
414+ (tpe isRef defn.ByteClass ) ||
415+ (tpe isRef defn.ShortClass ) ||
416+ (tpe isRef defn.CharClass )
417+
418+ val scrutinee = node.scrutinee
419+
420+ def isIntConst (tree : Tree ) = tree match {
421+ case Literal (const) => const.isIntRange
422+ case _ => false
423+ }
424+
425+ def recur (node : Node ): List [Node ] = node match {
426+ case node : EqualTest if node.scrutinee === scrutinee && isIntConst(node.tree) =>
427+ node :: recur(node.onFailure)
428+ case _ =>
429+ node :: Nil
430+ }
431+
432+ recur(node)
433+ }
434+
435+ /** Emit cases of a switch */
436+ def emitSwitchCases (cases : List [Node ]): List [CaseDef ] = cases match {
437+ case (test : EqualTest ) :: cases1 =>
438+ CaseDef (test.tree, EmptyTree , emit(test.onSuccess)) :: emitSwitchCases(cases1)
439+ case (default : Node ) :: Nil =>
440+ CaseDef (Underscore (defn.IntType ), EmptyTree , emit(default)) :: Nil
441+ }
442+
407443 def emit (node : Node ): Tree = {
408444 if (selfCheck) {
409445 assert(node.isInstanceOf [CallNode ] || ! emitted.contains(node.id), node.id)
410446 emitted += node.id
411447 }
412448 node match {
413449 case node : Test =>
414- If (node.condition, emit(node.onSuccess), emit(node.onFailure)).withPos(node.pos)
450+ val switchCases = collectSwitchCases(node)
451+ if (switchCases.lengthCompare(4 ) >= 0 ) // at least 3 cases + default
452+ Match (node.scrutinee, emitSwitchCases(switchCases))
453+ else
454+ If (node.condition, emit(node.onSuccess), emit(node.onFailure)).withPos(node.pos)
415455 case node @ LetNode (sym, body) =>
416456 val symDef =
417457 if (sym.is(Label )) DefDef (sym, emit(labelled(sym)))
0 commit comments