summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-08-18 15:36:18 -0700
committerPaul Phillips <paulp@improving.org>2013-08-18 15:57:48 -0700
commit6d4e71c111226591a4eeb5b77efac689ef1dd79a (patch)
tree64bf11cafd20f69773517272f8077d79c5c6cef8
parentb3d9dfa9857aeb937a987536b3e2029d3be0030b (diff)
downloadscala-6d4e71c111226591a4eeb5b77efac689ef1dd79a.tar.gz
scala-6d4e71c111226591a4eeb5b77efac689ef1dd79a.tar.bz2
scala-6d4e71c111226591a4eeb5b77efac689ef1dd79a.zip
Refinement of name-based unapplySeq.
Can't finnesse the drop method. Call it blindly for now, even though in the long run you won't have to write drop.
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala22
-rw-r--r--test/files/run/string-extractor.check5
-rw-r--r--test/files/run/string-extractor.scala30
3 files changed, 46 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
index 8de8eb7d92..1b49b335c8 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
@@ -66,17 +66,17 @@ trait MatchCodeGen extends Interface {
def tupleSel(binder: Symbol)(i: Int): Tree = (REF(binder) DOT nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder
def index(tgt: Tree)(i: Int): Tree = tgt APPLY (LIT(i))
- private def definesDrop(tgt: Tree) = (tgt.tpe ne null) && (typeOfMemberNamedDrop(tgt.tpe) != NoType)
-
- // Right now this calls a direct drop member if it sees one, otherwise calls
- // into the drop helper in ScalaRunTime. You should not actually have to write
- // a method called drop for things to work, it's just not finished yet.
- def drop(tgt: Tree)(n: Int): Tree = (
- if (definesDrop(tgt))
- Apply(Select(tgt, nme.drop), LIT(n) :: Nil)
- else
- gen.mkMethodCall(traversableDropMethod, tgt :: LIT(n) :: Nil)
- )
+ // Right now this blindly calls drop on the result of the unapplySeq
+ // unless it verifiably has no drop method (this is the case in particular
+ // with Array.) You should not actually have to write a method called drop
+ // for name-based matching, but this was an expedient route for the basics.
+ def drop(tgt: Tree)(n: Int): Tree = {
+ def callDirect = fn(tgt, nme.drop, LIT(n))
+ def callRuntime = Apply(REF(traversableDropMethod), tgt :: LIT(n) :: Nil)
+ def needsRuntime = (tgt.tpe ne null) && (typeOfMemberNamedDrop(tgt.tpe) == NoType)
+
+ if (needsRuntime) callRuntime else callDirect
+ }
// NOTE: checker must be the target of the ==, that's the patmat semantics for ya
def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder)
diff --git a/test/files/run/string-extractor.check b/test/files/run/string-extractor.check
index 7268e44da9..47f3722c86 100644
--- a/test/files/run/string-extractor.check
+++ b/test/files/run/string-extractor.check
@@ -2,3 +2,8 @@ by
BY
oTheClown
nope
+1: ob
+2: obby
+2: OBBY
+3: BOBO
+3: TomTomTheClown
diff --git a/test/files/run/string-extractor.scala b/test/files/run/string-extractor.scala
index 4fb977df0b..c0fe911ff3 100644
--- a/test/files/run/string-extractor.scala
+++ b/test/files/run/string-extractor.scala
@@ -11,9 +11,26 @@ final class StringExtract(val s: String) extends AnyVal {
override def toString = s
}
+final class ThreeStringExtract(val s: String) extends AnyVal {
+ def isEmpty = (s eq null) || (s == "")
+ def get: (List[Int], Double, ThreeStringExtract) = ((s.length :: Nil, s.length.toDouble, this))
+ def length = s.length
+ def lengthCompare(n: Int) = s.length compare n
+ def apply(idx: Int): Char = s charAt idx
+ def head: Char = s charAt 0
+ def tail: String = s drop 1
+ def drop(n: Int): ThreeStringExtract = new ThreeStringExtract(s drop n)
+
+ override def toString = s
+}
+
+
object Bippy {
def unapplySeq(x: Any): StringExtract = new StringExtract("" + x)
}
+object TripleBippy {
+ def unapplySeq(x: Any): ThreeStringExtract = new ThreeStringExtract("" + x)
+}
object Test {
def f(x: Any) = x match {
@@ -21,10 +38,23 @@ object Test {
case _ => "nope"
}
+ def g(x: Any): String = x match {
+ case TripleBippy(3 :: Nil, 3.0, 'b', chars @ _*) => "1: " + chars
+ case TripleBippy(5 :: Nil, 5.0, 'b' | 'B', chars @ _*) => "2: " + chars
+ case TripleBippy(_, _, chars @ _*) => "3: " + chars
+ case _ => "nope"
+ }
+
def main(args: Array[String]): Unit = {
println(f("Bobby"))
println(f("BOBBY"))
println(f("BoBoTheClown"))
println(f("TomTomTheClown"))
+
+ println(g("bob"))
+ println(g("bobby"))
+ println(g("BOBBY"))
+ println(g("BOBO"))
+ println(g("TomTomTheClown"))
}
}