diff options
author | Burak Emir <emir@epfl.ch> | 2007-07-06 10:07:15 +0000 |
---|---|---|
committer | Burak Emir <emir@epfl.ch> | 2007-07-06 10:07:15 +0000 |
commit | 16e1b57be1b05c460bbce0de51e607ae6b1b9027 (patch) | |
tree | a34641b84da4ad568221f9aaeec869eeff105ce6 | |
parent | 0cd9d0935523dc7176d2b3bfab3ca7e46aa99af0 (diff) | |
download | scala-16e1b57be1b05c460bbce0de51e607ae6b1b9027.tar.gz scala-16e1b57be1b05c460bbce0de51e607ae6b1b9027.tar.bz2 scala-16e1b57be1b05c460bbce0de51e607ae6b1b9027.zip |
optimzing unapply calls returning Some[T], savi...
optimzing unapply calls returning Some[T], saving emptynessCheck fix of
#999 (better late than never), added test case to run/unapply.scala
4 files changed, 46 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala index 7b8813db3e..d54d4e95bd 100644 --- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala +++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala @@ -82,6 +82,13 @@ trait CodeFactory { result } + def emptynessCheck(vsym: Symbol) = { + if(vsym.tpe.symbol == definitions.SomeClass) // is Some[_] + Literal(Constant(true)) + else // is Option[_] + Not(Select(Ident(vsym), nme.isEmpty)) + } + def makeIf(cond:Tree, thenp:Tree, elsep:Tree) = cond match { case Literal(Constant(true)) => thenp case Literal(Constant(false)) => elsep diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 67e66d6649..e44f06b484 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -38,7 +38,7 @@ trait ParallelMatching { def isUnapply(x:Tree): Boolean = x match { case Bind(_,p) => isUnapply(p) case UnApply(Apply(fn,_),arg) => fn.tpe match { - case MethodType(List(argtpe),_) => + case MethodType(List(argtpe,_*),_) => //Console.println("scrutinee.tpe"+scrutinee.tpe) //Console.println("argtpe"+argtpe) val r = scrutinee.tpe <:< argtpe @@ -54,6 +54,17 @@ trait ParallelMatching { } isUnapply(column.head) } + def isFlatCases(col:List[Tree]): Boolean = (col eq Nil) || { + strip(col.head)._2 match { + case a @ Apply(fn,_) => + ((a.tpe.symbol.flags & symtab.Flags.CASE) != 0) && isFlatCases(col.tail) + case Typed(_,tpt) => + ( (tpt.symbol.flags & symtab.Flags.CASE) != 0) && isFlatCases(col.tail) + case p => + Console.println(p) + false + } + } //def containsUnapply = column exists { _.isInstanceOf[UnApply] } if(settings_debug) { Console.println("/// MixtureRule("+scrutinee.name+":"+scrutinee.tpe+","+column+", rep = ") @@ -64,6 +75,9 @@ trait ParallelMatching { if(settings_debug) { Console.println("MixLiteral") } return new MixLiterals(scrutinee, column, rest) } + //if(isFlatCases(column)) { + // Console.println("flat cases!"+column) + //} //Console.println("isUnapplyHead") if(isUnapplyHead) { if(settings_debug) { Console.println("MixUnapply") } @@ -181,15 +195,15 @@ trait ParallelMatching { def getTransition(implicit theOwner: Symbol): (Tree, List[Tree], Rep, Option[Rep]) = { unapp match { - case ua @ UnApply(app @ Apply(fn, _), args) => + case ua @ UnApply(app @ Apply(fn, appargs), args) => val ures = newVarCapture(ua.pos, app.tpe) val n = args.length - val uacall = typer.typed { ValDef(ures, Apply(fn, List(Ident(scrutinee)))) } + val uacall = typer.typed { ValDef(ures, Apply(fn, Ident(scrutinee) :: appargs.tail)) } //Console.println("uacall:"+uacall) val nrowsOther = column.tail.zip(rest.row.tail) flatMap { case (pat,(ps,subst,g,b)) => strip(pat)._2 match { - case UnApply(Apply(fn1,_),args) if fn.symbol==fn1.symbol => Nil - case p => List((pat::ps, subst, g, b)) + case UnApply(app @ Apply(fn1,_),args) if fn.symbol==fn1.symbol => Nil + case p => List((pat::ps, subst, g, b)) }} val nrepFail = if(nrowsOther.isEmpty) None else Some(Rep(scrutinee::rest.temp, nrowsOther)) //Console.println("active = "+column.head+" / nrepFail = "+nrepFail) @@ -542,10 +556,10 @@ trait ParallelMatching { //Console.println("getTransition"+(uacall,vdefs,srep,frep)) val succ = repToTree(srep, typed, handleOuter) val fail = if(frep.isEmpty) failTree else repToTree(frep.get, typed, handleOuter) - val cond = if(uacall.symbol.tpe =:= definitions.BooleanClass.tpe) + val cond = if(uacall.symbol eq definitions.BooleanClass) Ident(uacall.symbol) else - typed { Not(Select(Ident(uacall.symbol),nme.isEmpty)) } + emptynessCheck(uacall.symbol) typed { squeezedBlock(List(uacall), makeIf(cond,squeezedBlock(vdefs,succ),fail)) } } } @@ -612,8 +626,9 @@ object Rep { pats = q::pats } else pats = o::pats - case ua @ UnApply(Apply(fn,_),arg) => fn.tpe match { - case MethodType(List(argtpe),_) => + case ua @ UnApply(Apply(fn,_),arg) => + fn.tpe match { + case MethodType(List(argtpe,_*),_) => pats = (if (temp(j).tpe <:< argtpe) ua else Typed(ua,TypeTree(argtpe)).setType(argtpe))::pats } case p => diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala index f4c7f3e731..2fdf72c423 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala @@ -1165,7 +1165,7 @@ print() val fntpe = fn.tpe val v = newVar(fn.pos, fntpe) var __opt_get__ = typed(Select(Ident(v),nme.get)) - var __opt_nonemp__ = Not(Select(Ident(v), nme.isEmpty)) + var __opt_nonemp__ = emptynessCheck(v) Or(And(checkType, squeezedBlock( diff --git a/test/files/run/unapply.scala b/test/files/run/unapply.scala index d351468bec..416f8174f4 100644 --- a/test/files/run/unapply.scala +++ b/test/files/run/unapply.scala @@ -28,6 +28,9 @@ object FaaPrecise { object FaaPreciseSome { def unapply(x: Bar) = Some(x.name) // return type Some[String] } +object VarFoo { + def unapply(a : Int)(implicit b : Int) : Option[Int] = Some(a + b) +} object Foo extends TestCase("Foo") with Assert { def unapply(x: Any): Option[Product2[Int, String]] = x match { case y: Bar => Some(Tuple(y.size, y.name)) @@ -55,6 +58,10 @@ object Foo extends TestCase("Foo") with Assert { assertEquals(doMatch3(b),"medium") assertEquals(doMatch4(b),"medium") assertEquals(doMatch5(b),"medium") + implicit val bc: Int = 3 + assertEquals(4 match { + case VarFoo(x) => x + }, 7) } } @@ -79,11 +86,18 @@ object Mas extends TestCase("Mas") with Assert { } object LisSeqArr extends TestCase("LisSeqArr") with Assert { +// def foo[A](x:List[A]) {} def runTest { assertEquals((List(1,2,3): Any) match { case List(x,y,_*) => (x,y)}, (1,2)) assertEquals((List(1,2,3): Any) match { case Seq(x,y,_*) => (x,y)}, (1,2)) assertEquals((Array(1,2,3): Any) match { case Seq(x,y,_*) => (x,y)}, (1,2)) //assertEquals((Array(1,2,3): Any) match { case Array(x,y,_*) => {x,y}}, {1,2}) + + // just compile, feature request #1196 +// (List(1,2,3): Any) match { +// case a @ List(x,y,_*) => foo(a) +// } + } } |