From 6ac3bdaf7ff56b6234508087f6927b689acd5e2c Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 3 Oct 2009 04:43:31 +0000 Subject: 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. --- .../tools/nsc/matching/ParallelMatching.scala | 82 +++++----------------- .../scala/tools/nsc/matching/PatternBindings.scala | 6 ++ .../scala/tools/nsc/matching/PatternNodes.scala | 5 -- .../scala/tools/nsc/matching/Patterns.scala | 36 +++++++--- 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 -- cgit v1.2.3