summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2007-09-14 13:05:38 +0000
committerBurak Emir <emir@epfl.ch>2007-09-14 13:05:38 +0000
commitee3213739c3a53cbfe363e03af5c0b4e347b8b91 (patch)
treedc718d172cd9513026b36f5aee50e3d56aa0861c
parent9f996ddaf6ecda1ba270041a7c70a70121510647 (diff)
downloadscala-ee3213739c3a53cbfe363e03af5c0b4e347b8b91.tar.gz
scala-ee3213739c3a53cbfe363e03af5c0b4e347b8b91.tar.bz2
scala-ee3213739c3a53cbfe363e03af5c0b4e347b8b91.zip
enabled MixSequence rule for sequence patterns ...
enabled MixSequence rule for sequence patterns without _*
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala115
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala4
2 files changed, 63 insertions, 56 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index ad43caad4a..4154aff430 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -80,13 +80,12 @@ trait ParallelMatching {
//DBG(rest.toString)
//DBG(")///")
*/
- if(isEqualsPattern(column.head.tpe)) { //DBG("\n%%% MixEquals");
+ if(isEqualsPattern(column.head.tpe)) { DBG("\n%%% MixEquals");
return new MixEquals(scrutinee, column, rest)
}
// the next condition is never true, @see isImplemented/CantHandleSeq
- if(column.head.isInstanceOf[ArrayValue]) { //DBG("\n%%% MixSequence");
- throw new FatalError("not implemented yet");
- //return new MixSequence(scrutinee, column, rest)
+ if(column.head.isInstanceOf[ArrayValue]) { DBG("\n%%% MixSequence");
+ return new MixSequence(scrutinee, column, rest)
}
if(isSimpleSwitch) { //DBG("\n%%% MixLiterals")
return new MixLiterals(scrutinee, column, rest)
@@ -94,17 +93,17 @@ trait ParallelMatching {
if(settings_casetags && (column.length > 1) && isFlatCases(column)) {
//DBG("flat cases!"+column+"\n"+scrutinee.tpe.typeSymbol.children+"\n"+scrutinee.tpe.member(nme.tag))
- //DBG("\n%%% MixCases")
+ DBG("\n%%% MixCases")
return new MixCases(scrutinee, column, rest)
// if(scrutinee.tpe./*?type?*/symbol.hasFlag(symtab.Flags.SEALED)) new MixCasesSealed(scrutinee, column, rest)
// else new MixCases(scrutinee, column, rest)
}
//Console.println("isUnapplyHead = "+isUnapplyHead())
- if(isUnapplyHead()) { //DBG("\n%%% MixUnapply")
+ if(isUnapplyHead()) { DBG("\n%%% MixUnapply")
return new MixUnapply(scrutinee, column, rest)
}
- //DBG("\n%%% MixTypes")
+ DBG("\n%%% MixTypes")
return new MixTypes(scrutinee, column, rest) // todo: handle type tests in unapply
} /* def MixtureRule(scrutinee:Symbol, column:List[Tree], rest:Rep): RuleApplication */
@@ -512,12 +511,21 @@ trait ParallelMatching {
} /* def tree(implicit theOwner: Symbol, failTree: Tree) */
} /* MixUnapply */
- /** handle sequence pattern and ArrayValue
- class MixSequence(val scrutinee:Symbol, val column:List[Tree], val rest:Rep) extends RuleApplication {
+ /** handle sequence pattern and ArrayValue (but not star patterns)
+ */
+ class MixSequence(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends RuleApplication(rep) {
+
+ final def getSubPatterns(len:Int, x:Tree) = x match {
+ case ArrayValue(_,xs) if xs.length == len => Some(xs)
+ case EmptyTree | Ident(nme.WILDCARD) => Some(getDummies(len))
+ case _ => None
+ }
+
// context (to be used in IF), success and failure Rep
final def getTransition(implicit theOwner: Symbol): (Tree => Tree => Tree, Rep, Rep) = {
assert(isSubType(scrutinee.tpe, column.head.tpe), "problem "+scrutinee.tpe+" not <: "+column.head.tpe)
+ assert(!isRightIgnoring(column.head.asInstanceOf[ArrayValue]), "is RI!")
val treeAsSeq =
if(!isSubType(scrutinee.tpe, column.head.tpe))
@@ -525,8 +533,6 @@ trait ParallelMatching {
else
mkIdent(scrutinee)
- val failRep = repWithoutHead(column,rest)
-
column.head match {
case av @ ArrayValue(_, xs) =>
@@ -535,25 +541,45 @@ trait ParallelMatching {
var vs = new ListBuffer[Symbol]
var ix = 0
+ //build new temps on which we will match subpatterns
+
// if is right ignoring, don't want last one
var ys = if(isRightIgnoring(av)) xs.take(xs.length-1) else xs; while(ys ne Nil) {
- val p = ys.head
+ val p = strip2(ys.head)
childpats += p
- val temp = newVar(p.pos, p.tpe)
- Console.println("new temp:"+temp+":"+temp.tpe)
- Console.println("seqelem:"+seqElement(treeAsSeq.duplicate, ix))
+ val temp = newVar(p.pos, getElemType_Sequence(scrutinee.tpe))
+ 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 childpatList = childpats.toList
- val nrows = rest.row.map {
- case Row(pats,subst,g,b) => Row(childpatList ::: pats,subst,g,b)
+ //bindings += typedValDef(temp, seqElement(treeAsSeq.duplicate, ix))
+
+
+ val nrows = new ListBuffer[Row]
+ val frows = new ListBuffer[Row]
+ //val childpatList = childpats.toList
+ var cs = column; var rw = rest.row; while (cs ne Nil) {
+ assert(!cs.head.isInstanceOf[ArrayValue] || !isRightIgnoring(cs.head.asInstanceOf[ArrayValue]), "is RI!!")
+ (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))
+ frows += Row( cs.head :: pats, subst, g, b)
+ case ( None , Row(pats,subst,g,b) ) =>
+ frows += Row( cs.head :: pats, subst, g, b)
+ }
+ cs = cs.tail
+ rw = rw.tail
}
- val succRep = rep.make( vs.toList ::: rest.temp, nrows)
+ val succRep = rep.make( vs.toList ::: rest.temp, nrows.toList)
+
+ val failRep = rep.make( scrutinee :: rest.temp, frows.toList)
+
+ /*
if(isRightIgnoring(av)) { // contains a _* at the end
val minlen = xs.length-1;
@@ -568,12 +594,12 @@ trait ParallelMatching {
If(cond, squeezedBlock(bindings.toList, thenp), elsep)
}}, succRep, failRep)
}
-
+ */
// fixed length
val cond = seqHasLength(treeAsSeq.duplicate, column.head.tpe, xs.length)
- return ({thenp:Tree => {elsep:Tree => If(cond, thenp, elsep)}}, succRep, failRep)
+ return ({thenp:Tree => {elsep:Tree => squeezedBlock(bindings.toList,If(cond, thenp, elsep))}}, succRep, failRep)
}
- }
+ }
final def tree(implicit theOwner: Symbol, failTree: Tree) = {
val (cx,srep,frep) = this.getTransition
@@ -581,9 +607,9 @@ trait ParallelMatching {
val fail = repToTree(frep)
cx(succ)(fail)
}
-
}
- */
+
+
// @todo: equals test for same constant
class MixEquals(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends RuleApplication(rep) {
/** condition (to be used in IF), success and failure Rep */
@@ -720,7 +746,7 @@ trait ParallelMatching {
//Console.println("[2")
(EmptyTree::ms, (j,dummies)::ss, rs); // matching an object
- case Typed(/*p @ __UnApply(_,_,_)*/ p, _) if (strip2(p).isInstanceOf[UnApply] && (patternType /*is never <equals>*/ <:< headPatternType)) =>
+ case Typed(p, _) if (strip2(p).isInstanceOf[UnApply] && (patternType /*is never <equals>*/ <:< headPatternType)) =>
//Console.println("unapply arg is same or *more* specific")
(p::ms, (j, dummies)::ss, rs);
@@ -1068,19 +1094,11 @@ trait ParallelMatching {
var indexOfAlternative = -1
var j = 0; while(opats ne Nil) {
var opat = opats.head // original pattern
- DBG("opat = "+opat)
+ //DBG("opat = "+opat)
val (vars,strippedPat) = strip(opat)
val vs = vars.toList
- def handle(prepat:Tree): Unit = prepat match {
-
- /* annotations do not make sense on pattern
- case Typed(p, tpt) if prepat.tpe.isInstanceOf[AnnotatedType] =>
- Console.println("HELLO")
- Console.println("p ="+p)
- Console.println("p.tpe ="+p.tpe)
- opat = makeBind(vs,p)
- handle(p)
- */
+ (strippedPat: @unchecked) match {
+
case p @ Alternative(ps) =>
if(indexOfAlternative == -1) {
unchanged = false
@@ -1095,16 +1113,6 @@ trait ParallelMatching {
pats = opat :: pats
case o @ Ident(n) => // n != nme.WILDCARD
- /*
- Console.println("/'''''''''''' 1"+o.tpe)
- Console.println("/'''''''''''' 2"+o.symbol)
- Console.println("/'''''''''''' 3"+o.symbol.tpe)
- Console.println("/'''''''''''' 4"+o.symbol.tpe.prefix)
- Console.println("/'''''''''''' 5"+o.symbol.tpe.prefix.isStable)
-
- Console.println("/'''''''''''' 6"+(o.symbol.tpe.typeSymbol hasFlag (Flags.CASE)))
- Console.println("/'''''''''''' 7"+(o.symbol.tpe.termSymbol.hasFlag (Flags.CASE)))
- */
val tpe =
if (!o.symbol.isValue) {
singleType(o.tpe.prefix, o.symbol)
@@ -1145,8 +1153,8 @@ trait ParallelMatching {
val nmlzdPat = normalizedListPattern(xs, tptArg.tpe)
pats = makeBind(vs, nmlzdPat) :: pats
- //case /* ua @ */ __UnApply(_,argtpe,_) =>
- // val ua = prepat
+ //case ua @ __UnApply(_,argtpe,_) =>
+ //val ua = prepat
// val npat = (if (temp(j).tpe <:< argtpe) ua else Typed(ua,TypeTree(argtpe)).setType(argtpe))
// pats = (makeBind(vs, npat) setType argtpe)::pats
@@ -1158,8 +1166,7 @@ trait ParallelMatching {
pats = (makeBind(vs, npat) setType argtpe)::pats
}
- /** something too tricky is going on if the outer types don't match
- */
+ // something too tricky is going on if the outer types don't match
case o @ Apply(fn, List()) if !isCaseClass(o.tpe) =>
//DBG("o.tpe "+o.tpe)
//DBG("fn is ")
@@ -1218,11 +1225,11 @@ trait ParallelMatching {
pats = opat :: pats
case ArrayValue(_,xs) =>
- assert(false) // inactive, @see PatternMatchers::isImplemented
+ //assert(false) // inactive, @see PatternMatchers::isImplemented
+ pats = opat :: pats
}
- handle(strippedPat)
- DBG("!!added "+pats.head+":"+pats.head.tpe)
+ //DBG("!!added "+pats.head+":"+pats.head.tpe)
opats = opats.tail
j += 1
}
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index 3a5868369f..cda17044c7 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -257,7 +257,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
//Console.println(app.symbol)
//Console.println(fn.symbol)
if(!xs.isEmpty) {
- assert(false)
+ assert(false, "this never happens")
return CantHandleApply // this should never happen
}
null
@@ -287,7 +287,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
case p:Typed => null // if(guard eq EmptyTree) null else CantHandleGuard
// ArrayValue nodes can also appear in repeated parameter positions of case classes (e.g. xml.Elem)
- case ArrayValue(_,xs) => CantHandleSeq
+ case av @ ArrayValue(_,xs) => if(isRightIgnoring(av)) CantHandleSeq else isImplemented(xs,guard)
//@todo
//case av @ ArrayValue(_,xs) =>