summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-03-16 17:46:58 +0000
committerPaul Phillips <paulp@improving.org>2009-03-16 17:46:58 +0000
commit67c3c68da5de6284c5e37ef4b5f907d0079f0490 (patch)
tree0db5a40f781f2f9edb21fd4c20ce6608c8a5c147 /src/library
parent00d196adeeb3aa88f2afedcb5d7eb51f0fc19896 (diff)
downloadscala-67c3c68da5de6284c5e37ef4b5f907d0079f0490.tar.gz
scala-67c3c68da5de6284c5e37ef4b5f907d0079f0490.tar.bz2
scala-67c3c68da5de6284c5e37ef4b5f907d0079f0490.zip
The birth of the @switch and @tailrec annotations.
They are located in package scala.annotation. Also in this patch: * numerous test cases for both annotations * addition of @tailrec and @switch in a few strategic locations * fixes for critical section NewScanners methods which were not being compiled into switches, immediately proving the value of @switch * tail recursive implementations for Iterator.{ dropWhile, drop} and List.dropWhile tagged with @tailrec, closing bug #1376
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/Iterator.scala29
-rw-r--r--src/library/scala/List.scala14
-rw-r--r--src/library/scala/annotation/switch.scala17
-rw-r--r--src/library/scala/annotation/tailrec.scala16
-rwxr-xr-xsrc/library/scalax/collection/immutable/Stream.scala2
5 files changed, 67 insertions, 11 deletions
diff --git a/src/library/scala/Iterator.scala b/src/library/scala/Iterator.scala
index d04d32393a..b5092a2430 100644
--- a/src/library/scala/Iterator.scala
+++ b/src/library/scala/Iterator.scala
@@ -14,6 +14,7 @@ package scala
import Predef._
import collection.mutable.{Buffer, ListBuffer, ArrayBuffer}
+import annotation.tailrec
/** The <code>Iterator</code> object provides various functions for
* creating specialized iterators.
@@ -248,8 +249,14 @@ trait Iterator[+A] {
* @param n the number of elements to drop
* @return the new iterator
*/
- def drop(n: Int): Iterator[A] =
- if (n > 0 && hasNext) { next; drop(n - 1) } else this
+ def drop(n: Int): Iterator[A] = {
+ @tailrec
+ def loop(left: Int): Iterator[A] =
+ if (left > 0 && hasNext) { next; loop(left - 1) }
+ else this
+
+ loop(n)
+ }
/** A sub-iterator of <code>until - from elements
* starting at index <code>from</code>
@@ -366,12 +373,18 @@ trait Iterator[+A] {
* @param p the predicate used to skip elements.
* @return an iterator consisting of the remaining elements
*/
- def dropWhile(p: A => Boolean): Iterator[A] =
- if (hasNext) {
- val x = next
- if (p(x)) dropWhile(p)
- else Iterator.single(x) append this
- } else this
+ def dropWhile(p: A => Boolean): Iterator[A] = {
+ @tailrec
+ def loop(): Iterator[A] =
+ if (hasNext) {
+ val x = next
+ if (p(x)) loop()
+ else Iterator.single(x) append this
+ }
+ else this
+
+ loop()
+ }
/** Return an iterator formed from this iterator and the specified iterator
* <code>that</code> by associating each element of the former with
diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala
index eda39f9ec9..5482deabf4 100644
--- a/src/library/scala/List.scala
+++ b/src/library/scala/List.scala
@@ -12,6 +12,7 @@
package scala
import scala.collection.mutable.ListBuffer
+import annotation.tailrec
import Predef._
/** This object provides methods for creating specialized lists, and for
@@ -702,6 +703,7 @@ sealed abstract class List[+A] extends Seq[A] with Product {
* @return the suffix of length <code>n</code> of the list
*/
def takeRight(n: Int): List[A] = {
+ @tailrec
def loop(lead: List[A], lag: List[A]): List[A] = lead match {
case Nil => lag
case _ :: tail => loop(tail, lag.tail)
@@ -765,9 +767,14 @@ sealed abstract class List[+A] extends Seq[A] with Product {
* @return the longest suffix of the list whose first element
* does not satisfy the predicate <code>p</code>.
*/
- override def dropWhile(p: A => Boolean): List[A] =
- if (isEmpty || !p(head)) this
- else tail dropWhile p
+ override def dropWhile(p: A => Boolean): List[A] = {
+ @tailrec
+ def loop(xs: List[A]): List[A] =
+ if (xs.isEmpty || !p(xs.head)) xs
+ else loop(xs.tail)
+
+ loop(this)
+ }
/** Returns the longest prefix of the list whose elements all satisfy
* the given predicate, and the rest of the list.
@@ -823,6 +830,7 @@ sealed abstract class List[+A] extends Seq[A] with Product {
* @return the reversed list of results.
*/
def reverseMap[B](f: A => B): List[B] = {
+ @tailrec
def loop(l: List[A], res: List[B]): List[B] = l match {
case Nil => res
case head :: tail => loop(tail, f(head) :: res)
diff --git a/src/library/scala/annotation/switch.scala b/src/library/scala/annotation/switch.scala
new file mode 100644
index 0000000000..5ecbf73905
--- /dev/null
+++ b/src/library/scala/annotation/switch.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation
+
+/** <p>
+ * An annotation to be applied to a match expression. If present,
+ * the compiler will verify that the match has been compiled to a
+ * tableswitch or lookupswitch, and issue an error if it instead
+ * compiles into a series of conditional expressions.
+ * </p>
+ */
+final class switch extends StaticAnnotation \ No newline at end of file
diff --git a/src/library/scala/annotation/tailrec.scala b/src/library/scala/annotation/tailrec.scala
new file mode 100644
index 0000000000..6ce23a92fa
--- /dev/null
+++ b/src/library/scala/annotation/tailrec.scala
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation
+
+/** <p>
+ * A method annotation which verifies that the method will be compiled
+ * with tail call optimization. If it is present, the compiler will
+ * issue an error if the method cannot be optimized into a loop.
+ * </p>
+ */
+final class tailrec extends StaticAnnotation
diff --git a/src/library/scalax/collection/immutable/Stream.scala b/src/library/scalax/collection/immutable/Stream.scala
index 036fefe70c..4055be40bc 100755
--- a/src/library/scalax/collection/immutable/Stream.scala
+++ b/src/library/scalax/collection/immutable/Stream.scala
@@ -14,6 +14,7 @@ package scalax.collection.immutable
import mutable.ListBuffer
import generic.{SequenceTemplate, SequenceFactory, EmptyIterableFactory, Builder, LazyBuilder}
import annotation.unchecked.uncheckedVariance
+import annotation.tailrec
/**
* The object <code>Stream</code> provides helper functions
@@ -486,6 +487,7 @@ self =>
* @param sep The separator string printed between consecutive elements.
*/
def print(sep: String) {
+ @tailrec
def loop(these: Stream[A], start: String) {
Console.print(start)
if (isEmpty) Console.print("empty")