From fbccd6a31839eb0e1f7f67e7c0cc35771226a6e5 Mon Sep 17 00:00:00 2001 From: Burak Emir Date: Wed, 9 May 2007 13:05:23 +0000 Subject: bug contributions fixed 460 461 --- .../tools/nsc/matching/ParallelMatching.scala | 165 ++++++++++++--------- .../scala/tools/nsc/matching/PatternMatchers.scala | 6 +- 2 files changed, 97 insertions(+), 74 deletions(-) diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 8af380d447..dc0c31c010 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -18,6 +18,7 @@ trait ParallelMatching { import global._ //final def DEBUG(x:String) = {if (settings.debug.value) Console.println(x)} + //final def DEBUG(x:String) = {Console.println(x)} // ---------------------------------- data sealed trait RuleApplication @@ -178,6 +179,7 @@ trait ParallelMatching { } def repToTree(rep:Rep, typed:Tree => Tree, handleOuter: Tree => Tree)(implicit theOwner: Symbol, failTree: Tree, bodies: collection.mutable.Map[Tree,(Tree,Tree, Symbol)]): Tree = { + //Console.println("repToTree") rep.applyRule match { case VariableRule(subst, EmptyTree, b) => bodies.get(b) match { case Some(EmptyTree, b, theLabel) => @@ -277,46 +279,63 @@ trait ParallelMatching { } } - def makeRep(temp:List[Symbol], row1:List[(List[Tree], List[(Symbol,Symbol)], Tree, Tree)]/*, exCh:List[Boolean]*/): Rep = { - var i = -1 - val row = row1 flatMap { - xx => - def isAlternative(p: Tree): Boolean = p match { - case Bind(_,p) => isAlternative(p) - case Alternative(ps) => true - case _ => false - } - def getAlternativeBranches(p:Tree): List[Tree] = { - def get_BIND(pctx:Tree => Tree, p:Tree):List[Tree] = p match { - case b @ Bind(n,p) => get_BIND({ x:Tree => pctx(copy.Bind(b, n, x) setType x.tpe) }, p) - case Alternative(ps) => ps map pctx - } - get_BIND({x=>x}, p) - } - val (pats,subst,g,b) = xx - i = pats findIndexOf isAlternative - if(i == -1) - List((pats,subst,g,b)) - else { - val prefix:List[Tree] = pats.take(i) - val alts = getAlternativeBranches(pats(i)) - val suffix:List[Tree] = pats.drop(i+1) - alts map { p => (prefix ::: p :: suffix, subst, g, b) } - } +object Rep { + type RepType = Product2[List[Symbol], List[(List[Tree], List[(Symbol,Symbol)], Tree, Tree)]] + def unapply(x:Rep):Option[RepType] = + if(x.isInstanceOf[RepImpl]) Some(x.asInstanceOf[RepImpl]) else None + + private + case class RepImpl(val temp:List[Symbol], val row:List[(List[Tree], List[(Symbol,Symbol)], Tree, Tree)]) extends Rep with RepType { + assert(row.forall { case (pats,subst,g,b) => temp.length == pats.length }); + def _1 = temp + def _2 = row + } + + /** the injection here handles alternatives */ + def apply(temp:List[Symbol], row1:List[(List[Tree], List[(Symbol,Symbol)], Tree, Tree)]): Rep = { + var i = -1 + val row = row1 flatMap { + xx => + def isAlternative(p: Tree): Boolean = p match { + case Bind(_,p) => isAlternative(p) + case Alternative(ps) => true + case _ => false + } + def getAlternativeBranches(p:Tree): List[Tree] = { + def get_BIND(pctx:Tree => Tree, p:Tree):List[Tree] = p match { + case b @ Bind(n,p) => get_BIND({ x:Tree => pctx(copy.Bind(b, n, x) setType x.tpe) }, p) + case Alternative(ps) => ps map pctx + } + get_BIND({x=>x}, p) } + val (pats,subst,g,b) = xx + i = pats findIndexOf isAlternative if(i == -1) - Rep(temp,row/*,ex*/) - else - makeRep(temp,row/*,ex*/) + List((pats,subst,g,b)) + else { + val prefix:List[Tree] = pats.take(i) + val alts = getAlternativeBranches(pats(i)) + val suffix:List[Tree] = pats.drop(i+1) + alts map { p => (prefix ::: p :: suffix, subst, g, b) } + } } + if(i == -1) + RepImpl(temp,row).init + else + Rep(temp,row) // recursive call + } +} - case class Rep(val temp:List[Symbol], val row:List[(List[Tree], List[(Symbol,Symbol)], Tree, Tree)]/*, val exhaustivenessChecked:List[Boolean]*/) { - assert(row.forall { case (pats,subst,g,b) => temp.length == pats.length }) + abstract class Rep { + val temp:List[Symbol] + val row:List[(List[Tree], List[(Symbol,Symbol)], Tree, Tree)] var sealedCols = List[Int]() var sealedComb = List[Set[Symbol]]() //Console.println(" the matrix "+this.toString) - temp.zipWithIndex.foreach { + + def init: this.type = { + temp.zipWithIndex.foreach { case (sym,i) => //Console.println("sym! "+sym+" mutable? "+sym.hasFlag(symtab.Flags.MUTABLE)+" captured? "+sym.hasFlag(symtab.Flags.CAPTURED)) if (sym.hasFlag(symtab.Flags.MUTABLE) && // indicates that have not yet checked exhaustivity @@ -340,48 +359,52 @@ trait ParallelMatching { sealedComb = cases::sealedComb } } - } - // computes cartesian product, keeps indices available - def combine(colcom: List[(Int,Set[Symbol])]): List[List[(Int,Symbol)]] = colcom match { - case Nil => Nil - case (i,syms)::Nil => syms.toList.map { sym => List((i,sym)) } - case (i,syms)::cs => for (s <- syms.toList; rest <- combine(cs)) yield (i,s) :: rest - } + } - if(!sealedCols.isEmpty) { - //DEBUG("cols"+sealedCols) - //DEBUG("comb") - //for (com <- sealedComb) DEBUG(com.toString) - - val allcomb = combine(sealedCols zip sealedComb) - //Console.println("all comb!" + allcomb) - /** returns true if pattern vector pats covers a type symbols "combination" - * @param pats pattern vector - * @param comb pairs of (column index, type symbol) - */ - def covers(pats: List[Tree], comb:List[(Int,Symbol)]) = { - comb forall { case (i,sym) => val p = pats(i); p.tpe.symbol == sym || sym.tpe <:< p.tpe } + // computes cartesian product, keeps indices available + def combine(colcom: List[(Int,Set[Symbol])]): List[List[(Int,Symbol)]] = colcom match { + case Nil => Nil + case (i,syms)::Nil => syms.toList.map { sym => List((i,sym)) } + case (i,syms)::cs => for (s <- syms.toList; rest <- combine(cs)) yield (i,s) :: rest } - val coversAll = allcomb forall { combination => row exists { r => covers(r._1, combination)}} - //Console.println("all combinations covered? "+coversAll) - if(!coversAll) { - val sb = new StringBuilder() - sb.append("match is not exhaustive!\n") - for (open <- allcomb if !(row exists { r => covers(r._1, open)})) { - sb.append("missing combination ") - val NPAD = 15 - def pad(s:String) = { Iterator.range(1,NPAD - s.length).foreach { x => sb.append(" ") }; sb.append(s) } - List.range(0, temp.length) foreach { - i => open.find { case (j,sym) => j==i } match { - case None => pad("*") - case Some((_,sym)) => pad(sym.name.toString) - } + + if(!sealedCols.isEmpty) { + //DEBUG("cols"+sealedCols) + //DEBUG("comb") + //for (com <- sealedComb) DEBUG(com.toString) + + val allcomb = combine(sealedCols zip sealedComb) + //Console.println("all comb!" + allcomb) + /** returns true if pattern vector pats covers a type symbols "combination" + * @param pats pattern vector + * @param comb pairs of (column index, type symbol) + */ + def covers(pats: List[Tree], comb:List[(Int,Symbol)]) = { + comb forall { case (i,sym) => val p = pats(i); p.tpe.symbol == sym || sym.tpe <:< p.tpe } + } + val coversAll = allcomb forall { combination => row exists { r => covers(r._1, combination)}} + //Console.println("all combinations covered? "+coversAll) + if(!coversAll) { + val sb = new StringBuilder() + sb.append("match is not exhaustive!\n") + for (open <- allcomb if !(row exists { r => covers(r._1, open)})) { + sb.append("missing combination ") + val NPAD = 15 + def pad(s:String) = { Iterator.range(1,NPAD - s.length).foreach { x => sb.append(" ") }; sb.append(s) } + List.range(0, temp.length) foreach { + i => open.find { case (j,sym) => j==i } match { + case None => pad("*") + case Some((_,sym)) => pad(sym.name.toString) } - sb.append('\n') } - cunit.warning(temp.head.pos, sb.toString) + sb.append('\n') + } + cunit.warning(temp.head.pos, sb.toString) + } } - } + return this + } // end init + // if this was the *fail* branch, the Rep preceding this Rep var mixtureParent: MixtureRule = null @@ -408,7 +431,7 @@ trait ParallelMatching { val restTemp = temp.take(i) ::: temp.drop(i+1) val restRows = row map { case (pats,subst,g,b) => (pats.take(i) ::: pats.drop(i+1),subst,g,b) } //val restEx = exhaustivenessChecked.take(i) ::: exhaustivenessChecked.drop(i+1) - MixtureRule(temp(i), column, makeRep(restTemp,restRows/*,restEx*/)) setParent this + MixtureRule(temp(i), column, Rep(restTemp,restRows/*,restEx*/)) setParent this } } // a fancy toString method for debugging @@ -434,7 +457,7 @@ trait ParallelMatching { if(!checkExhaustive) root.setFlag(symtab.Flags.CAPTURED) val row = cases map { case CaseDef(pat,g,b) => (List(pat),List(),g,b) } - makeRep(List(root), row) + Rep(List(root), row) } /** this tree node is used several times in the parallel algo and will never be needed for matching, so it is reused */ val Ident_WILDCARD = Ident(nme.WILDCARD) setType definitions.AnyClass.tpe diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala index 409b939ad8..f2a7c15545 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala @@ -166,9 +166,9 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes with P if(i != -1) { val CaseDef(_,_,b) = cases(i) //DEBUG("*** damn, unreachable!") - //for (b <- bodies) { + //Console.println("damn, unreachable!") + //for (b <- bodies) // Console.println(b) - //} cunit.error(b.pos, "unreachable code") } @@ -245,7 +245,7 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes with P protected def updateBody(tree: Body, bound: Array[ValDef], guard: Tree, body: Tree): Unit = if (tree.guard(tree.guard.length - 1) == EmptyTree) { - cunit.error(body.pos, "unreachable code") + cunit.error(body.pos, "B unreachable code") } else { val bd = new Array[Array[ValDef]](tree.bound.length + 1) val ng = new Array[Tree](tree.guard.length + 1) -- cgit v1.2.3