@@ -127,7 +127,7 @@ object PatMat {
127
127
override def toString = i " TypeTest( $scrutinee: $tpt) "
128
128
}
129
129
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) {
131
131
def pos = tree.pos
132
132
def condition = applyOverloaded(tree, nme.EQ , scrutinee :: Nil , Nil , defn.BooleanType )
133
133
override def toString = i " EqualTest( $tree == $scrutinee) "
@@ -404,14 +404,54 @@ object PatMat {
404
404
405
405
val emitted = mutable.Set [Int ]()
406
406
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
+
407
443
def emit (node : Node ): Tree = {
408
444
if (selfCheck) {
409
445
assert(node.isInstanceOf [CallNode ] || ! emitted.contains(node.id), node.id)
410
446
emitted += node.id
411
447
}
412
448
node match {
413
449
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)
415
455
case node @ LetNode (sym, body) =>
416
456
val symDef =
417
457
if (sym.is(Label )) DefDef (sym, emit(labelled(sym)))
0 commit comments