diff options
author | Burak Emir <emir@epfl.ch> | 2006-10-28 20:39:01 +0000 |
---|---|---|
committer | Burak Emir <emir@epfl.ch> | 2006-10-28 20:39:01 +0000 |
commit | 61723a8f72c7b533fc46c4bd721574c94daa15cc (patch) | |
tree | 659b3d4bf9ba04c4d335681c00eec1764ab102c8 /src/compiler | |
parent | d8e8ab6a9ec2550716278c8ddffa03d295531808 (diff) | |
download | scala-61723a8f72c7b533fc46c4bd721574c94daa15cc.tar.gz scala-61723a8f72c7b533fc46c4bd721574c94daa15cc.tar.bz2 scala-61723a8f72c7b533fc46c4bd721574c94daa15cc.zip |
support UnApply in pattern matcher.
Diffstat (limited to 'src/compiler')
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 && |