summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-10-03 04:43:31 +0000
committerPaul Phillips <paulp@improving.org>2009-10-03 04:43:31 +0000
commit6ac3bdaf7ff56b6234508087f6927b689acd5e2c (patch)
treea8757def9006869adc5b3b41c033b878fde12c82
parent845d054b6c5c345a47e3b7bb2b9b0a180ebf1c4f (diff)
downloadscala-6ac3bdaf7ff56b6234508087f6927b689acd5e2c.tar.gz
scala-6ac3bdaf7ff56b6234508087f6927b689acd5e2c.tar.bz2
scala-6ac3bdaf7ff56b6234508087f6927b689acd5e2c.zip
Pattern Matcher Productions is pleased to annou...
Pattern Matcher Productions is pleased to announce, for what might be the first time ever, the thrilling arrival of... Polly Morphism! (Cue arena music) Now that the basic pattern variations are straitjacketed I can corral the strays.
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala82
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternBindings.scala6
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala5
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala36
4 files changed, 48 insertions, 81 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index f39a2d0f08..a904b9026d 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -87,60 +87,7 @@ trait ParallelMatching extends ast.TreeDSL
/** the injection here handles alternatives and unapply type tests */
final def make(tvars: List[Symbol], row1: List[Row]): Rep = {
- def classifyPat(opat: Pattern, j: Int): Pattern = {
- def testVar = tvars(j)
-
- // @pre for doUnapplySeq: is not right-ignoring (no star pattern) ; no exhaustivity check
- def doUnapplySeq(tptArg: Tree, xs: List[Tree]) = {
- testVar setFlag Flags.TRANS_FLAG
-
- opat rebindTo normalizedListPattern(xs, tptArg.tpe)
- }
- def doValMatch(x: Tree, fn: Tree) = {
- val p = Pattern(x)
-
- def examinePrefix(path: Tree) = (path, path.tpe) match {
- case (_, t: ThisType) => singleType(t, x.symbol) // cases 2/3 are e.g. `case Some(p._2)' in s.c.jcl.Map
- case (_: Apply, _) => PseudoType(x) // outer-matching: test/files/pos/t154.scala
- case _ => singleType(Pattern(path).mkSingleton, x.symbol) // old
- }
- val singletonType =
- if (p.isModule) p.mkSingleton else fn match {
- case Select(path, _) => examinePrefix(path)
- case x: Ident => Pattern(fn).equalsCheck
- }
- val typeToTest = mkEqualsRef(singletonType)
-
- val t = Typed(WILD(typeToTest), TypeTree(singletonType)) setType typeToTest
- opat rebindTo t
- }
-
- def doReturnOriginal(t: Tree) = cond(t) {
- case EmptyTree | WILD() | _: Literal | _: Typed | _: ArrayValue => true
- }
-
- // NOTE - this seemingly pointless representation has a point. Until extractors
- // can be trusted, I only feel safe using them by using one to a match, because it is
- // in the transitions they are broken. This will return to a more traditional
- // pattern match before the final curtain falls.
- val f = List[PartialFunction[Tree, Pattern]](
- { case _: Alternative => opat } ,
- { case _: Typed => opat simplify testVar } ,
- { case x if doReturnOriginal(x) => opat } ,
- // This busts things for now
- // { case _: Ident => opat.simplify() } ,
- { case _: Ident | _: Select => opat.rebindToEqualsCheck() } ,
- { case _: This => opat } ,
- { case UnapplySeq(tptArg, xs) => doUnapplySeq(tptArg, xs) } ,
- { case UnApply(Apply(fn, _), _) => opat simplify testVar } ,
- { case x @ Apply_Function(fn) => doValMatch(x, fn) } ,
- { case Apply_Value(_, _) => opat simplify testVar } ,
- { case Apply_CaseClass(_, _) => opat.simplify() } ,
- { case x => abort("Unexpected pattern: " + x.getClass + " => " + x) }
- ) reduceLeft (_ orElse _)
-
- f(opat.tree)
- }
+ def classifyPat(opat: Pattern, j: Int): Pattern = opat simplify tvars(j)
val rows = row1 flatMap (_ expandAlternatives classifyPat)
if (rows.length != row1.length) make(tvars, rows) // recursive call if any change
@@ -202,8 +149,6 @@ trait ParallelMatching extends ast.TreeDSL
def dummyPatterns = dummies map (x => Pattern(x))
def apply(i: Int): Pattern = ps(i)
- // XXX temp
- def zip() = trees.zipWithIndex
def pzip() = ps.zipWithIndex
def zip[T](others: List[T]) = trees zip others
def pzip[T](others: List[T]) = ps zip others
@@ -218,9 +163,9 @@ trait ParallelMatching extends ast.TreeDSL
val (lits, others) = trees span isSwitchableConst
others match {
- case Nil => Some(lits, None)
+ case Nil => Some((lits, None))
// TODO: This needs to also allow the case that the last is a compatible type pattern.
- case List(x) if isSwitchableDefault(x) => Some(lits, Some(x))
+ case List(x) if isSwitchableDefault(x) => Some((lits, Some(x)))
case _ => None
}
}
@@ -540,7 +485,7 @@ trait ParallelMatching extends ast.TreeDSL
def getTransition(): Branch[TransitionContext] = {
assert(scrut.tpe <:< head.tpe, "fatal: %s is not <:< %s".format(scrut, head.tpe))
- val av @ ArrayValue(_, elems) = head.boundTree
+ val av @ ArrayValue(_, elems) = head.tree
val ys = if (isRightIgnoring(av)) elems.init else elems
val vs = ys map (y => newVar(unbind(y).pos, scrut.elemType))
def scrutCopy = scrut.id.duplicate
@@ -658,7 +603,10 @@ trait ParallelMatching extends ast.TreeDSL
// remaining: remaining, rows index and pattern
def join[T](xs: List[Option[T]]): List[T] = xs.flatMap(x => x)
val (moreSpecific, subsumed, remaining) : (List[Tree], List[(Int, List[Tree])], List[(Int, Tree)]) = unzip3(
- for ((pat @ Stripped(spat), j) <- pats.zip) yield {
+ for ((pattern, j) <- pats.pzip()) yield {
+ val spat: Tree = pattern.tree
+ val pat: Tree = pattern.boundTree
+
def eqHead(tpe: Type) = pats.headType =:= tpe
def alts(yes: Tree, no: Tree) = if (eqHead(pat.tpe)) yes else no
@@ -711,6 +659,8 @@ trait ParallelMatching extends ast.TreeDSL
/** returns casted symbol, success matrix and optionally fail matrix for type test on the top of this column */
final def getTransition(): Branch[Scrutinee] = {
val casted = scrut castedTo pats.headType
+ // val neededCast = (scrut ne casted)
+
val isAnyMoreSpecific = moreSpecific exists (x => !x.isEmpty)
def mkZipped = moreSpecific zip subsumed map { case (mspat, (j, pats)) => (j, mspat :: pats) }
@@ -1000,18 +950,18 @@ trait ParallelMatching extends ast.TreeDSL
final def expand(roots: List[Symbol], cases: List[Tree]): ExpandedMatrix = {
val (rows, finals) = List.unzip(
for ((CaseDef(pat, guard, body), index) <- cases.zipWithIndex) yield {
- def mkRow(ps: List[Tree]) = Row(toPats(ps), NoBinding, Guard(guard), index)
+ def mkRow(ps: List[Pattern]) = Row(ps, NoBinding, Guard(guard), index)
- def rowForPat: Option[Row] = condOpt(pat) {
- case _ if roots.length <= 1 => mkRow(List(pat))
- case Apply(fn, args) => mkRow(args)
- case WILD() => mkRow(getDummies(roots.length))
+ def rowForPat = pat match {
+ case _ if roots.length <= 1 => mkRow(List(Pattern(pat)))
+ case Apply(fn, args) => mkRow(toPats(args))
+ case WILD() => mkRow(emptyPatterns(roots.length))
}
(rowForPat, FinalState(NoBinding, body, definedVars(pat)))
}
)
- new ExpandedMatrix(rows flatMap (x => x), finals)
+ new ExpandedMatrix(rows, finals)
}
/** returns the condition in "if (cond) k1 else k2"
diff --git a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
index eeb8938b6a..575050821a 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
@@ -21,6 +21,12 @@ trait PatternBindings extends ast.TreeDSL
def mkEqualsRef(tpe: Type) = typeRef(NoPrefix, EqualsPatternClass, List(tpe))
def decodedEqualsType(tpe: Type) = condOpt(tpe) { case TypeRef(_, EqualsPatternClass, List(arg)) => arg } getOrElse (tpe)
+ // used as argument to `EqualsPatternClass'
+ case class PseudoType(o: Tree) extends SimpleTypeProxy {
+ override def underlying: Type = o.tpe
+ override def safeToString: String = "PseudoType("+o+")"
+ }
+
// If the given pattern contains alternatives, return it as a list of patterns.
// Makes typed copies of any bindings found so all alternatives point to final state.
def extractBindings(p: Tree, prevBindings: Tree => Tree = identity[Tree] _): List[Tree] = {
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index 19baaab00a..dd9022cd2d 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -114,11 +114,6 @@ trait PatternNodes extends ast.TreeDSL
}
}
- // used as argument to `EqualsPatternClass'
- case class PseudoType(o: Tree) extends SimpleTypeProxy {
- override def underlying: Type = o.tpe
- override def safeToString: String = "PseudoType("+o+")"
- }
}
/** For folding a list into a well-typed x :: y :: etc :: tree. */
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index 2bc76b57f1..6c72caed0c 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -48,6 +48,7 @@ trait Patterns extends ast.TreeDSL {
// 8.1.1
case class VariablePattern(tree: Ident) extends Pattern {
override def irrefutableFor(tpe: Type) = true
+ override def simplify(testVar: Symbol) = this.rebindToEqualsCheck()
}
// 8.1.1 (b)
@@ -72,17 +73,14 @@ trait Patterns extends ast.TreeDSL {
// 8.1.4
case class StableIdPattern(tree: Ident) extends Pattern {
- override def simplify(testVar: Symbol) = rebindToEqualsCheck()
+ override def simplify(testVar: Symbol) = this.rebindToEqualsCheck()
}
// 8.1.4 (b)
case class SelectPattern(tree: Select) extends Pattern {
- // override def simplify(testVar: Symbol) =
- // this rebindToEmpty mkEqualsRef(singleType(pre, sym))
+ override def simplify(testVar: Symbol) = this.rebindToEqualsCheck()
}
- // 8.1.4 (b)
-
// 8.1.5
case class ConstructorPattern(tree: Apply) extends ApplyPattern {
require(fn.isType)
@@ -98,8 +96,22 @@ trait Patterns extends ast.TreeDSL {
case class ApplyValuePattern(tree: Apply) extends ApplyPattern {
require(!fn.isType)
- override def simplify(testVar: Symbol) =
- this rebindToEmpty mkEqualsRef(singleType(prefix, sym))
+ override def simplify(testVar: Symbol) = {
+ def examinePrefix(path: Tree) = (path, path.tpe) match {
+ case (_, t: ThisType) => singleType(t, sym)
+ case (_: Apply, _) => PseudoType(tree)
+ case _ => singleType(Pattern(path).mkSingleton, sym)
+ }
+ val singletonType =
+ if (isModule) mkSingleton else fn match {
+ case Select(path, _) => examinePrefix(path)
+ case x: Ident => Pattern(x).equalsCheck
+ }
+
+ val typeToTest = mkEqualsRef(singletonType)
+ val tt = Typed(WILD(typeToTest), TypeTree(singletonType)) setType typeToTest
+ this rebindTo tt
+ }
}
// 8.1.6
@@ -114,6 +126,7 @@ trait Patterns extends ast.TreeDSL {
private val MethodType(List(arg, _*), _) = fn.tpe
private def uaTyped = Typed(tree, TypeTree(arg.tpe)) setType arg.tpe
+ // can fix #1697 here?
override def simplify(testVar: Symbol) =
if (testVar.tpe <:< arg.tpe) this
else this rebindTo uaTyped
@@ -154,10 +167,13 @@ trait Patterns extends ast.TreeDSL {
// XXX - temporary pattern until we have integrated every tree type.
case class MiscPattern(tree: Tree) extends Pattern {
- // println("Resorted to MiscPattern: %s/%s".format(tree, tree.getClass))
+ log("Resorted to MiscPattern: %s/%s".format(tree, tree.getClass))
+ override def simplify(testVar: Symbol) = tree match {
+ case x: Ident => this.rebindToEqualsCheck()
+ case _ => super.simplify(testVar)
+ }
}
-
object Pattern {
def isDefaultPattern(t: Tree) = cond(unbind(t)) { case EmptyTree | WILD() => true }
def isStar(t: Tree) = cond(unbind(t)) { case Star(q) => isDefaultPattern(q) }
@@ -238,7 +254,7 @@ trait Patterns extends ast.TreeDSL {
// The logic formerly in classifyPat, returns either a simplification
// of this pattern or identity.
def simplify(testVar: Symbol): Pattern = this
- def simplify(): Pattern = simplify(NoSymbol)
+ def simplify(): Pattern = this simplify NoSymbol
def subpatterns(pats: MatchMatrix#Patterns): List[Pattern] = Nil