diff options
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 |