summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2007-07-06 10:07:15 +0000
committerBurak Emir <emir@epfl.ch>2007-07-06 10:07:15 +0000
commit16e1b57be1b05c460bbce0de51e607ae6b1b9027 (patch)
treea34641b84da4ad568221f9aaeec869eeff105ce6
parent0cd9d0935523dc7176d2b3bfab3ca7e46aa99af0 (diff)
downloadscala-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
-rw-r--r--src/compiler/scala/tools/nsc/matching/CodeFactory.scala7
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala33
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala2
-rw-r--r--test/files/run/unapply.scala14
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)
+// }
+
}
}