summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-01-23 22:01:43 -0800
committerPaul Phillips <paulp@improving.org>2012-01-23 22:01:43 -0800
commitdae39538513420bf66b61ff80d69116f9617d2b5 (patch)
treecd7701bdfee9969013ca626dd9af31f1250b735b /src
parentcc3ad6e00ad3a5cfcbbc47bf62f425a31911f79f (diff)
parent963ab412ce2e404a92d89a3f1f61d5f669426eb9 (diff)
downloadscala-dae39538513420bf66b61ff80d69116f9617d2b5.tar.gz
scala-dae39538513420bf66b61ff80d69116f9617d2b5.tar.bz2
scala-dae39538513420bf66b61ff80d69116f9617d2b5.zip
Merge remote-tracking branch 'gkossakowski/virtpatmat-emitswitch' into develop
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala68
1 files changed, 27 insertions, 41 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
index 4104803194..ed185c27d6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
@@ -1128,62 +1128,48 @@ defined class Foo */
// }
// }
- def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type): Option[Tree] = if (optimizingCodeGen) {
- def unfold(tms: List[TreeMaker], currLabel: Option[Symbol] = None, nextLabel: Option[Symbol] = None): List[CaseDef] = tms match {
- // constant
- case (EqualityTestTreeMaker(_, const@SwitchablePattern(), _)) :: (btm@BodyTreeMaker(body, _)) :: Nil => import CODE._
- @inline
- def substedBody = btm.substitution(body)
- val labelledBody = currLabel match {
- case None => substedBody // currLabel.isEmpty implies nextLabel.isEmpty
- case Some(myLabel) =>
- LabelDef(myLabel, Nil,
- nextLabel match {
- case None => substedBody
- case Some(next) => ID(next) APPLY ()
- }
- )
- }
- List(CaseDef(const, EmptyTree, labelledBody))
-
- // alternatives
- case AlternativesTreeMaker(_, altss, _) :: bodyTm :: Nil => // assert(currLabel.isEmpty && nextLabel.isEmpty)
- val labels = altss map { alts =>
- Some(freshSym(NoPosition, MethodType(Nil, pt), "$alt$") setFlag (METHOD | LABEL))
- }
-
- val caseDefs = (altss, labels, labels.tail :+ None).zipped.map { case (alts, currLabel, nextLabel) =>
- unfold(alts :+ bodyTm, currLabel, nextLabel)
- }
-
- if (caseDefs exists (_.isEmpty)) Nil
- else caseDefs.flatten
-
- case _ => Nil // failure
- }
+ def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type): Option[Tree] = if (!optimizingCodeGen) None else {
+ def sequence[T](xs: List[Option[T]]): Option[List[T]] =
+ if (xs exists (_.isEmpty)) None else Some(xs.flatten)
val caseDefs = cases map { makers =>
removeSubstOnly(makers) match {
// default case (don't move this to unfold, as it may only occur on the top level, not as an alternative -- well, except in degenerate matches)
case (btm@BodyTreeMaker(body, _)) :: Nil =>
- List(CaseDef(Ident(nme.WILDCARD), EmptyTree, btm.substitution(body)))
- case nonTrivialMakers =>
- unfold(nonTrivialMakers)
+ Some(CaseDef(Ident(nme.WILDCARD), EmptyTree, btm.substitution(body)))
+ // constant
+ case (EqualityTestTreeMaker(_, const@SwitchablePattern(), _)) :: (btm@BodyTreeMaker(body, _)) :: Nil => import CODE._
+ Some(CaseDef(const, EmptyTree, btm.substitution(body)))
+ // alternatives
+ case AlternativesTreeMaker(_, altss, _) :: (btm@BodyTreeMaker(body, _)) :: Nil => // assert(currLabel.isEmpty && nextLabel.isEmpty)
+ val caseConstants = altss map {
+ case EqualityTestTreeMaker(_, const@SwitchablePattern(), _) :: Nil =>
+ Some(const)
+ case _ =>
+ None
+ }
+
+ sequence(caseConstants) map { contants =>
+ val substedBody = btm.substitution(body)
+ CaseDef(Alternative(contants), EmptyTree, substedBody)
+ }
+ case _ =>
+ None //failure (can't translate pattern to a switch)
}
}
- if (caseDefs exists (_.isEmpty)) None
- else { import CODE._
+ sequence(caseDefs) map { caseDefs =>
+ import CODE._
val matcher = BLOCK(
VAL(scrutSym) === scrut, // TODO: type test for switchable type if patterns allow switch but the scrutinee doesn't
- Match(REF(scrutSym), caseDefs.flatten) // match on scrutSym, not scrut to avoid duplicating scrut
+ Match(REF(scrutSym), caseDefs) // match on scrutSym, not scrut to avoid duplicating scrut
)
// matcher filter (tree => tree.tpe == null) foreach println
// treeBrowser browse matcher
- Some(matcher) // set type to avoid recursion in typedMatch
+ matcher // set type to avoid recursion in typedMatch
}
- } else None
+ }
def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): List[List[TreeMaker]] =
doCSE(prevBinder, doDCE(prevBinder, cases, pt), pt)