diff options
author | Burak Emir <emir@epfl.ch> | 2007-09-16 02:39:52 +0000 |
---|---|---|
committer | Burak Emir <emir@epfl.ch> | 2007-09-16 02:39:52 +0000 |
commit | 0b2f65aa6c6b3bb3e7628720893fb8116fdc8f71 (patch) | |
tree | 8ddae77b1334a6e4b80c47e3c58d650217fa80c1 /src | |
parent | 4c74083c14c959370dd69dd6a745f56354143998 (diff) | |
download | scala-0b2f65aa6c6b3bb3e7628720893fb8116fdc8f71.tar.gz scala-0b2f65aa6c6b3bb3e7628720893fb8116fdc8f71.tar.bz2 scala-0b2f65aa6c6b3bb3e7628720893fb8116fdc8f71.zip |
fixed seq matching bug + reorganized test cases
Diffstat (limited to 'src')
3 files changed, 43 insertions, 22 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 06b9077168..5c0e05ebfc 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -75,11 +75,7 @@ trait ParallelMatching { false } } - /* - //DBG("/// MixtureRule("+scrutinee.name+":"+scrutinee.tpe+","+column+", rep = ") - //DBG(rest.toString) - //DBG(")///") - */ + if(isEqualsPattern(column.head.tpe)) { DBG("\n%%% MixEquals"); return new MixEquals(scrutinee, column, rest) } @@ -527,13 +523,23 @@ trait ParallelMatching { protected def getSubPatterns(len:Int, x:Tree):Option[List[Tree]] = x match { case av @ ArrayValue(_,xs) if (!isRightIgnoring(av) && xs.length == len) => Some(xs ::: List(EmptyTree)) - case av @ ArrayValue(_,xs) if ( isRightIgnoring(av) && xs.length == len+1) => Some(removeStar(xs)) + case av @ ArrayValue(_,xs) if ( isRightIgnoring(av) && xs.length == len+1) => Some(removeStar(xs)) // (*) case EmptyTree | Ident(nme.WILDCARD) => Some(getDummies(len+1)) case _ => None } + protected def makeSuccRep(vs:List[Symbol], tail:Symbol, nrows:List[Row])(implicit theOwner: Symbol) = + rep.make( vs ::: tail :: rest.temp, nrows.toList) + + /** returns true if x is more general than y */ + protected def subsumes(x:Tree, y:Tree): Boolean = (x,y) match { + case (av @ ArrayValue(_,xs), bv @ ArrayValue(_,ys)) => + isRightIgnoring(av) && !isRightIgnoring(bv) && xs.length == ys.length+1 // (*) + case _ => + false + } // context (to be used in IF), success and failure Rep - final def getTransition(implicit theOwner: Symbol): (Tree => Tree => Tree, Rep, Rep) = { + def getTransition(implicit theOwner: Symbol): (Tree => Tree => Tree, Rep, Rep) = { assert(isSubType(scrutinee.tpe, column.head.tpe), "problem "+scrutinee.tpe+" not <: "+column.head.tpe) @@ -558,15 +564,15 @@ trait ParallelMatching { val p = strip2(ys.head) childpats += p val temp = newVar(p.pos, elementType) - DBG("new temp:"+temp+":"+temp.tpe) - DBG("seqelem:"+seqElement(treeAsSeq.duplicate, ix)) + //DBG("new temp:"+temp+":"+temp.tpe) + //DBG("seqelem:"+seqElement(treeAsSeq.duplicate, ix)) vs += temp bindings += typedValDef(temp, seqElement(treeAsSeq.duplicate, ix)) ix += 1 ys = ys.tail } val tail = newVar(scrutinee.pos, sequenceType) - bindings += typedValDef(tail, {if(ix-1>0) seqDrop(treeAsSeq.duplicate, ix-1) else mkIdent(scrutinee)}) + bindings += typedValDef(tail, {if(ix-1>0) seqDrop(treeAsSeq.duplicate, ix) else mkIdent(scrutinee)}) val nrows = new ListBuffer[Row] @@ -576,7 +582,7 @@ trait ParallelMatching { (getSubPatterns(ix, cs.head),rw.head) match { case (Some(ps), Row(pats,subst,g,b)) => nrows += Row( ps ::: pats, subst, g, b) - if(isDefaultPattern(cs.head)) + if(isDefaultPattern(cs.head) || subsumes(cs.head, av)) frows += Row( cs.head :: pats, subst, g, b) case ( None , Row(pats,subst,g,b) ) => frows += Row( cs.head :: pats, subst, g, b) @@ -585,7 +591,7 @@ trait ParallelMatching { rw = rw.tail } - val succRep = rep.make( vs.toList ::: tail :: rest.temp, nrows.toList) + val succRep = makeSuccRep(vs.toList, tail, nrows.toList) val failRep = rep.make( scrutinee :: rest.temp, frows.toList) @@ -616,6 +622,8 @@ trait ParallelMatching { final def tree(implicit theOwner: Symbol, failTree: Tree) = { val (cx,srep,frep) = this.getTransition + //DBG("MSSf:"+srep.toString) + //DBG("MSSs:"+frep.toString) val succ = repToTree(srep) val fail = repToTree(frep) cx(succ)(fail) @@ -626,14 +634,25 @@ trait ParallelMatching { final class MixSequenceStar(scrutinee:Symbol, column:List[Tree], rest:Rep)(implicit rep:RepFactory) extends MixSequence(scrutinee,column,rest) { // in principle, we could optimize more, but variable binding gets complicated (@todo use finite state methods instead) override def getSubPatterns(minlen:Int, x:Tree) = x match { - case av @ ArrayValue(_,xs) if (!isRightIgnoring(av) && xs.length == minlen) => Some(xs ::: List(EmptyTree)) - case av @ ArrayValue(_,xs) if ( isRightIgnoring(av) && xs.length-1 == minlen) => Some(removeStar(xs)) - case EmptyTree | Ident(nme.WILDCARD) => Some(getDummies(minlen+1)) - case _ => None + case av @ ArrayValue(_,xs) if (!isRightIgnoring(av) && xs.length == minlen) => // Seq(p1,...,pN) + Some(xs ::: gen.mkAttributedRef(definitions.NilModule) :: EmptyTree :: Nil) + case av @ ArrayValue(_,xs) if ( isRightIgnoring(av) && xs.length-1 == minlen) => // Seq(p1,...,pN,_*) + Some( removeStar(xs) ::: EmptyTree :: Nil) + case av @ ArrayValue(_,xs) if ( isRightIgnoring(av) && xs.length-1 < minlen) => // Seq(p1..,pJ,_*) J < N + Some( getDummies(minlen + 1) ::: x :: Nil) + case EmptyTree | Ident(nme.WILDCARD) => + Some( getDummies(minlen + 1 + 1)) + case _ => + None + } + + override protected def makeSuccRep(vs:List[Symbol], tail:Symbol, nrows:List[Row])(implicit theOwner: Symbol) = + rep.make( vs ::: tail :: scrutinee :: rest.temp, nrows) + // lengthArg is minimal length - protected override def getCond(tree:Tree, lengthArg:Int) = seqLongerThan(tree.duplicate, column.head.tpe, lengthArg - 1) + override protected def getCond(tree:Tree, lengthArg:Int) = seqLongerThan(tree.duplicate, column.head.tpe, lengthArg - 1) } @@ -1027,7 +1046,7 @@ trait ParallelMatching { //Console.println(jumpT) return jump } - DBG("requestbody("+bx+", "+subst+") isReached(bx)?"+isReached(bx)+" labels:"); + //DBG("requestbody("+bx+", "+subst+") isReached(bx)?"+isReached(bx)+" labels:"); //{for(s<-labels) Console.print({if(s ne null) {s} else "_"}+",")} //DBG("vss(bx) = "+vss(bx)) if(!isReached(bx)) { // first time this bx is requested diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala index 60b9183b74..780cc46b8c 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala @@ -18,6 +18,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par import typer.typed import symtab.Flags +/* abstract class CantHandle // extends Exception object CantHandleSeq extends CantHandle object CantHandleUnapply extends CantHandle @@ -27,7 +28,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par object CantHandleGuard extends CantHandle object CantOptimize extends CantHandle //object CantHandleLiteral extends Exception - +*/ var nPatterns = 0 var nParallel = 0 @@ -121,6 +122,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par var dfatree: Tree = null /** enters a sequence of cases into the pattern matcher */ +/* def construct(cases: List[Tree]): Unit = { nPatterns = nPatterns + 1 @@ -171,7 +173,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par constructIncremental(cases) } - +*/ def constructParallel(cases: List[Tree]): Any = { //var cases1 = cases; while(cases1 ne Nil) { // val c = cases1.head.asInstanceOf[CaseDef] @@ -216,7 +218,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par // return e // fallback //non-fallback: - case e: CantHandle => rep.cleanup(); return e + //case e: CantHandle => rep.cleanup(); return e case e => e.printStackTrace(); throw new FatalError(e.getMessage()) } } diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala index 29c156a537..8d099455a6 100644 --- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala +++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala @@ -240,7 +240,7 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with CodeFa } else { val pm = new PatternMatcher() pm.initialize(sel, doCheckExhaustive, owner, handleOuter) - pm.construct(cases) + pm.constructParallel(cases) //if (global.log()) { // global.log("internal pattern matching structure"); // pm.print(); |