summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2006-10-28 20:39:01 +0000
committerBurak Emir <emir@epfl.ch>2006-10-28 20:39:01 +0000
commit61723a8f72c7b533fc46c4bd721574c94daa15cc (patch)
tree659b3d4bf9ba04c4d335681c00eec1764ab102c8 /src/compiler
parentd8e8ab6a9ec2550716278c8ddffa03d295531808 (diff)
downloadscala-61723a8f72c7b533fc46c4bd721574c94daa15cc.tar.gz
scala-61723a8f72c7b533fc46c4bd721574c94daa15cc.tar.bz2
scala-61723a8f72c7b533fc46c4bd721574c94daa15cc.zip
support UnApply in pattern matcher.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/matching/CodeFactory.scala5
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala79
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala3
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala4
5 files changed, 29 insertions, 64 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
index e832cc886f..c3d373b731 100644
--- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
+++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
@@ -114,6 +114,11 @@ trait CodeFactory requires transform.ExplicitOuter {
typed(Literal(Constant(i))))
//defs.Seq_length instead of tpe.member ?
+ def Not(arg:Tree) = arg match {
+ case Literal(Constant(true)) => Literal(Constant(false))
+ case Literal(Constant(false)) => Literal(Constant(true))
+ case t => Select(arg, definitions.Boolean_not)
+ }
/*protected*/ def And(left: Tree, right: Tree): Tree = left match {
case Literal(Constant(value: Boolean)) =>
if (value) right else left
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index 72b7fd9d79..62d7247bfb 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -138,18 +138,10 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
}
def pUnapplyPat(pos: PositionType, fn: Tree) = {
- // the type of the "child" of unapply is AnyRef, because want to check
- // against null and in this way, this is done using the isInstanceOf
- // magic. @todo, replace this with null check
- val tpe = definitions.AnyRefClass.tpe
- /* val tpe = fn.tpe match {
- case MethodType(_,TypeRef(_,_,args)) => // pedantic? add if sym==defs.TupleClass(args.length).
- if(args.isEmpty) definitions.UnitClass.tpe else definitions.tupleType(args)
- } */
+ val tpe = definitions.productType(definitions.optionOfProductElems(fn.tpe)) // is subtype of producttype
val node = new UnapplyPat(newVar(pos, tpe), fn)
- //Console.println("!pUnapply sym = "+node.symbol+" tpe "+tpe)
node.pos = pos
- node.setType(definitions.AnyRefClass.tpe)
+ node.setType(tpe)
node
}
@@ -342,14 +334,6 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
tree.body = nb
}
- protected def isUnapply(tree:Tree): Boolean = tree match {
- case Apply(fn, args) if (settings.Xunapply.value && fn.symbol != null && fn.symbol.name == nme.unapply) =>
- //Console.println("isUnapply:"+tree)
- true
- case _ =>
- false
- }
-
/** returns the child patterns of a pattern
*/
protected def patternArgs(tree: Tree): List[Tree] = {
@@ -368,6 +352,9 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
case a @ Apply(_, args) =>
args
+ case a @ UnApply(_, args) =>
+ args
+
case av @ ArrayValue(_, ts) if isRightIgnoring(av) =>
ts.reverse.drop(1).reverse
@@ -417,9 +404,8 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
}
node
- case t @ Apply(fn, args) if isUnapply(t) =>
- //t.setType(definitions.AnyRefClass.tpe) // hack to avoid stupid effects
- pUnapplyPat(tree.pos, fn)
+ case t @ UnApply(fn, args) =>
+ pUnapplyPat(tree.pos, fn)
case t @ Apply(fn, args) => // pattern with args
//Console.println("Apply node: "+t);
@@ -580,16 +566,17 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
} else {
//Console.println("NOT FIRSTPOS");
//Console.println("newHeader :: ");
- /*
+
if(!casted.tpe.symbol.hasFlag(Flags.CASE)) {
- Console.println(" newHeader :: casted="+casted);
+/* Console.println(" newHeader :: casted="+casted);
Console.println(" newHeader :: casted.pos="+casted.pos);
Console.println(" newHeader :: casted.pos==Position.FIRSTPOS"+(casted.pos == Position.FIRSTPOS));
Console.println(" newHeader :: casted.tpe="+casted.tpe);
Console.println(" newHeader :: casted.tpe.symbol="+casted.tpe.symbol);
- throw new Error("internal problem, trying casefield access for no case class") //DBG
+print()
+*/ throw new Error("internal problem, trying casefield access for no case class") //DBG
}
- */
+
val caseAccs = casted.tpe.symbol.caseFieldAccessors;
if (caseAccs.length <= index) System.out.println("selecting " + index + " in case fields of " + casted.tpe.symbol + "=" + casted.tpe.symbol.caseFieldAccessors);//debug
val ts = caseAccs(index);
@@ -637,9 +624,7 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
//assert index >= 0 : casted;
if (index < 0) { Predef.error("error entering:" + casted); return null }
- if(!target.isInstanceOf[UnapplyPat] && !isUnapply(pat)) { // most common case
- //Console.println("Hello 3, target "+target)
- //access the index'th child of a case class
+ //access the index'th child of a case class
curHeader = newHeader(pat.pos, casted, index)
target.and = curHeader; // (*)
@@ -649,34 +634,6 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
curHeader.or = patternNode(pat, curHeader, env)
enter(patArgs, curHeader.or, casted, env)
- } else if(target.isInstanceOf[UnapplyPat]) target match { // parent is unapply
- case UnapplyPat(ncasted, fn) =>
- // do a pHeader for "Some", but skip one for Product
- //Console.println("Hello 2")
- // @todo this erases existing unapply pat children -- if optimizing unapply, need to revisit
- val curHeader = pHeader(pat.pos, ncasted.tpe, Ident(ncasted) setType ncasted.tpe)
- target.and = curHeader
- val pn = patternNode(pat, curHeader, env)
- //Console.println("ncasted.tpe "+ncasted.tpe)
- //Console.println("pn ="+pn)
- curHeader.or = pn
- //Console.println("patArgs = "+patArgs)
- //Console.println("curHeader = "+curHeader)
- //Console.println("curHeader.or = "+curHeader.or)
- //Console.println("pn.sym = "+pn.symbol)
- enter(patArgs, curHeader.or, pn.symbol, env)
- } else pat match { // isUnapply(pat) holds;
- case Apply(fn,args) => // load the result of fn(casted)
- Console.println("Hello 1")
- val ident = Ident(casted)
- curHeader = pHeader( pat.pos, definitions.AnyRefClass.tpe, Apply(fn,List(ident)))
- target.and = curHeader
- //test
- curHeader.or = patternNode(pat, curHeader, env)
- //Console.println("have to add a header and casted is "+casted+" casted.tpe is "+casted.tpe) // DBG ;
- enter(patArgs, curHeader.or, casted, env)
- }
-
} else {
//Console.println(" enter: using old header for casted = "+casted) // DBG
// find most recent header
@@ -1200,9 +1157,13 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
case DefaultPat() =>
return toTree(node.and);
- case UnapplyPat(casted,fn) =>
- return Or(Block(List(ValDef(casted, Apply(fn,List(selector)))), toTree(node.and)),
- toTree(node.or, selector.duplicate))
+ case UnapplyPat(casted,fn @ Apply(fn1, _)) =>
+ val v = newVar(fn.pos, fn.tpe)
+ Or(squeezedBlock(
+ List(ValDef(v,Apply(fn1,List(selector)))),
+ And(Not(Select(Ident(v), nme.isEmpty)),
+ squeezedBlock(List(ValDef(casted, Select(Ident(v),"get"))),toTree(node.and)))),
+ toTree(node.or, selector.duplicate))
case ConstrPat(casted) =>
def outerAlwaysEqual(left: Type, right: Type) = Pair(left,right) match {
case Pair(TypeRef(lprefix, _,_), TypeRef(rprefix,_,_)) if lprefix =:= rprefix =>
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index 7f6abff21a..65a9ed1709 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -193,7 +193,8 @@ trait PatternNodes requires transform.ExplicitOuter {
sb.append(indent).append("NULL")
else
patNode match {
-
+ case UnapplyPat(_,fn) =>
+ sb.append(indent + "UNAPPLY(" + fn + ")").append('\n')
case _h: Header =>
val selector = _h.selector
val next = _h.next
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index e42ba067fb..1ab16f0203 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -188,7 +188,7 @@ with PatternMatchers */ {
isReg = true // cause there are ArrayValues now
copy.Sequence(pat, trees map { isRegular1 })
- //case ArrayValue( tt, List(b @ Bind(id, Star(wc @ Ident(nme.WILDCARD))))) =>
+ case UnApply(fn, args) => copy.UnApply(pat, fn, args map { isRegular1 })
// a pattern of the form List(foo@_*)
case app @ Apply(fn, List(pat2@ ArrayValue( tt, List(b @ Bind(id, Star(wc @ Ident(nme.WILDCARD))))))) if isSeqApply(app) =>
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index e8c55d383e..da4375fbe6 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -362,9 +362,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
mainTransform(new TreeSubstituter(vparams map (.symbol), args).transform(body))
}
- case Apply(fn0, List(t @ Apply(fn1, List(u @ Apply(fn2, args))))) if inPattern && settings.Xunapply.value && definitions.isProductType(u.tpe) =>
- // leave unapply trees in patterns alone
- copy.Apply(tree, fn0, List(copy.Apply(t, fn1, List(copy.Apply(u, fn2, transformTrees(args))))))
+ case UnApply(fn, args) => copy.UnApply(tree, fn, transformTrees(args))
case Apply(fn, args) =>
if (settings.noassertions.value &&