summaryrefslogtreecommitdiff
path: root/src/dotnet-library
diff options
context:
space:
mode:
authorGeoffrey Washburn <geoffrey.washburn@epfl.ch>2008-04-07 12:15:54 +0000
committerGeoffrey Washburn <geoffrey.washburn@epfl.ch>2008-04-07 12:15:54 +0000
commit48fdb8620aeb3253f0048667044b39301c1d77c8 (patch)
tree1677e938deef28b99a0d0cd2022c34f05c906d92 /src/dotnet-library
parent09d3a7bb5b1a96300b78e7f1b38f135c5ab80d20 (diff)
downloadscala-48fdb8620aeb3253f0048667044b39301c1d77c8.tar.gz
scala-48fdb8620aeb3253f0048667044b39301c1d77c8.tar.bz2
scala-48fdb8620aeb3253f0048667044b39301c1d77c8.zip
New reorg plan
Diffstat (limited to 'src/dotnet-library')
-rw-r--r--src/dotnet-library/scala/Application.scala61
-rw-r--r--src/dotnet-library/scala/Console.scala298
-rw-r--r--src/dotnet-library/scala/List.scala1305
-rw-r--r--src/dotnet-library/scala/Math.scala135
-rw-r--r--src/dotnet-library/scala/Predef.scala310
-rw-r--r--src/dotnet-library/scala/Random.scala74
-rw-r--r--src/dotnet-library/scala/StringBuilder.scala709
-rw-r--r--src/dotnet-library/scala/Symbol.scala49
-rw-r--r--src/dotnet-library/scala/compat/Platform.scala64
-rw-r--r--src/dotnet-library/scala/runtime/BooleanRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/BoxedUnit.cs36
-rw-r--r--src/dotnet-library/scala/runtime/ByteRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/CharRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/Comparator.cs40
-rw-r--r--src/dotnet-library/scala/runtime/DoubleRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/ExceptionHandling.cs27
-rw-r--r--src/dotnet-library/scala/runtime/FloatRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/IntRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/LongRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/ObjectRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/RichChar.scala70
-rw-r--r--src/dotnet-library/scala/runtime/RichClass.scala25
-rw-r--r--src/dotnet-library/scala/runtime/RichDouble.scala52
-rw-r--r--src/dotnet-library/scala/runtime/RichException.scala21
-rw-r--r--src/dotnet-library/scala/runtime/RichFloat.scala54
-rw-r--r--src/dotnet-library/scala/runtime/RichInt.scala39
-rw-r--r--src/dotnet-library/scala/runtime/RichLong.scala30
-rw-r--r--src/dotnet-library/scala/runtime/RichString.scala196
-rw-r--r--src/dotnet-library/scala/runtime/Runnable.cs17
-rw-r--r--src/dotnet-library/scala/runtime/ShortRef.cs22
-rw-r--r--src/dotnet-library/scala/runtime/StringAdd.scala28
-rw-r--r--src/dotnet-library/scala/runtime/SymtabAttribute.cs22
-rw-r--r--src/dotnet-library/scala/util/DynamicVariable.scala83
33 files changed, 3943 insertions, 0 deletions
diff --git a/src/dotnet-library/scala/Application.scala b/src/dotnet-library/scala/Application.scala
new file mode 100644
index 0000000000..4a47186a15
--- /dev/null
+++ b/src/dotnet-library/scala/Application.scala
@@ -0,0 +1,61 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+//import java.lang.System.getProperty
+//import scala.compat.Platform.currentTime
+
+/** <p>
+ * The <code>Application</code> class can be used to quickly turn objects
+ * into executable programs. Here is an example:
+ * </p><pre>
+ * object Main with Application {
+ * Console.println("Hello World!");
+ * }
+ * </pre>
+ * <p>
+ * Here, object <code>Main</code> inherits the <code>main</code> method
+ * of <code>Application</code>. The body of the <code>Main</code> object
+ * defines the main program. This technique does not work if the main
+ * program depends on command-line arguments (which are not accessible
+ * with the technique presented here).
+ * </p>
+ * <p>
+ * It is possible to time the execution of objects that inherit from class
+ * <code>Application</code> by setting the global <code>scala.time</code>
+ * property. Here is an example for benchmarking object <code>Main</code>:
+ * </p><pre>
+ * java -Dscala.time Main
+ * </pre>
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/09/2003
+ */
+
+trait Application {
+
+ /** The time when execution of this program started.
+ */
+// val executionStart: Long = currentTime
+
+ /** The default main method.
+ *
+ * @param args the arguments passed to the main method
+ */
+ def main(args: Array[String]) = {
+// if (getProperty("scala.time") ne null) {
+// val total = currentTime - executionStart
+// Console.println("[total " + total + "ms]")
+// }
+ }
+
+}
diff --git a/src/dotnet-library/scala/Console.scala b/src/dotnet-library/scala/Console.scala
new file mode 100644
index 0000000000..7a9c20c034
--- /dev/null
+++ b/src/dotnet-library/scala/Console.scala
@@ -0,0 +1,298 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import System.IO.{TextReader,TextWriter}
+
+import scala.util.DynamicVariable
+import Predef._
+
+
+/** The <code>Console</code> object implements functionality for
+ * printing Scala values on the terminal. There are also functions
+ * for reading specific values. <code>Console</code> also defines
+ * constants for marking up text on ANSI terminals.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/09/2003
+ */
+object Console {
+
+ // ANSI colors foreground
+ final val BLACK = "\033[30m"
+ final val RED = "\033[31m"
+ final val GREEN = "\033[32m"
+ final val YELLOW = "\033[33m"
+ final val BLUE = "\033[34m"
+ final val MAGENTA = "\033[35m"
+ final val CYAN = "\033[36m"
+ final val WHITE = "\033[37m"
+
+ // ANSI colors background
+ final val BLACK_B = "\033[40m"
+ final val RED_B = "\033[41m"
+ final val GREEN_B = "\033[42m"
+ final val YELLOW_B = "\033[43m"
+ final val BLUE_B = "\033[44m"
+ final val MAGENTA_B = "\033[45m"
+ final val CYAN_B = "\033[46m"
+ final val WHITE_B = "\033[47m"
+
+ // ANSI styles
+ final val RESET = "\033[0m"
+ final val BOLD = "\033[1m"
+ final val UNDERLINED = "\033[4m"
+ final val BLINK = "\033[5m"
+ final val REVERSED = "\033[7m"
+ final val INVISIBLE = "\033[8m"
+
+ private val outVar = new DynamicVariable[TextWriter](System.Console.Out)
+ private val inVar = new DynamicVariable[TextReader](System.Console.In)
+
+ def out = outVar.value
+ def in = inVar.value
+
+ /** Set the default output stream.
+ *
+ * @param out the new output stream.
+ */
+ def setOut(out: TextWriter) { outVar.value = out }
+
+ /** Set the default output stream for the duration
+ * of execution of one thunk.
+ *
+ * @param out the new output stream.
+ * @param thunk the code to execute with
+ * the new output stream active
+ */
+ def withOut[T](out: TextWriter)(thunk: =>T): T =
+ outVar.withValue(out)(thunk)
+
+
+ /** Set the default input stream.
+ *
+ * @param reader specifies the new input stream.
+ */
+ def setIn(reader: TextReader): Unit = {
+ inVar.value = reader
+ }
+
+ /** Set the default input stream for the duration
+ * of execution of one thunk.
+ *
+ * @param in the new input stream.
+ * @param thunk the code to execute with
+ * the new input stream active
+ */
+ def withIn[T](reader: TextReader)(thunk: =>T): T =
+ inVar.withValue(reader)(thunk)
+
+ /** Print an object on the terminal.
+ *
+ * @param obj the object to print.
+ */
+ def print(obj: Any): Unit = {
+ out.Write(if (null == obj) "null" else obj.toString());
+ }
+
+ /** Flush the output stream. This function is required when partial
+ * output (i.e. output not terminated by a new line character) has
+ * to be made visible on the terminal.
+ */
+ def flush() { out.Flush() }
+
+ /** Print a new line character on the terminal.
+ */
+ def println(): Unit = out.WriteLine()
+
+ /** Print out an object followed by a new line character.
+ *
+ * @param x the object to print.
+ */
+ def println(x: Any): Unit = out.WriteLine(x)
+
+ /** <p>
+ * Format and print out some text (in a fashion similar to printf in C or
+ * <code>printf</code> in Java 6).
+ * </p>
+ * <p>
+ * The format of the text to print is specified by the parameter
+ * <code>text</code>. The arguments that are inserted into specific
+ * locations in <code>text</code> are provided with parameter
+ * <code>args</code>. See class <a href="" target="contentFrame"
+ * class="java/text/MessageFormat"><code>java.text.MessageFormat</code></a>
+ * for a full specification of the <a href="#syntax" target="contentFrame"
+ * class="java/util/Formatter">format syntax</a>.
+ * </p>
+ *
+ * @param text the format of the text to print out.
+ * @param args the parameters used to instantiate the format.
+ * @throws java.lang.IllegalArgumentException
+ */
+ def printf(text: String, args: Any*) { format(text, args: _*) }
+
+ /**
+ * @see <a href="#printf(java.lang.String,scala.Any*)"
+ * target="contentFrame">Console.printf</a>.
+ */
+ def format(text: String, args: Any*): Unit =
+ if (text eq null) out.Write("null")
+ else out.Write(text, args.toArray)
+
+ /** Read a full line from the terminal.
+ *
+ * @return the string read from the terminal.
+ */
+ def readLine(): String = in.ReadLine();
+
+ /** Print a formatted text and read a full line from the terminal
+ *
+ * @param text the format of the text to print out.
+ * @param args the parameters used to instantiate the format.
+ * @return the string read from the terminal.
+ */
+ def readLine(text: String, args: Any*): String = {
+ format(text, args: _*)
+ readLine()
+ }
+
+
+ /** Read a boolean value from the terminal.
+ *
+ * @return the boolean value read from the terminal.
+ */
+ def readBoolean(): Boolean = readLine().toLowerCase() match {
+ case "true" => true
+ case "t" => true
+ case "yes" => true
+ case "y" => true
+ case _ => false
+ }
+
+ /** Read a byte value from the terminal.
+ */
+ def readByte(): Byte = readLine().toByte
+
+ /** Read a short value from the terminal.
+ */
+ def readShort(): Short = readLine.toShort
+
+ /** Read a char value from the terminal.
+ */
+ def readChar(): Char = readLine() charAt 0
+
+ /** Read an int value from the terminal.
+ */
+ def readInt(): Int = readLine().toInt
+
+ /** Read an int value from the terminal.
+ */
+ def readLong(): Long = readLine().toLong
+
+ /** Read a float value from the terminal.
+ */
+ def readFloat(): Float = readLine().toFloat
+
+ /** Read a double value from the terminal.
+ */
+ def readDouble(): Double = readLine().toDouble
+
+// /** Read in some structured input, specified by a format specifier.
+// * See class <code>java.text.MessageFormat</code> for details of
+// * the format specification.
+// *
+// * @param format the format of the input.
+// * @return a list of all extracted values.
+// */
+// def readf(format: String): List[Any] =
+// textComponents(new MessageFormat(format).parse(readLine()))
+
+// /** Read in some structured input, specified by a format specifier.
+// * Opposed to <code>readf</code>, this function only returns the
+// * first value extracted from the input according to the format
+// * specification.
+// *
+// * @param format ...
+// * @return ...
+// */
+// def readf1(format: String): Any = readf(format).head
+
+// /** Read in some structured input, specified by a format specifier.
+// * Opposed to <code>readf</code>, this function only returns the
+// * first two values extracted from the input according to the format
+// * specification.
+// *
+// * @param format ...
+// * @return ...
+// */
+// def readf2(format: String): (Any, Any) = {
+// val res = readf(format)
+// (res.head, res.tail.head)
+// }
+
+// /** Read in some structured input, specified by a format specifier.
+// * Opposed to <code>readf</code>, this function only returns the
+// * first three values extracted from the input according to the format
+// * specification.
+// *
+// * @param format ...
+// * @return ...
+// */
+// def readf3(format: String): (Any, Any, Any) = {
+// val res = readf(format)
+// (res.head, res.tail.head, res.tail.tail.head)
+// }
+
+// private def textComponents(a: Array[AnyRef]): List[Any] = {
+// var i: Int = a.length - 1
+// var res: List[Any] = Nil
+// while (i >= 0) {
+// res = (a(i) match {
+// case x: java.lang.Boolean => x.booleanValue()
+// case x: java.lang.Byte => x.byteValue()
+// case x: java.lang.Short => x.shortValue()
+// case x: java.lang.Character => x.charValue()
+// case x: java.lang.Integer => x.intValue()
+// case x: java.lang.Long => x.longValue()
+// case x: java.lang.Float => x.floatValue()
+// case x: java.lang.Double => x.doubleValue()
+// case x => x
+// }) :: res;
+// i = i - 1
+// }
+// res
+// }
+
+// private def textParams(s: Seq[Any]): Array[AnyRef] = {
+// val res = new Array[AnyRef](s.length);
+// var i: Int = 0;
+// val iter = s.elements;
+// while (iter.hasNext) {
+// res(i) = iter.next match {
+// case x: Boolean => new java.lang.Boolean(x)
+// case x: Byte => new java.lang.Byte(x)
+// case x: Short => new java.lang.Short(x)
+// case x: Char => new java.lang.Character(x)
+// case x: Int => new java.lang.Integer(x)
+// case x: Long => new java.lang.Long(x)
+// case x: Float => new java.lang.Float(x)
+// case x: Double => new java.lang.Double(x)
+// case x: Unit => "()"
+// case x: AnyRef => x
+// }
+// i = i + 1
+// }
+// res
+// }
+
+}
diff --git a/src/dotnet-library/scala/List.scala b/src/dotnet-library/scala/List.scala
new file mode 100644
index 0000000000..a592060f9a
--- /dev/null
+++ b/src/dotnet-library/scala/List.scala
@@ -0,0 +1,1305 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import scala.collection.mutable.ListBuffer
+import Predef._
+
+/** This object provides methods for creating specialized lists, and for
+ * transforming special kinds of lists (e.g. lists of lists).
+ *
+ * @author Martin Odersky and others
+ * @version 1.0, 15/07/2003
+ */
+object List {
+
+ /** Create a list with given elements.
+ *
+ * @param xs the elements to put in the list
+ * @return the list containing elements xs.
+ */
+ def apply[A](xs: A*): List[A] = xs.toList
+
+ /** for unapply matching
+ */
+ def unapplySeq[A](x: List[A]): Some[List[A]] = Some(x)
+
+ /** Create a sorted list of all integers in a range.
+ *
+ * @param from the start value of the list
+ * @param end the end value of the list
+ * @return the sorted list of all integers in range [from;end).
+ */
+ def range(start: Int, end: Int): List[Int] =
+ range(start, end, 1)
+
+ /** Create a list with element values
+ * <code>v<sub>n+1</sub> = v<sub>n</sub> + step</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and elements are in the range between <code>start</code> (inclusive)
+ * and <code>end</code> (exclusive)
+ *
+ * @param start the start value of the list
+ * @param end the end value of the list
+ * @param step the increment value of the list
+ * @return the sorted list of all integers in range [start;end).
+ */
+ def range(start: Int, end: Int, step: Int): List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = start
+ while ((step <= 0 || i < end) && (step >= 0 || i > end)) {
+ b += i
+ i += step
+ }
+ b.toList
+ }
+
+ /** Create a sorted list with element values
+ * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and elements are in the range between <code>start</code> (inclusive)
+ * and <code>end</code> (exclusive)
+ *
+ * @param start the start value of the list
+ * @param end the end value of the list
+ * @param step the increment function of the list, must be monotonically increasing or decreasing
+ * @return the sorted list of all integers in range [start;end).
+ */
+ def range(start: Int, end: Int, step: Int => Int): List[Int] = {
+ val up = step(start) > start
+ val down = step(start) < start
+ val b = new ListBuffer[Int]
+ var i = start
+ while ((!up || i < end) && (!down || i > end)) {
+ b += i
+ i += step(i)
+ }
+ b.toList
+ }
+
+ /** Create a list containing several copies of an element.
+ *
+ * @param n the length of the resulting list
+ * @param elem the element composing the resulting list
+ * @return a list composed of n elements all equal to elem
+ */
+ def make[A](n: Int, elem: A): List[A] = {
+ val b = new ListBuffer[A]
+ var i = 0
+ while (i < n) {
+ b += elem
+ i += 1
+ }
+ b.toList
+ }
+
+ /** Create a list by applying a function to successive integers.
+ *
+ * @param n the length of the resulting list
+ * @param maker the procedure which, given an integer <code>n</code>,
+ * returns the nth element of the resulting list, where
+ * <code>n</code> is in interval <code>[0;n)</code>.
+ * @return the list obtained by applying the maker function to
+ * successive integers from 0 to n (exclusive).
+ */
+ def tabulate[A](n: Int, maker: Int => A): List[A] = {
+ val b = new ListBuffer[A]
+ var i = 0
+ while (i < n) {
+ b += maker(i)
+ i += 1
+ }
+ b.toList
+ }
+
+ /** Concatenate all the elements of a given list of lists.
+ *
+ * @param xss the list of lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def flatten[A](xss: List[List[A]]): List[A] = concat(xss: _*)
+
+ /** Concatenate all the argument lists into a single list.
+ *
+ * @param xss the lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def concat[A](xss: List[A]*): List[A] = {
+ val b = new ListBuffer[A]
+ for (xs <- xss) {
+ var xc = xs
+ while (!xc.isEmpty) {
+ b += xc.head
+ xc = xc.tail
+ }
+ }
+ b.toList
+ }
+
+ /** Transforms a list of pair into a pair of lists.
+ *
+ * @param xs the list of pairs to unzip
+ * @return a pair of lists: the first list in the pair contains the list
+ */
+ def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = {
+ val b1 = new ListBuffer[A]
+ val b2 = new ListBuffer[B]
+ var xc = xs
+ while (!xc.isEmpty) {
+ b1 += xc.head._1
+ b2 += xc.head._2
+ xc = xc.tail
+ }
+ (b1.toList, b2.toList)
+ }
+
+ /** Converts an iterator to a list.
+ *
+ * @param it the iterator to convert
+ * @return a list that contains the elements returned by successive
+ * calls to <code>it.next</code>
+ */
+ def fromIterator[A](it: Iterator[A]): List[A] = it.toList
+
+ /** Converts an array into a list.
+ *
+ * @param arr the array to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length)
+
+ /** Converts a range of an array into a list.
+ *
+ * @param arr the array to convert
+ * @param start the first index to consider
+ * @param len the lenght of the range to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = {
+ var res: List[A] = Nil
+ var i = start + len
+ while (i > start) {
+ i -= 1
+ res = arr(i) :: res
+ }
+ res
+ }
+
+ /** Parses a string which contains substrings separated by a
+ * separator character and returns a list of all substrings.
+ *
+ * @param str the string to parse
+ * @param separator the separator character
+ * @return the list of substrings
+ */
+ def fromString(str: String, separator: Char): List[String] = {
+ var words: List[String] = Nil
+ var pos = str.length()
+ while (pos > 0) {
+ val pos1 = str.lastIndexOf(separator, pos - 1)
+ if (pos1 + 1 < pos)
+ words = str.substring(pos1 + 1, pos) :: words
+ pos = pos1
+ }
+ words
+ }
+
+ /** Returns the given string as a list of characters.
+ *
+ * @param str the string to convert.
+ * @return the string as a list of characters.
+ * @deprecated use <code>str.toList</code> instead
+ */
+ @deprecated def fromString(str: String): List[Char] =
+ str.toList
+
+ /** Returns the given list of characters as a string.
+ *
+ * @param xs the list to convert.
+ * @return the list in form of a string.
+ */
+ def toString(xs: List[Char]): String = {
+ val sb = new StringBuilder()
+ var xc = xs
+ while (!xc.isEmpty) {
+ sb.append(xc.head)
+ xc = xc.tail
+ }
+ sb.toString()
+ }
+
+ /** Like xs map f, but returns <code>xs</code> unchanged if function
+ * <code>f</code> maps all elements to themselves.
+ *
+ * @param xs ...
+ * @param f ...
+ * @return ...
+ */
+ def mapConserve[A <: AnyRef](xs: List[A])(f: A => A): List[A] = {
+ def loop(ys: List[A]): List[A] =
+ if (ys.isEmpty) xs
+ else {
+ val head0 = ys.head
+ val head1 = f(head0)
+ if (head1 eq head0) {
+ loop(ys.tail)
+ } else {
+ val ys1 = head1 :: mapConserve(ys.tail)(f)
+ if (xs eq ys) ys1
+ else {
+ val b = new ListBuffer[A]
+ var xc = xs
+ while (xc ne ys) {
+ b += xc.head
+ xc = xc.tail
+ }
+ b.prependToList(ys1)
+ }
+ }
+ }
+ loop(xs)
+ }
+
+ /** Returns the list resulting from applying the given function <code>f</code>
+ * to corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a0,b0), ..., f(an,bn)]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>n = min(k,l)</code>
+ */
+ def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = {
+ val b = new ListBuffer[C]
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ b += f(xc.head, yc.head)
+ xc = xc.tail
+ yc = yc.tail
+ }
+ b.toList
+ }
+
+ /** Returns the list resulting from applying the given function
+ * <code>f</code> to corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a<sub>0</sub>,b<sub>0</sub>,c<sub>0</sub>),
+ * ..., f(a<sub>n</sub>,b<sub>n</sub>,c<sub>n</sub>)]</code>
+ * if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>,
+ * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code>,
+ * <code>[c<sub>0</sub>, ..., c<sub>m</sub>]</code> and
+ * <code>n = min(k,l,m)</code>
+ */
+ def map3[A,B,C,D](xs: List[A], ys: List[B], zs: List[C])(f: (A, B, C) => D): List[D] = {
+ val b = new ListBuffer[D]
+ var xc = xs
+ var yc = ys
+ var zc = zs
+ while (!xc.isEmpty && !yc.isEmpty && !zc.isEmpty) {
+ b += f(xc.head, yc.head, zc.head)
+ xc = xc.tail
+ yc = yc.tail
+ zc = zc.tail
+ }
+ b.toList
+ }
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for all corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>(p(a<sub>0</sub>,b<sub>0</sub>) &amp;&amp;
+ * ... &amp;&amp; p(a<sub>n</sub>,b<sub>n</sub>))]</code>
+ * if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>;
+ * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code>
+ * and <code>n = min(k,l)</code>
+ */
+ def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = {
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ if (!f(xc.head, yc.head)) return false
+ xc = xc.tail
+ yc = yc.tail
+ }
+ true
+ }
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for some corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n != 0 &amp;&amp; (p(a<sub>0</sub>,b<sub>0</sub>) ||
+ * ... || p(a<sub>n</sub>,b<sub>n</sub>))]</code> if the lists are
+ * <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>,
+ * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code> and
+ * <code>n = min(k,l)</code>
+ */
+ def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = {
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ if (f(xc.head, yc.head)) return true
+ xc = xc.tail
+ yc = yc.tail
+ }
+ false
+ }
+
+ /** Transposes a list of lists.
+ * pre: All element lists have the same length.
+ *
+ * @param xss the list of lists
+ * @return the transposed list of lists
+ */
+ def transpose[A](xss: List[List[A]]): List[List[A]] = {
+ val buf = new ListBuffer[List[A]]
+ var yss = xss
+ while (!yss.head.isEmpty) {
+ buf += (yss map (_.head))
+ yss = (yss map (_.tail))
+ }
+ buf.toList
+ }
+
+ /** Lists with ordered elements are ordered
+ implicit def list2ordered[a <% Ordered[a]](x: List[a]): Ordered[List[a]] = new Ordered[List[a]] {
+ def compare [b >: List[a] <% Ordered[b]](y: b): Int = y match {
+ case y1: List[a] => compareLists(x, y1);
+ case _ => -(y compare x)
+ }
+ private def compareLists(xs: List[a], ys: List[a]): Int = {
+ if (xs.isEmpty && ys.isEmpty) 0
+ else if (xs.isEmpty) -1
+ else if (ys.isEmpty) 1
+ else {
+ val s = xs.head compare ys.head;
+ if (s != 0) s
+ else compareLists(xs.tail, ys.tail)
+ }
+ }
+ }
+ */
+}
+
+/** A class representing an ordered collection of elements of type
+ * <code>a</code>. This class comes with two implementing case
+ * classes <code>scala.Nil</code> and <code>scala.::</code> that
+ * implement the abstract members <code>isEmpty</code>,
+ * <code>head</code> and <code>tail</code>.
+ *
+ * @author Martin Odersky and others
+ * @version 1.0, 16/07/2003
+ */
+sealed abstract class List[+A] extends Seq[A] {
+
+ /** Returns true if the list does not contain any elements.
+ * @return <code>true</code>, iff the list is empty.
+ */
+ override def isEmpty: Boolean
+
+ /** Returns this first element of the list.
+ *
+ * @return the first element of this list.
+ * @throws Predef.NoSuchElementException if the list is empty.
+ */
+ def head: A
+
+ /** returns length - l, without calling length
+ */
+ override def lengthCompare(l: Int) = {
+ if (isEmpty) 0 - l
+ else if (l <= 0) 1
+ else tail.lengthCompare(l - 1)
+ }
+
+ /** Returns this list without its first element.
+ *
+ * @return this list without its first element.
+ * @throws Predef.NoSuchElementException if the list is empty.
+ */
+ def tail: List[A]
+
+ /** <p>
+ * Add an element <code>x</code> at the beginning of this list.
+ * </p>
+ *
+ * @param x the element to prepend.
+ * @return the list with <code>x</code> added at the beginning.
+ * @ex <code>1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)</code>
+ */
+ def ::[B >: A] (x: B): List[B] =
+ new scala.::(x, this)
+
+ /** <p>
+ * Add an element <code>x</code> at the end of this list.
+ * </p>
+ *
+ * @param x the element to append.
+ * @return the list with <code>x</code> added at the end.
+ */
+ def +[B >: A](x: B): List[B] =
+ if (isEmpty) List(x)
+ else {
+ val buf = new ListBuffer[B]
+ this copyToBuffer buf
+ buf += x
+ buf.toList
+ }
+
+ /** <p>
+ * Returns a list resulting from the concatenation of the given
+ * list <code>prefix</code> and this list.
+ * </p>
+ *
+ * @param prefix the list to concatenate at the beginning of this list.
+ * @return the concatenation of the two lists.
+ * @ex <code>List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)</code>
+ */
+ def :::[B >: A](prefix: List[B]): List[B] =
+ if (isEmpty) prefix
+ else {
+ val b = new ListBuffer[B]
+ var those = prefix
+ while (!those.isEmpty) {
+ b += those.head
+ those = those.tail
+ }
+ b.prependToList(this)
+ }
+
+ /** Appends two list objects.
+ */
+ override def ++[B >: A](that: Iterable[B]): List[B] = {
+ val buf = new ListBuffer[B]
+ this copyToBuffer buf
+ that copyToBuffer buf
+ buf.toList
+ }
+
+ /** Reverse the given prefix and append the current list to that.
+ * This function is equivalent to an application of <code>reverse</code>
+ * on the prefix followed by a call to <code>:::</code>, but more
+ * efficient (and tail recursive).
+ *
+ * @param prefix the prefix to reverse and then prepend
+ * @return the concatenation of the reversed prefix and the current list.
+ */
+ def reverse_:::[B >: A](prefix: List[B]): List[B] = {
+ var these: List[B] = this
+ var pres = prefix
+ while (!pres.isEmpty) {
+ these = pres.head :: these
+ pres = pres.tail
+ }
+ these
+ }
+
+ /** Returns the number of elements in the list.
+ *
+ * @return the number of elements in the list.
+ */
+ def length: Int = {
+ var these = this
+ var len = 0
+ while (!these.isEmpty) {
+ len += 1
+ these = these.tail
+ }
+ len
+ }
+
+ /** Creates a list with all indices in the list. This is
+ * equivalent to a call to <code>List.range(0, xs.length)</code>.
+ *
+ * @return a list of all indices in the list.
+ */
+ def indices: List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = 0
+ var these = this
+ while (!these.isEmpty) {
+ b += i
+ i += 1
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Returns the elements in the list as an iterator
+ *
+ * @return an iterator on the list elements.
+ */
+ override def elements: Iterator[A] = new Iterator[A] {
+ var these = List.this
+ def hasNext: Boolean = !these.isEmpty
+ def next: A =
+ if (!hasNext)
+ throw new NoSuchElementException("next on empty Iterator")
+ else {
+ val result = these.head; these = these.tail; result
+ }
+ override def toList: List[A] = these
+ }
+
+ /** Overrides the method in Iterable for efficiency.
+ *
+ * @return the list itself
+ */
+ override def toList: List[A] = this
+
+ /** Returns the list without its last element.
+ *
+ * @return the list without its last element.
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ def init: List[A] =
+ if (isEmpty) throw new UnsupportedOperationException("Nil.init")
+ else {
+ val b = new ListBuffer[A]
+ var elem = head
+ var next = tail
+ while (!next.isEmpty) {
+ b += elem
+ elem = next.head
+ next = next.tail
+ }
+ b.toList
+ }
+
+ /** Returns the last element of this list.
+ *
+ * @return the last element of the list.
+ * @throws Predef.NoSuchElementException if the list is empty.
+ */
+ override def last: A =
+ if (isEmpty) throw new Predef.NoSuchElementException("Nil.last")
+ else {
+ var cur = this
+ var next = this.tail
+ while (!next.isEmpty) {
+ cur = next
+ next = next.tail
+ }
+ cur.head
+ }
+
+ /** Returns the <code>n</code> first elements of this list, or else the whole
+ * list, if it has less than <code>n</code> elements.
+ *
+ * @param n the number of elements to take.
+ * @return the <code>n</code> first elements of this list.
+ */
+ override def take(n: Int): List[A] = {
+ val b = new ListBuffer[A]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i += 1
+ b += these.head
+ these = these.tail
+ }
+ if (these.isEmpty) this
+ else b.toList
+ }
+
+ /** Returns the list with elements belonging to the given index range.
+ *
+ * @param start the start position of the list slice.
+ * @param end the end position (exclusive) of the list slice.
+ * @return the list with elements belonging to the given index range.
+ */
+ override def slice(start: Int, end: Int): List[A] = {
+ val s = start max 0
+ val e = end min this.length
+ drop(s) take (e - s)
+ }
+
+ /** Returns the list without its <code>n</code> first elements.
+ * If this list has less than <code>n</code> elements, the empty list is returned.
+ *
+ * @param n the number of elements to drop.
+ * @return the list without its <code>n</code> first elements.
+ */
+ override def drop(n: Int): List[A] = {
+ var these = this
+ var count = n
+ while (!these.isEmpty && count > 0) {
+ these = these.tail
+ count -= 1
+ }
+ these
+ }
+
+ /** Returns the rightmost <code>n</code> elements from this list.
+ *
+ * @param n the number of elements to take
+ * @return the suffix of length <code>n</code> of the list
+ */
+ def takeRight(n: Int): List[A] = {
+ def loop(lead: List[A], lag: List[A]): List[A] = lead match {
+ case Nil => lag
+ case _ :: tail => loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Returns the list wihout its rightmost <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return the suffix of length <code>n</code> of the list
+ */
+ def dropRight(n: Int): List[A] = {
+ def loop(lead: List[A], lag: List[A]): List[A] = lead match {
+ case Nil => Nil
+ case _ :: tail => lag.head :: loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Split the list at a given point and return the two parts thus
+ * created.
+ *
+ * @param n the position at which to split
+ * @return a pair of lists composed of the first <code>n</code>
+ * elements, and the other elements.
+ */
+ def splitAt(n: Int): (List[A], List[A]) = {
+ val b = new ListBuffer[A]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i += 1
+ b += these.head
+ these = these.tail
+ }
+ (b.toList, these)
+ }
+
+ /** Returns the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ */
+ override def takeWhile(p: A => Boolean): List[A] = {
+ val b = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Returns the longest suffix of this list whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @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
+
+ /** Returns the longest prefix of the list whose elements all satisfy
+ * the given predicate, and the rest of the list.
+ *
+ * @param p the test predicate
+ * @return a pair consisting of the longest prefix of the list whose
+ * elements all satisfy <code>p</code>, and the rest of the list.
+ */
+ def span(p: A => Boolean): (List[A], List[A]) = {
+ val b = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ (b.toList, these)
+ }
+
+ /** Like <code>span</code> but with the predicate inverted.
+ */
+ def break(p: A => Boolean): (List[A], List[A]) = span { x => !p(x) }
+
+ /** Returns the <code>n</code>-th element of this list. The first element
+ * (head of the list) is at position 0.
+ *
+ * @param n index of the element to return
+ * @return the element at position <code>n</code> in this list.
+ * @throws Predef.NoSuchElementException if the list is too short.
+ */
+ def apply(n: Int): A = drop(n).head
+
+ /** Returns the list resulting from applying the given function <code>f</code> to each
+ * element of this list.
+ *
+ * @param f function to apply to each element.
+ * @return <code>[f(a0), ..., f(an)]</code> if this list is <code>[a0, ..., an]</code>.
+ */
+ final override def map[B](f: A => B): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ b += f(these.head)
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Apply a function to all the elements of the list, and return the
+ * reversed list of results. This is equivalent to a call to <code>map</code>
+ * followed by a call to <code>reverse</code>, but more efficient.
+ *
+ * @param f the function to apply to each elements.
+ * @return the reversed list of results.
+ */
+ def reverseMap[B](f: A => B): List[B] = {
+ def loop(l: List[A], res: List[B]): List[B] = l match {
+ case Nil => res
+ case head :: tail => loop(tail, f(head) :: res)
+ }
+ loop(this, Nil)
+ }
+
+ /** Apply the given function <code>f</code> to each element of this list
+ * (while respecting the order of the elements).
+ *
+ * @param f the treatment to apply to each element.
+ */
+ final override def foreach(f: A => Unit) {
+ var these = this
+ while (!these.isEmpty) {
+ f(these.head)
+ these = these.tail
+ }
+ }
+
+ /** Returns all the elements of this list that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ * It is guarenteed that the receiver list itself is returned iff all its
+ * elements satisfy the predicate `p'. Hence the following equality is valid:
+ *
+ * (xs filter p) eq xs == xs forall p
+ *
+ * @param p the predicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ final override def filter(p: A => Boolean): List[A] = {
+ // return same list if all elements satisfy p
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ these = these.tail
+ }
+ if (these.isEmpty) this
+ else {
+ val b = new ListBuffer[A]
+ var these1 = this
+ while (these1 ne these) {
+ b += these1.head
+ these1 = these1.tail
+ }
+
+ these = these.tail // prevent the second evaluation of the predicate
+ // on the element on which it first failed
+ while (!these.isEmpty) {
+ if (p(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+ }
+
+// final def filterMap[B](f: PartialFunction[A, B]): List[B] =
+// this filter f.isDefinedAt map f
+
+ /** Removes all elements of the list which satisfy the predicate
+ * <code>p</code>. This is like <code>filter</code> with the
+ * predicate inversed.
+ *
+ * @param p the predicate to use to test elements
+ * @return the list without all elements which satisfy <code>p</code>
+ */
+ def remove(p: A => Boolean): List[A] = filter (x => !p(x))
+
+ /** Partition the list in two sub-lists according to a predicate.
+ *
+ * @param p the predicate on which to partition
+ * @return a pair of lists: the list of all elements which satisfy
+ * <code>p</code> and the list of all elements which do not.
+ * The relative order of the elements in the sub-lists is the
+ * same as in the original list.
+ */
+ override def partition(p: A => Boolean): (List[A], List[A]) = {
+ val btrue = new ListBuffer[A]
+ val bfalse = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty) {
+ (if (p(these.head)) btrue else bfalse) += these.head
+ these = these.tail
+ }
+ (btrue.toList, bfalse.toList)
+ }
+
+ /** <p>
+ * Sort the list according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>,
+ * which should be true iff <code>e1</code> is smaller than
+ * <code>e2</code>.
+ * </p>
+ *
+ * @param lt the comparison function
+ * @return a list sorted according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>.
+ * @ex <pre>
+ * List("Steve", "Tom", "John", "Bob")
+ * .sort((e1, e2) => (e1 compareTo e2) &lt; 0) =
+ * List("Bob", "John", "Steve", "Tom")</pre>
+ */
+ def sort(lt : (A,A) => Boolean): List[A] = {
+ /** Merge two already-sorted lists */
+ def merge(l1: List[A], l2: List[A]): List[A] = {
+ val res = new ListBuffer[A]
+ var left1 = l1
+ var left2 = l2
+
+ while (!left1.isEmpty && !left2.isEmpty) {
+ if(lt(left1.head, left2.head)) {
+ res += left1.head
+ left1 = left1.tail
+ } else {
+ res += left2.head
+ left2 = left2.tail
+ }
+ }
+
+ res ++= left1
+ res ++= left2
+
+ res.toList
+ }
+
+ /** Split a list into two lists of about the same size */
+ def split(lst: List[A]) = {
+ val res1 = new ListBuffer[A]
+ val res2 = new ListBuffer[A]
+ var left = lst
+
+ while (!left.isEmpty) {
+ res1 += left.head
+ left = left.tail
+ if (!left.isEmpty) {
+ res2 += left.head
+ left = left.tail
+ }
+ }
+
+ (res1.toList, res2.toList)
+ }
+
+
+ /** Merge-sort the specified list */
+ def ms(lst: List[A]): List[A] =
+ lst match {
+ case Nil => lst
+ case x :: Nil => lst
+ case x :: y :: Nil =>
+ if (lt(x,y))
+ lst
+ else
+ y :: x :: Nil
+
+ case lst =>
+ val (l1, l2) = split(lst)
+ val l1s = ms(l1)
+ val l2s = ms(l2)
+ merge(l1s, l2s)
+ }
+
+ ms(this)
+ }
+
+
+ /** Count the number of elements in the list which satisfy a predicate.
+ *
+ * @param p the predicate for which to count
+ * @return the number of elements satisfying the predicate <code>p</code>.
+ */
+ def count(p: A => Boolean): Int = {
+ var cnt = 0
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) cnt += 1
+ these = these.tail
+ }
+ cnt
+ }
+
+ /** Tests if the predicate <code>p</code> is satisfied by all elements
+ * in this list.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff all elements of this list satisfy the
+ * predicate <code>p</code>.
+ */
+ override def forall(p: A => Boolean): Boolean = {
+ var these = this
+ while (!these.isEmpty) {
+ if (!p(these.head)) return false
+ these = these.tail
+ }
+ true
+ }
+
+ /** Tests the existence in this list of an element that satisfies the
+ * predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff there exists an element in this list that
+ * satisfies the predicate <code>p</code>.
+ */
+ override def exists(p: A => Boolean): Boolean = {
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return true
+ these = these.tail
+ }
+ false
+ }
+
+ /** Find and return the first element of the list satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the list satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ override def find(p: A => Boolean): Option[A] = {
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return Some(these.head)
+ these = these.tail
+ }
+ None
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the list is
+ * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldLeft[B](z: B)(f: (B, A) => B): B = {
+ var acc = z
+ var these = this
+ while (!these.isEmpty) {
+ acc = f(acc, these.head)
+ these = these.tail
+ }
+ acc
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
+ * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldRight[B](z: B)(f: (A, B) => B): B = this match {
+ case Nil => z
+ case x :: xs => f(x, xs.foldRight(z)(f))
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from left to right
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the list has elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ override def reduceLeft[B >: A](f: (B, B) => B): B = this match {
+ case Nil => throw new UnsupportedOperationException("Nil.reduceLeft")
+ case x :: xs => ((xs: List[B]) foldLeft (x: B))(f)
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from right to left
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the list has elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ *
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ override def reduceRight[B >: A](f: (B, B) => B): B = this match {
+ case Nil => throw new UnsupportedOperationException("Nil.reduceRight")
+ case x :: Nil => x: B
+ case x :: xs => f(x, xs reduceRight f)
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this list, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this list is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ final override def flatMap[B](f: A => Iterable[B]): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ var those = f(these.head).elements
+ while (those.hasNext) {
+ b += those.next
+ }
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** A list consisting of all elements of this list in reverse order.
+ */
+ override def reverse: List[A] = {
+ var result: List[A] = Nil
+ var these = this
+ while (!these.isEmpty) {
+ result = these.head :: result
+ these = these.tail
+ }
+ result
+ }
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two lists is longer than the other, its remaining elements are ignored.
+ *
+ * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ...,
+ * (a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>))</code> when
+ * <code>List(a<sub>0</sub>, ..., a<sub>m</sub>)
+ * zip List(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked.
+ */
+ def zip[B](that: List[B]): List[(A, B)] = {
+ val b = new ListBuffer[(A, B)]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += (these.head, those.head)
+ these = these.tail
+ those = those.tail
+ }
+ b.toList
+ }
+
+ /** Returns a list that pairs each element of this list
+ * with its index, counting from 0.
+ *
+ * @return the list <code>List((a<sub>0</sub>,0), (a<sub>1</sub>,1), ...)</code>
+ * where <code>a<sub>i</sub></code> are the elements of this list.
+ */
+ def zipWithIndex: List[(A, Int)] = {
+ val b = new ListBuffer[(A, Int)]
+ var these = this
+ var idx = 0
+
+ while(!these.isEmpty) {
+ b += (these.head, idx)
+ these = these.tail
+ idx += 1
+ }
+
+ b.toList
+ }
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param that list <code>that</code> may have a different length
+ * as the self list.
+ * @param thisElem element <code>thisElem</code> is used to fill up the
+ * resulting list if the self list is shorter than
+ * <code>that</code>
+ * @param thatElem element <code>thatElem</code> is used to fill up the
+ * resulting list if <code>that</code> is shorter than
+ * the self list
+ * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ...,
+ * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>),
+ * ..., {elem,b<sub>m</sub>})</code>
+ * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip
+ * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is
+ * invoked where <code>m &gt; n</code>.
+ */
+ def zipAll[B, C >: A, D >: B](that: List[B], thisElem: C, thatElem: D): List[(C, D)] = {
+ val b = new ListBuffer[(C, D)]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += (these.head, those.head)
+ these = these.tail
+ those = those.tail
+ }
+ while (!these.isEmpty) {
+ b += (these.head, thatElem)
+ these = these.tail
+ }
+ while (!those.isEmpty) {
+ b += (thisElem, those.head)
+ those = those.tail
+ }
+ b.toList
+ }
+
+ /** Computes the union of this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to add to the list.
+ * @return a list without doubles containing the elements of this
+ * list and those of the given list <code>that</code>.
+ */
+ def union[B >: A](that: List[B]): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ if (!that.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.prependToList(that)
+ }
+
+ /** Computes the difference between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to remove from this list.
+ * @return this list without the elements of the given list
+ * <code>that</code>.
+ * @deprecated use <code>--</code> instead
+ */
+ @deprecated
+ def diff[B >: A](that: List[B]): List[B] = this -- that
+
+ /** Computes the difference between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to remove from this list.
+ * @return this list without the elements of the given list
+ * <code>that</code>.
+ */
+ def -- [B >: A](that: List[B]): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ if (!that.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Computes the difference between this list and the given object
+ * <code>x</code>.
+ *
+ * @param x the object to remove from this list.
+ * @return this list without the elements of the given object
+ * <code>x</code>.
+ */
+ def - [B >: A](x: B): List[B] =
+ this -- List(x)
+
+ def flatten[B](implicit f : A => Iterable[B]) : List[B] = {
+ val buf = new ListBuffer[B]
+ foreach(f(_).foreach(buf += _))
+ buf.toList
+ }
+
+ /** Computes the intersection between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list to intersect.
+ * @return the list of elements contained both in this list and
+ * in the given list <code>that</code>.
+ */
+ def intersect[B >: A](that: List[B]): List[B] = filter(x => that contains x)
+
+ /** Removes redundant elements from the list. Uses the method <code>==</code>
+ * to decide if two elements are identical.
+ *
+ * @return the list without doubles.
+ */
+ def removeDuplicates: List[A] = {
+ val b = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty) {
+ if (!these.tail.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ override protected def stringPrefix = "List"
+ override def projection = toStream
+ override def toStream : Stream[A] = new Stream.Definite[A] {
+ override def force : List[A] = List.this
+ override def isEmpty = List.this.isEmpty
+ override def head = List.this.head
+ override def tail = List.this.tail.toStream
+ protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = if (!isEmpty) {
+ var prefix0 = prefix
+ var buf1 = buf.append(prefix0).append(head)
+ prefix0 = ", "
+ var tail0 = tail
+ while (!tail0.isEmpty) {
+ buf1 = buf.append(prefix0).append(tail0.head)
+ tail0 = tail0.tail
+ }
+ buf1
+ } else buf
+ }
+
+}
+
+/** The empty list.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+@SerialVersionUID(0 - 8256821097970055419L)
+case object Nil extends List[Nothing] {
+ override def isEmpty = true
+ def head: Nothing =
+ throw new NoSuchElementException("head of empty list")
+ def tail: List[Nothing] =
+ throw new NoSuchElementException("tail of empty list")
+}
+
+/** A non empty list characterized by a head and a tail.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+@SerialVersionUID(0L - 8476791151983527571L)
+final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] {
+ def head : B = hd
+ def tail : List[B] = tl
+ override def isEmpty: Boolean = false
+}
+
diff --git a/src/dotnet-library/scala/Math.scala b/src/dotnet-library/scala/Math.scala
new file mode 100644
index 0000000000..4d03de9b77
--- /dev/null
+++ b/src/dotnet-library/scala/Math.scala
@@ -0,0 +1,135 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import Predef._
+
+object Math {
+
+ /** The smallest possible value for <a href="Byte.html" target="_self">scala.Byte</a>. */
+ val MIN_BYTE = System.Byte.MinValue
+ /** The greatest possible value for <a href="Byte.html" target="_self">scala.Byte</a>. */
+ val MAX_BYTE = System.Byte.MaxValue
+
+ /** The smallest possible value for <a href="Short.html" target="_self">scala.Short</a>. */
+ val MIN_SHORT = System.Int16.MinValue
+ /** The greatest possible value for <a href="Short.html" target="_self">scala.Short</a>. */
+ val MAX_SHORT = System.Int16.MaxValue
+
+ /** The smallest possible value for <a href="Char.html" target="_self">scala.Char</a>. */
+ val MIN_CHAR = System.Char.MinValue
+ /** The greatest possible value for <a href="Char.html" target="_self">scala.Char</a>. */
+ val MAX_CHAR = System.Char.MaxValue
+
+ /** The smallest possible value for <a href="Int.html" target="_self">scala.Int</a>. */
+ val MIN_INT = System.Int32.MinValue
+ /** The greatest possible value for <a href="Int.html" target="_self">scala.Int</a>. */
+ val MAX_INT = System.Int32.MaxValue
+
+ /** The smallest possible value for <a href="Long.html" target="_self">scala.Long</a>. */
+ val MIN_LONG = System.Int64.MinValue
+ /** The greatest possible value for <a href="Long.html" target="_self">scala.Long</a>. */
+ val MAX_LONG = System.Int64.MaxValue
+
+ /** The smallest possible value for <a href="Float.html" target="_self">scala.Float</a>. */
+ val MIN_FLOAT = System.Single.MinValue
+ /** The smallest difference between two values of <a href="Float.html" target="_self">scala.Float</a>. */
+ val EPS_FLOAT = System.Single.Epsilon
+ /** The greatest possible value for <a href="Float.html" target="_self">scala.Float</a>. */
+ val MAX_FLOAT = System.Single.MinValue
+ /** A value of type <a href="Float.html" target="_self">scala.Float</a> that represents no number. */
+ //val NaN_FLOAT = System.Single.NaN
+ /** Negative infinity of type <a href="Float.html" target="_self">scala.Float</a>. */
+ //val NEG_INF_FLOAT = System.Double.NegativeInfinity
+ /** Positive infinity of type <a href="Float.html" target="_self">scala.Float</a>. */
+ //val POS_INF_FLOAT = System.Double.PositiveInfinity
+
+ /** The smallest possible value for <a href="Double.html" target="_self">scala.Double</a>. */
+ val MIN_DOUBLE = System.Double.MinValue
+ /** The smallest difference between two values of <a href="Double.html" target="_self">scala.Double</a>. */
+ val EPS_DOUBLE = System.Double.Epsilon
+ /** The greatest possible value for <a href="Double.html" target="_self">scala.Double</a>. */
+ val MAX_DOUBLE = System.Double.MaxValue
+ /** A value of type <a href="Double.html" target="_self">scala.Double</a> that represents no number. */
+ //val NaN_DOUBLE = System.Double.NaN
+ /** Negative infinity of type <a href="Double.html" target="_self">scala.Double</a>. */
+ //val NEG_INF_DOUBLE = System.Double.NegativeInfinity
+ /** Positive infinity of type <a href="Double.html" target="_self">scala.Double</a>. */
+ //val POS_INF_DOUBLE = System.Double.PositiveInfinity
+
+ /** The <code>double</code> value that is closer than any other to
+ * <code>e</code>, the base of the natural logarithms.
+ */
+
+ val E = System.Math.E
+ val Pi = System.Math.PI
+
+ //def random: Double = System.Math.random()
+
+ def sin(x: Double): Double = System.Math.Sin(x)
+ def cos(x: Double): Double = System.Math.Cos(x)
+ def tan(x: Double): Double = System.Math.Tan(x)
+ def asin(x: Double): Double = System.Math.Asin(x)
+ def acos(x: Double): Double = System.Math.Acos(x)
+ def atan(x: Double): Double = System.Math.Atan(x)
+
+ def toRadians(x: Double): Double = x * Pi / 180.0
+
+ def toDegrees(x: Double): Double = x * 180.0 / Pi
+
+ def exp(x: Double): Double = System.Math.Exp(x)
+ def log(x: Double): Double = System.Math.Log(x)
+ def sqrt(x: Double): Double = System.Math.Sqrt(x)
+ def sqrt(x: Int): Int = System.Math.Sqrt(x.toDouble).toInt
+ def IEEEremainder(x: Double, y: Double): Double = System.Math.IEEERemainder(x, y)
+
+ def ceil(x: Double): Double = System.Math.Ceiling(x)
+ def floor(x: Double): Double = System.Math.Floor(x)
+
+ //def rint(x: Double): Double = System.Math.rint(x)
+ def atan2(y: Double, x: Double): Double = System.Math.Atan2(y, x)
+ def pow(x: Double, y: Double): Double = System.Math.Pow(x, y)
+ def round(x: Float): Int = System.Math.Round(x).toInt
+ def round(x: Double): Long = System.Math.Round(x).toLong
+
+ def abs(x: Int): Int = System.Math.Abs(x)
+ def abs(x: Long): Long = System.Math.Abs(x)
+ def abs(x: Float): Float = System.Math.Abs(x)
+ def abs(x: Double): Double = System.Math.Abs(x)
+
+ def max(x: Int, y: Int): Int = System.Math.Max(x, y)
+ def max(x: Long, y: Long): Long = System.Math.Max(x, y)
+ def max(x: Float, y: Float): Float = System.Math.Max(x, y)
+ def max(x: Double, y: Double): Double = System.Math.Max(x, y)
+
+ def min(x: Int, y: Int): Int = System.Math.Min(x, y)
+ def min(x: Long, y: Long): Long = System.Math.Min(x, y)
+ def min(x: Float, y: Float): Float = System.Math.Min(x, y)
+ def min(x: Double, y: Double): Double = System.Math.Min(x, y)
+
+ // from Java 1.5
+// def log10(x: Double): Double = java.lang.Math.log10(x)
+// def cbrt(x: Double): Double = java.lang.Math.cbrt(x)
+
+// def ulp(x: Double): Double = java.lang.Math.ulp(x)
+// def ulp(x: Float): Float = java.lang.Math.ulp(x)
+// def signum(x: Double): Double = java.lang.Math.signum(x)
+// def signum(x: Float): Float = java.lang.Math.signum(x)
+// def sinh(x: Double): Double = java.lang.Math.sinh(x)
+// def cosh(x: Double): Double = java.lang.Math.cosh(x)
+// def tanh(x: Double):Double = java.lang.Math.tanh(x)
+// def hypot(x: Double, y: Double): Double = java.lang.Math.hypot(x, y)
+// def expm1(x: Double): Double = java.lang.Math.expm1(x)
+// def log1p(x: Double): Double = java.lang.Math.log1p(x)
+
+}
diff --git a/src/dotnet-library/scala/Predef.scala b/src/dotnet-library/scala/Predef.scala
new file mode 100644
index 0000000000..dc45fe2bec
--- /dev/null
+++ b/src/dotnet-library/scala/Predef.scala
@@ -0,0 +1,310 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/** The <code>Predef</code> object provides definitions that are
+ * accessible in all Scala compilation units without explicit
+ * qualification.
+ */
+object Predef {
+
+ // classOf dummy ------------------------------------------------------
+
+ /** Return the runtime representation of a class type. */
+ def classOf[T]: Class[T] = null
+
+ // aliases ------------------------------------------------------------
+
+ type byte = scala.Byte
+ type short = scala.Short
+ type char = scala.Char
+ type int = scala.Int
+ type long = scala.Long
+ type float = scala.Float
+ type double = scala.Double
+ type boolean = scala.Boolean
+ type unit = scala.Unit
+
+ type String = System.String
+ type Class[T] = System.Type
+ type Runnable = scala.runtime.Runnable
+
+ type Throwable = System.Exception
+ type Exception = System.Exception
+ type Error = System.Exception
+
+ type RuntimeException = System.Exception
+ type NullPointerException = System.NullReferenceException
+ type ClassCastException = System.InvalidCastException
+ type IndexOutOfBoundsException = System.IndexOutOfRangeException
+ type ArrayIndexOutOfBoundsException = System.IndexOutOfRangeException
+ type StringIndexOutOfBoundsException = System.IndexOutOfRangeException
+ type UnsupportedOperationException = System.InvalidOperationException
+ type IllegalArgumentException = System.ArgumentException
+ type NoSuchElementException = System.InvalidOperationException
+ //type NumberFormatException = java.lang.NumberFormatException
+
+ // miscelleaneous -----------------------------------------------------
+
+ //val $scope = scala.xml.TopScope
+
+ type Function[-A, +B] = Function1[A, B]
+
+ type Map[A, B] = collection.immutable.Map[A, B]
+ type Set[A] = collection.immutable.Set[A]
+
+ val Map = collection.immutable.Map
+ val Set = collection.immutable.Set
+
+ // errors and asserts -------------------------------------------------
+
+ def error(message: String): Nothing = throw new Error(message)
+
+ def exit: Nothing = exit(0)
+
+ def exit(status: Int): Nothing = {
+ System.Environment.Exit(status)
+ throw new Throwable()
+ }
+
+ def assert(assertion: Boolean) {
+ if (!assertion)
+ throw new Error("assertion failed")
+ }
+
+ def assert(assertion: Boolean, message: Any) {
+ if (!assertion)
+ throw new Error("assertion failed: " + message)
+ }
+
+ def assume(assumption: Boolean) {
+ if (!assumption)
+ throw new IllegalArgumentException("assumption failed")
+ }
+
+ def assume(assumption: Boolean, message: Any) {
+ if (!assumption)
+ throw new IllegalArgumentException("assumption failed: " + message)
+ }
+
+ // tupling ------------------------------------------------------------
+
+ type Pair[+A, +B] = Tuple2[A, B]
+ object Pair {
+ def apply[A, B](x: A, y: B) = Tuple2(x, y)
+ def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x)
+ }
+
+ type Triple[+A, +B, +C] = Tuple3[A, B, C]
+ object Triple {
+ def apply[A, B, C](x: A, y: B, z: C) = Tuple3(x, y, z)
+ def unapply[A, B, C](x: Tuple3[A, B, C]): Option[Tuple3[A, B, C]] = Some(x)
+ }
+
+ class ArrowAssoc[A](x: A) {
+ def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
+ }
+ implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
+
+ def Tuple[A1](x1: A1) = Tuple1(x1)
+ def Tuple[A1, A2](x1: A1, x2: A2) = Tuple2(x1, x2)
+ def Tuple[A1, A2, A3](x1: A1, x2: A2, x3: A3) = Tuple3(x1, x2, x3)
+ def Tuple[A1, A2, A3, A4](x1: A1, x2: A2, x3: A3, x4: A4) = Tuple4(x1, x2, x3, x4)
+ def Tuple[A1, A2, A3, A4, A5](x1: A1, x2: A2, x3: A3, x4: A4, x5: A5) = Tuple5(x1, x2, x3, x4, x5)
+ def Tuple[A1, A2, A3, A4, A5, A6](x1: A1, x2: A2, x3: A3, x4: A4, x5: A5, x6: A6) = Tuple6(x1, x2, x3, x4, x5, x6)
+ def Tuple[A1, A2, A3, A4, A5, A6, A7](x1: A1, x2: A2, x3: A3, x4: A4, x5: A5, x6: A6, x7: A7) = Tuple7(x1, x2, x3, x4, x5, x6, x7)
+ def Tuple[A1, A2, A3, A4, A5, A6, A7, A8](x1: A1, x2: A2, x3: A3, x4: A4, x5: A5, x6: A6, x7: A7, x8: A8) = Tuple8(x1, x2, x3, x4, x5, x6, x7, x8)
+ def Tuple[A1, A2, A3, A4, A5, A6, A7, A8, A9](x1: A1, x2: A2, x3: A3, x4: A4, x5: A5, x6: A6, x7: A7, x8: A8, x9: A9) = Tuple9(x1, x2, x3, x4, x5, x6, x7, x8, x9)
+
+ // printing and reading -----------------------------------------------
+
+ def print(x: Any) = Console.print(x)
+ def println() = Console.println()
+ def println(x: Any) = Console.println(x)
+ //def printf(text: String, xs: Any*) = Console.printf(text, xs: _*)
+ //def format(text: String, xs: Any*) = Console.format(text, xs)
+
+ def readLine(): String = Console.readLine()
+ def readLine(text: String, args: Any*) = Console.readLine(text, args)
+ def readBoolean() = Console.readBoolean()
+ def readByte() = Console.readByte()
+ def readShort() = Console.readShort()
+ def readChar() = Console.readChar()
+ def readInt() = Console.readInt()
+ def readLong() = Console.readLong()
+ def readFloat() = Console.readFloat()
+ def readDouble() = Console.readDouble()
+ //def readf(format: String) = Console.readf(format)
+ //def readf1(format: String) = Console.readf1(format)
+ //def readf2(format: String) = Console.readf2(format)
+ //def readf3(format: String) = Console.readf3(format)
+
+ // views --------------------------------------------------------------
+
+ implicit def identity[A](x: A): A = x
+
+ implicit def byteWrapper(x: Byte) = new runtime.RichByte(x)
+ implicit def shortWrapper(x: Short) = new runtime.RichShort(x)
+ implicit def intWrapper(x: Int) = new runtime.RichInt(x)
+ implicit def charWrapper(c: Char) = new runtime.RichChar(c)
+ implicit def longWrapper(x: Long) = new runtime.RichLong(x)
+ implicit def floatWrapper(x: Float) = new runtime.RichFloat(x)
+ implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x)
+
+ implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x)
+
+ implicit def stringWrapper(x: String) = new runtime.RichString(x)
+ //implicit def stringBuilderWrapper(x : StringBuilder) = new runtime.RichStringBuilder(x)
+
+ implicit def any2stringadd(x: Any) = new runtime.StringAdd(x)
+
+ implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc)
+
+ final class GetClassWrapper(obj: AnyRef) {
+ def getClass(): runtime.RichClass = classWrapper(obj.GetType())
+ }
+ implicit def getClassWrapper(obj: AnyRef) = new GetClassWrapper(obj)
+ implicit def classWrapper(clazz: Class[_]): runtime.RichClass =
+ new runtime.RichClass(clazz)
+
+ implicit def unit2ordered(x: Unit): Ordered[Unit] = new Ordered[Unit] with Proxy {
+ def self: Any = x
+ def compare(y: Unit): Int = 0
+ }
+
+ implicit def iterable2ordered[A <% Ordered[A]](xs: Iterable[A]): Ordered[Iterable[A]] =
+ new Ordered[Iterable[A]] with Proxy {
+ val self = xs
+ def compare(that: Iterable[A]): Int = {
+ var res = 0
+ val these = xs.elements
+ val those = that.elements
+ while (res == 0 && these.hasNext)
+ res = if (those.hasNext) these.next compare those.next else 1
+ if (res == 0) {
+ if (those.hasNext) -1 else 0
+ } else
+ res
+ }
+ }
+
+ implicit def tuple22ordered[A1 <% Ordered[A1], A2 <% Ordered[A2]](x: Tuple2[A1, A2]): Ordered[Tuple2[A1, A2]] =
+ new Ordered[Tuple2[A1, A2]] with Proxy {
+ val self = x
+ def compare(y: Tuple2[A1, A2]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) x._2 compare y._2
+ else res
+ }
+ }
+
+ implicit def tuple32ordered[A1 <% Ordered[A1], A2 <% Ordered[A2], A3 <% Ordered[A3]](x: Tuple3[A1, A2, A3]): Ordered[Tuple3[A1, A2, A3]] =
+ new Ordered[Tuple3[A1, A2, A3]] with Proxy {
+ val self = x
+ def compare(y: Tuple3[A1, A2, A3]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple2(x._2, x._3) compare Tuple2(y._2, y._3)
+ else res
+ }
+ }
+
+ implicit def tuple42ordered[A1 <% Ordered[A1], A2 <% Ordered[A2], A3 <% Ordered[A3], A4 <% Ordered[A4]](x: Tuple4[A1, A2, A3, A4]): Ordered[Tuple4[A1, A2, A3, A4]] =
+ new Ordered[Tuple4[A1, A2, A3, A4]] with Proxy {
+ val self = x
+ def compare(y: Tuple4[A1, A2, A3, A4]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple3(x._2, x._3, x._4) compare Tuple3(y._2, y._3, y._4)
+ else res
+ }
+ }
+
+ implicit def tuple52ordered[A1 <% Ordered[A1], A2 <% Ordered[A2], A3 <% Ordered[A3], A4 <% Ordered[A4], A5 <% Ordered[A5]](x: Tuple5[A1, A2, A3, A4, A5]): Ordered[Tuple5[A1, A2, A3, A4, A5]] =
+ new Ordered[Tuple5[A1, A2, A3, A4, A5]] with Proxy {
+ val self = x
+ def compare(y: Tuple5[A1, A2, A3, A4, A5]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple4(x._2, x._3, x._4, x._5) compare Tuple4(y._2, y._3, y._4, y._5)
+ else res
+ }
+ }
+
+ implicit def tuple62ordered[A1 <% Ordered[A1], A2 <% Ordered[A2], A3 <% Ordered[A3], A4 <% Ordered[A4], A5 <% Ordered[A5], A6 <% Ordered[A6]](x: Tuple6[A1, A2, A3, A4, A5, A6]): Ordered[Tuple6[A1, A2, A3, A4, A5, A6]] =
+ new Ordered[Tuple6[A1, A2, A3, A4, A5, A6]] with Proxy {
+ val self = x
+ def compare(y: Tuple6[A1, A2, A3, A4, A5, A6]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple5(x._2, x._3, x._4, x._5, x._6) compare Tuple5(y._2, y._3, y._4, y._5, y._6)
+ else res
+ }
+ }
+
+ implicit def tuple72ordered[A1 <% Ordered[A1], A2 <% Ordered[A2], A3 <% Ordered[A3], A4 <% Ordered[A4], A5 <% Ordered[A5], A6 <% Ordered[A6], A7 <% Ordered[A7]](x: Tuple7[A1, A2, A3, A4, A5, A6, A7]): Ordered[Tuple7[A1, A2, A3, A4, A5, A6, A7]] =
+ new Ordered[Tuple7[A1, A2, A3, A4, A5, A6, A7]] with Proxy {
+ val self = x
+ def compare(y: Tuple7[A1, A2, A3, A4, A5, A6, A7]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple6(x._2, x._3, x._4, x._5, x._6, x._7) compare Tuple6(y._2, y._3, y._4, y._5, y._6, y._7)
+ else res
+ }
+ }
+
+ implicit def tuple82ordered[A1 <% Ordered[A1], A2 <% Ordered[A2], A3 <% Ordered[A3], A4 <% Ordered[A4], A5 <% Ordered[A5], A6 <% Ordered[A6], A7 <% Ordered[A7], A8 <% Ordered[A8]](x: Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]): Ordered[Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] =
+ new Ordered[Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] with Proxy {
+ val self = x
+ def compare(y: Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple7(x._2, x._3, x._4, x._5, x._6, x._7, x._8) compare Tuple7(y._2, y._3, y._4, y._5, y._6, y._7, y._8)
+ else res
+ }
+ }
+
+ implicit def tuple92ordered[A1 <% Ordered[A1], A2 <% Ordered[A2], A3 <% Ordered[A3], A4 <% Ordered[A4], A5 <% Ordered[A5], A6 <% Ordered[A6], A7 <% Ordered[A7], A8 <% Ordered[A8], A9 <% Ordered[A9]](x: Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]): Ordered[Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] =
+ new Ordered[Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] with Proxy {
+ val self = x
+ def compare(y: Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple8(x._2, x._3, x._4, x._5, x._6, x._7, x._8, x._9) compare Tuple8(y._2, y._3, y._4, y._5, y._6, y._7, y._8, y._9)
+ else res
+ }
+ }
+
+ implicit def byte2short(x: Byte): Short = x.toShort
+ implicit def byte2int(x: Byte): Int = x.toInt
+ implicit def byte2long(x: Byte): Long = x.toLong
+ implicit def byte2float(x: Byte): Float = x.toFloat
+ implicit def byte2double(x: Byte): Double = x.toDouble
+
+ implicit def short2int(x: Short): Int = x.toInt
+ implicit def short2long(x: Short): Long = x.toLong
+ implicit def short2float(x: Short): Float = x.toFloat
+ implicit def short2double(x: Short): Double = x.toDouble
+
+ implicit def char2int(x: Char): Int = x.toInt
+ implicit def char2long(x: Char): Long = x.toLong
+ implicit def char2float(x: Char): Float = x.toFloat
+ implicit def char2double(x: Char): Double = x.toDouble
+
+ implicit def int2long(x: Int): Long = x.toLong
+ implicit def int2float(x: Int): Float = x.toFloat
+ implicit def int2double(x: Int): Double = x.toDouble
+
+ implicit def long2float(x: Long): Float = x.toFloat
+ implicit def long2double(x: Long): Double = x.toDouble
+
+ implicit def float2double(x: Float): Double = x.toDouble
+
+ implicit def forceArrayProjection[A](x : Array.Projection[A]) : Array[A] = x.force
+
+ def currentThread = System.Threading.Thread.CurrentThread
+
+}
diff --git a/src/dotnet-library/scala/Random.scala b/src/dotnet-library/scala/Random.scala
new file mode 100644
index 0000000000..7d0b1be853
--- /dev/null
+++ b/src/dotnet-library/scala/Random.scala
@@ -0,0 +1,74 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/**
+ * @author Stephane Micheloud
+ */
+class Random(self0: System.Random) {
+ private var rnd = self0 // see setSeed(seed)
+ def self = rnd
+
+ /** Creates a new random number generator using a single long seed. */
+ def this(seed: Long) = this(new System.Random(seed.toInt))
+
+ /** Creates a new random number generator using a single integer seed. */
+ def this(seed: Int) = this(new System.Random(seed))
+
+ /** Creates a new random number generator. */
+ def this() = this(new System.Random(System.Environment.TickCount))
+
+ /** Returns the next pseudorandom, uniformly distributed boolean value
+ * from this random number generator's sequence.
+ */
+ def nextBoolean(): Boolean = (nextInt() & 0x1) == 1
+
+ /** Generates random bytes and places them into a user-supplied byte
+ * array.
+ */
+ def nextBytes(bytes: Array[Byte]) { rnd.NextBytes(bytes) }
+
+ /** Returns the next pseudorandom, uniformly distributed double value
+ * between 0.0 and 1.0 from this random number generator's sequence.
+ */
+ def nextDouble(): Double = rnd.NextDouble()
+
+ /** Returns the next pseudorandom, uniformly distributed float value
+ * between 0.0 and 1.0 from this random number generator's sequence.
+ */
+ def nextFloat(): Float = nextDouble().toFloat
+
+ /** Returns the next pseudorandom, Gaussian ("normally") distributed
+ * double value with mean 0.0 and standard deviation 1.0 from this
+ * random number generator's sequence.
+ */
+ //def nextGaussian(): Double
+
+ /** Returns the next pseudorandom, uniformly distributed int value
+ * from this random number generator's sequence.
+ */
+ def nextInt(): Int = rnd.Next()
+
+ /** Returns a pseudorandom, uniformly distributed int value between 0
+ * (inclusive) and the specified value (exclusive), drawn from this
+ * random number generator's sequence.
+ */
+ def nextInt(n: Int): Int = rnd.Next(0, n)
+
+ /** Returns the next pseudorandom, uniformly distributed long value
+ * from this random number generator's sequence.
+ */
+ def nextLong(): Long = nextInt().toLong // 2x nextInt() ?!
+
+ def setSeed(seed: Long) { rnd = new System.Random(seed.toInt) }
+
+}
diff --git a/src/dotnet-library/scala/StringBuilder.scala b/src/dotnet-library/scala/StringBuilder.scala
new file mode 100644
index 0000000000..b6912060e2
--- /dev/null
+++ b/src/dotnet-library/scala/StringBuilder.scala
@@ -0,0 +1,709 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import Predef._
+
+/** <p>
+ * A mutable sequence of characters. This class provides an API compatible
+ * with <code>java.lang.StringBuilder</code>, but with no guarantee of
+ * synchronization.
+ * </p>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+final class StringBuilder(initCapacity: Int, private val initValue: String)
+extends (Int => Char) with Proxy {
+ if (initCapacity < 0) throw new IllegalArgumentException
+ if (initValue eq null) throw new NullPointerException
+
+ /** The value is used for character storage. */
+ private var value = new Array[Char](initCapacity + initValue.length)
+
+ /** The count is the number of characters used. */
+ private var count: Int = 0
+
+ /** Constructs a string builder with no characters in it and an
+ * initial capacity of 16 characters.
+ */
+ def this() = this(16, "")
+
+ /** Constructs a string builder with no characters in it and an
+ * initial capacity specified by the <code>capacity</code> argument.
+ *
+ * @param capacity the initial capacity.
+ * @throws NegativeArraySizeException if the <code>capacity</code>
+ * argument is less than <code>0</code>.
+ */
+ def this(capacity: Int) = this(capacity, "")
+
+ def this(str: String) = this(16, str)
+
+ append(initValue)
+
+ def self = this
+
+ def toArray: Array[Char] = value
+
+ def length: Int = count
+
+ def length_=(n: Int) { setLength(n) }
+
+ /** Sets the length of the character sequence.
+ *
+ * @param newLength the new length
+ * @throws IndexOutOfBoundsException if the <code>n</code> argument is negative.
+ */
+ def setLength(n: Int) {
+ if (n < 0)
+ throw new StringIndexOutOfBoundsException//(n)
+ if (n > value.length) expandCapacity(n)
+ if (count < n)
+ while (count < n) {
+ value(count) = '\0'; count += 1
+ }
+ else
+ count = n
+ }
+
+ /** Returns the current capacity. The capacity is the amount of storage
+ * available for newly inserted characters, beyond which an allocation
+ * will occur.
+ *
+ * @return the current capacity
+ */
+ def capacity: Int = value.length
+
+ /** Same as <code>ensureCapacity</code>. */
+ def capacity_=(n: Int) { ensureCapacity(n) }
+
+ /** <p>
+ * Ensures that the capacity is at least equal to the specified minimum.
+ * If the current capacity is less than the argument, then a new internal
+ * array is allocated with greater capacity. The new capacity is the larger of:
+ * </p>
+ * <ul>
+ * <li>The <code>n</code> argument.
+ * <li>Twice the old capacity, plus <code>2</code>.
+ * </ul>
+ * <p>
+ * If the <code>n</code> argument is non-positive, this
+ * method takes no action and simply returns.
+ * </p>
+ *
+ * @param n the minimum desired capacity.
+ */
+ def ensureCapacity(n: Int) {
+ if (n > value.length) expandCapacity(n)
+ }
+
+ private def expandCapacity(n: Int) {
+ val newCapacity = (value.length + 1) * 2
+ value = StringBuilder.copyOf(
+ value,
+ if (newCapacity < 0) Math.MAX_INT else if (n > newCapacity) n else newCapacity
+ )
+ }
+
+ /** <p>
+ * Returns the <code>Char</code> value in this sequence at the specified index.
+ * The first <code>Char</code> value is at index <code>0</code>, the next at index
+ * <code>1</code>, and so on, as in array indexing.
+ * </p>
+ * <p>
+ * The index argument must be greater than or equal to
+ * <code>0</code>, and less than the length of this sequence.
+ * </p>
+ *
+ * @param index the index of the desired <code>Char</code> value.
+ * @return the <code>Char</code> value at the specified index.
+ * @throws IndexOutOfBoundsException if <code>index</code> is
+ * negative or greater than or equal to <code>length()</code>.
+ */
+ def charAt(index: Int): Char = {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException//(index)
+ value(index)
+ }
+
+ /** Same as <code>charAt</code>. */
+ def apply(i: Int): Char = charAt(i)
+
+ /** <p>
+ * Removes the <code>Char</code> at the specified position in this
+ * sequence. This sequence is shortened by one <code>Char</code>.
+ * </p>
+ *
+ * @param index Index of <code>Char</code> to remove
+ * @return This object.
+ * @throws StringIndexOutOfBoundsException if the <code>index</code>
+ * is negative or greater than or equal to <code>length()</code>.
+ */
+ def deleteCharAt(index: Int): StringBuilder = {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException//(index)
+ compat.Platform.arraycopy(value, index + 1, value, index, count - index - 1)
+ count -= 1
+ this
+ }
+
+ /** <p>
+ * The character at the specified index is set to <code>ch</code>. This
+ * sequence is altered to represent a new character sequence that is
+ * identical to the old character sequence, except that it contains the
+ * character <code>ch</code> at position <code>index</code>.
+ * </p>
+ * <p>
+ * The index argument must be greater than or equal to
+ * <code>0</code>, and less than the length of this sequence.
+ * </p>
+ *
+ * @param index the index of the character to modify.
+ * @param ch the new character.
+ * @throws IndexOutOfBoundsException if <code>index</code> is
+ * negative or greater than or equal to <code>length()</code>.
+ */
+ def setCharAt(index: Int, ch: Char) {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException//(index)
+ value(index) = ch
+ }
+
+ /** Same as <code>setCharAt</code>. */
+ def update(i: Int, c: Char) { setCharAt(i, c) }
+
+ /** Returns a new <code>String</code> that contains a subsequence of
+ * characters currently contained in this character sequence. The
+ * substring begins at the specified index and extends to the end of
+ * this sequence.
+ *
+ * @param start The beginning index, inclusive.
+ * @return The new string.
+ * @throws StringIndexOutOfBoundsException if <code>start</code> is
+ * less than zero, or greater than the length of this object.
+ */
+ def substring(start: Int): String = substring(start, count)
+
+ /** Returns a new <code>String</code> that contains a subsequence of
+ * characters currently contained in this sequence. The
+ * substring begins at the specified <code>start</code> and
+ * extends to the character at index <code>end - 1</code>.
+ *
+ * @param start The beginning index, inclusive.
+ * @param end The ending index, exclusive.
+ * @return The new string.
+ * @throws StringIndexOutOfBoundsException if <code>start</code>
+ * or <code>end</code> are negative or greater than
+ * <code>length()</code>, or <code>start</code> is
+ * greater than <code>end</code>.
+ */
+ def substring(start: Int, end: Int): String = {
+ if (start < 0)
+ throw new StringIndexOutOfBoundsException//(start)
+ if (end > count)
+ throw new StringIndexOutOfBoundsException//(end)
+ if (start > end)
+ throw new StringIndexOutOfBoundsException//(end - start)
+ new String(value, start, end - start)
+ }
+
+ /** <p>
+ * Appends the string representation of the <code>Any</code>
+ * argument.
+ * </p>
+ * <p>
+ * The argument is converted to a string as if by the method
+ * <code>System.Convert.ToString</code>, and the characters of
+ * that string are then appended to this sequence.
+ * </p>
+ *
+ * @param x an <code>Any</code> object.
+ * @return a reference to this object.
+ */
+ def append(x: Any): StringBuilder =
+ append(System.Convert.ToString(x))
+
+ /** Appends the specified string to this character sequence.
+ *
+ * @param s a string.
+ * @return a reference to this object.
+ */
+ def append(s: String): StringBuilder = {
+ val str = if (s == null) "null" else s
+ val len = str.length
+ if (len > 0) {
+ val newCount = count + len
+ if (newCount > value.length) expandCapacity(newCount)
+ compat.Platform.arraycopy(str.ToCharArray, 0, value, count, len)
+ count = newCount
+ }
+ this
+ }
+
+ /** Appends the specified string builder to this sequence.
+ *
+ * @param sb
+ * @return
+ */
+ def append(sb: StringBuilder): StringBuilder =
+ if (sb == null)
+ append("null")
+ else {
+ val len = sb.length
+ val newCount = count + len
+ if (newCount > value.length) expandCapacity(newCount)
+ compat.Platform.arraycopy(sb.toArray, 0, value, count, len)
+ count = newCount
+ this
+ }
+
+ /** <p>
+ * Appends the string representation of the <code>Char</code> array
+ * argument to this sequence.
+ * </p>
+ * <p>
+ * The characters of the array argument are appended, in order, to
+ * the contents of this sequence. The length of this sequence
+ * increases by the length of the argument.
+ * </p>
+ *
+ * @param x the characters to be appended.
+ * @return a reference to this object.
+ */
+ def append(x: Array[Char]): StringBuilder =
+ append(x, 0, x.length)
+
+ /** <p>
+ * Appends the string representation of a subarray of the
+ * <code>char</code> array argument to this sequence.
+ * </p>
+ * <p>
+ * Characters of the <code>Char</code> array <code>x</code>, starting at
+ * index <code>offset</code>, are appended, in order, to the contents
+ * of this sequence. The length of this sequence increases
+ * by the value of <code>len</code>.
+ * </p>
+ *
+ * @param x the characters to be appended.
+ * @param offset the index of the first <code>Char</code> to append.
+ * @param len the number of <code>Char</code>s to append.
+ * @return a reference to this object.
+ */
+ def append(x: Array[Char], offset: Int, len: Int): StringBuilder = {
+ val newCount = count + len
+ if (newCount > value.length) expandCapacity(newCount)
+ compat.Platform.arraycopy(x, offset, value, count, len)
+ count = newCount
+ this
+ }
+
+ /** <p>
+ * Appends the string representation of the <code>Boolean</code>
+ * argument to the sequence.
+ * </p>
+ * <p>
+ * The argument is converted to a string as if by the method
+ * <code>System.Convert.ToString</code>, and the characters of
+ * that string are then appended to this sequence.
+ * </p>
+ *
+ * @param x a <code>Boolean</code>.
+ * @return a reference to this object.
+ */
+ def append(x: Boolean): StringBuilder = {
+ if (x) {
+ val newCount = count + 4
+ if (newCount > value.length) expandCapacity(newCount)
+ value(count) = 't'; count += 1
+ value(count) = 'r'; count += 1
+ value(count) = 'u'; count += 1
+ value(count) = 'e'; count += 1
+ } else {
+ val newCount = count + 5
+ if (newCount > value.length) expandCapacity(newCount)
+ value(count) = 'f'; count += 1
+ value(count) = 'a'; count += 1
+ value(count) = 'l'; count += 1
+ value(count) = 's'; count += 1
+ value(count) = 'e'; count += 1
+ }
+ this
+ }
+
+ def append(x: Char): StringBuilder = {
+ val newCount = count + 1
+ if (newCount > value.length) expandCapacity(newCount)
+ value(count) = x; count += 1
+ this
+ }
+
+ def append(x: Int): StringBuilder =
+ append(System.Convert.ToString(x))
+
+ def append(x: Long): StringBuilder =
+ append(System.Convert.ToString(x))
+
+ def append(x: Float): StringBuilder =
+ append(System.Convert.ToString(x))
+
+ def append(x: Double): StringBuilder =
+ append(System.Convert.ToString(x))
+
+ /** Removes the characters in a substring of this sequence.
+ * The substring begins at the specified <code>start</code> and extends to
+ * the character at index <code>end - 1</code> or to the end of the
+ * sequence if no such character exists. If
+ * <code>start</code> is equal to <code>end</code>, no changes are made.
+ *
+ * @param start The beginning index, inclusive.
+ * @param end The ending index, exclusive.
+ * @return This object.
+ * @throws StringIndexOutOfBoundsException if <code>start</code>
+ * is negative, greater than <code>length()</code>, or
+ * greater than <code>end</code>.
+ */
+ def delete(start: Int, end: Int): StringBuilder = {
+ if (start < 0 || start > end)
+ throw new StringIndexOutOfBoundsException//(start)
+ val end0 = if (end > count) count else end
+ val len = end0 - start
+ if (len > 0) {
+ compat.Platform.arraycopy(value, start + len, value, start, count - end0)
+ count -= len
+ }
+ this
+ }
+
+ /** Replaces the characters in a substring of this sequence
+ * with characters in the specified <code>String</code>. The substring
+ * begins at the specified <code>start</code> and extends to the character
+ * at index <code>end - 1</code> or to the end of the sequence if no such
+ * character exists. First the characters in the substring are removed and
+ * then the specified <code>String</code> is inserted at <code>start</code>.
+ *
+ * @param start The beginning index, inclusive.
+ * @param end The ending index, exclusive.
+ * @param str String that will replace previous contents.
+ * @return This object.
+ * @throws StringIndexOutOfBoundsException if <code>start</code>
+ * is negative, greater than <code>length()</code>, or
+ * greater than <code>end</code>.
+ */
+ def replace(start: Int, end: Int, str: String) {
+ if (start < 0 || start > count || start > end)
+ throw new StringIndexOutOfBoundsException//(start)
+
+ val end0 = if (end > count) count else end
+ val len = str.length()
+ val newCount = count + len - (end0 - start)
+ if (newCount > value.length) expandCapacity(newCount)
+
+ compat.Platform.arraycopy(value, end, value, start + len, count - end)
+ compat.Platform.arraycopy(str.ToCharArray, 0, value, start, len)
+ count = newCount
+ this
+ }
+
+ /** Inserts the string representation of a subarray of the <code>str</code>
+ * array argument into this sequence. The subarray begins at the specified
+ * <code>offset</code> and extends <code>len</code> <code>char</code>s.
+ * The characters of the subarray are inserted into this sequence at
+ * the position indicated by <code>index</code>. The length of this
+ * sequence increases by <code>len</code> <code>Char</code>s.
+ *
+ * @param index position at which to insert subarray.
+ * @param str a <code>Char</code> array.
+ * @param offset the index of the first <code>char</code> in subarray to
+ * be inserted.
+ * @param len the number of <code>Char</code>s in the subarray to
+ * be inserted.
+ * @return This object
+ * @throws StringIndexOutOfBoundsException if <code>index</code>
+ * is negative or greater than <code>length()</code>, or
+ * <code>offset</code> or <code>len</code> are negative, or
+ * <code>(offset+len)</code> is greater than
+ * <code>str.length</code>.
+ */
+ def insert(index: Int, str: Array[Char], offset: Int, len: Int): StringBuilder = {
+ if (index < 0 || index > count)
+ throw new StringIndexOutOfBoundsException//(index)
+ if (offset < 0 || len < 0 || offset > str.length - len)
+ throw new StringIndexOutOfBoundsException/*(
+ "offset " + offset + ", len " + len +
+ ", str.length " + str.length)*/
+ val newCount = count + len
+ if (newCount > value.length) expandCapacity(newCount)
+ compat.Platform.arraycopy(value, index, value, index + len, count - index)
+ compat.Platform.arraycopy(str, offset, value, index, len)
+ count = newCount
+ this
+ }
+
+ /** <p>
+ * Inserts the string representation of the <code>Any</code>
+ * argument into this character sequence.
+ * </p>
+ * <p>
+ * The second argument is converted to a string as if by the method
+ * <code>System.Convert.ToString</code>, and the characters of that
+ * string are then inserted into this sequence at the indicated
+ * offset.
+ * </p>
+ * <p>
+ * The offset argument must be greater than or equal to
+ * <code>0</code>, and less than or equal to the length of this
+ * sequence.
+ * </p>
+ *
+ * @param offset the offset.
+ * @param x an <code>Any</code> value.
+ * @return a reference to this object.
+ * @throws StringIndexOutOfBoundsException if the offset is invalid.
+ */
+ def insert(at: Int, x: Any): StringBuilder =
+ insert(at, System.Convert.ToString(x))
+
+ /** Inserts the string into this character sequence.
+ *
+ * @param at the offset position.
+ * @param x a string.
+ * @return a reference to this object.
+ * @throws StringIndexOutOfBoundsException if the offset is invalid.
+ */
+ def insert(at: Int, x: String): StringBuilder = {
+ if (at < 0 || at > count)
+ throw new StringIndexOutOfBoundsException//(at)
+ val str = if (x == null) "null" else x
+ val len = str.length
+ val newCount = count + len
+ if (newCount > value.length) expandCapacity(newCount)
+ compat.Platform.arraycopy(value, at, value, at + len, count - at)
+ compat.Platform.arraycopy(str.ToCharArray, 0, value, at, len)
+ count = newCount
+ this
+ }
+
+ /** Inserts the string representation of the <code>Char</code> array
+ * argument into this sequence.
+ *
+ * @param at the offset position.
+ * @param x a character array.
+ * @return a reference to this object.
+ * @throws StringIndexOutOfBoundsException if the offset is invalid.
+ */
+ def insert(at: Int, x: Array[Char]): StringBuilder = {
+ if (at < 0 || at > count)
+ throw new StringIndexOutOfBoundsException//(at)
+ val len = x.length
+ val newCount = count + len
+ if (newCount > value.length) expandCapacity(newCount)
+ compat.Platform.arraycopy(value, at, value, at + len, count - at)
+ compat.Platform.arraycopy(x, 0, value, at, len)
+ count = newCount
+ this
+ }
+
+ def insert(at: Int, x: Boolean): StringBuilder =
+ insert(at, System.Convert.ToString(x))
+
+ def insert(at: Int, x: Char): StringBuilder = {
+ if (at < 0 || at > count)
+ throw new StringIndexOutOfBoundsException//(at)
+ val newCount = count + 1
+ if (newCount > value.length) expandCapacity(newCount)
+ compat.Platform.arraycopy(value, at, value, at + 1, count - at)
+ value(at) = x
+ count = newCount
+ this
+ }
+
+ def insert(at: Int, x: Int): StringBuilder =
+ insert(at, System.Convert.ToString(x))
+
+ def insert(at: Int, x: Long): StringBuilder =
+ insert(at, System.Convert.ToString(x))
+
+ def insert(at: Int, x: Float): StringBuilder =
+ insert(at, System.Convert.ToString(x))
+
+ def insert(at: Int, x: Double): StringBuilder =
+ insert(at, System.Convert.ToString(x))
+
+ /** Returns the index within this string of the first occurrence of the
+ * specified substring. The integer returned is the smallest value
+ * <i>k</i> such that:
+ * <blockquote><pre>
+ * this.toString().startsWith(str, <i>k</i>)
+ * </pre></blockquote>
+ * is <code>true</code>.
+ *
+ * @param str any string.
+ * @return if the string argument occurs as a substring within this
+ * object, then the index of the first character of the first
+ * such substring is returned; if it does not occur as a
+ * substring, <code>-1</code> is returned.
+ * @throws NullPointerException if <code>str</code> is <code>null</code>.
+ */
+ def indexOf(str: String): Int = indexOf(str, 0)
+
+ def indexOf(str: String, fromIndex: Int): Int =
+ StringBuilder.indexOf(value, 0, count, str.ToCharArray, 0, str.length(), fromIndex)
+
+ /** Returns the index within this string of the rightmost occurrence
+ * of the specified substring. The rightmost empty string "" is
+ * considered to occur at the index value <code>this.length()</code>.
+ * The returned index is the largest value <i>k</i> such that
+ * <blockquote><pre>
+ * this.toString().startsWith(str, k)
+ * </pre></blockquote>
+ * is true.
+ *
+ * @param str the substring to search for.
+ * @return if the string argument occurs one or more times as a substring
+ * within this object, then the index of the first character of
+ * the last such substring is returned. If it does not occur as
+ * a substring, <code>-1</code> is returned.
+ * @throws NullPointerException if <code>str</code> is <code>null</code>.
+ */
+ def lastIndexOf(str: String): Int = lastIndexOf(str, count)
+
+ def lastIndexOf(str: String, fromIndex: Int): Int =
+ StringBuilder.lastIndexOf(value, 0, count, str.ToCharArray, 0, str.length(), fromIndex)
+
+ /** <p>
+ * Causes this character sequence to be replaced by the reverse of the
+ * sequence. If there are any surrogate pairs included in the sequence,
+ * these are treated as single characters for the reverse operation.
+ * Thus, the order of the high-low surrogates is never reversed.
+ * </p>
+ * <p>
+ * Let <i>n</i> be the character length of this character sequence
+ * (not the length in <code>Char</code> values) just prior to
+ * execution of the <code>reverse</code> method. Then the
+ * character at index <i>k</i> in the new character sequence is
+ * equal to the character at index <i>n-k-1</i> in the old
+ * character sequence.
+ * </p>
+ *
+ * @return a reference to this object.
+ */
+ def reverse(): StringBuilder = {
+ val n = count - 1
+ var j = (n-1) >> 1
+ while (j >= 0) {
+ val temp = value(j)
+ val temp2 = value(n - j)
+ value(j) = temp2
+ value(n - j) = temp
+ j -= 1
+ }
+ this
+ }
+
+ /** Returns a string representing the data in this sequence.
+ * A new <code>String</code> object is allocated and initialized to
+ * contain the character sequence currently represented by this
+ * object. This <code>String</code> is then returned. Subsequent
+ * changes to this sequence do not affect the contents of the
+ * <code>String</code>.
+ *
+ * @return a string representation of this sequence of characters.
+ */
+ override def toString(): String = new String(value, 0, count)
+
+}
+
+
+object StringBuilder {
+
+ // method <code>java.util.Arrays.copyOf</code> exists since 1.6
+ private def copyOf(src: Array[Char], newLength: Int): Array[Char] = {
+ val dest = new Array[Char](newLength)
+ compat.Platform.arraycopy(src, 0, dest, 0, Math.min(src.length, newLength))
+ dest
+ }
+
+ private def indexOf(source: Array[Char], sourceOffset: Int, sourceCount: Int,
+ target: Array[Char], targetOffset: Int, targetCount: Int,
+ fromIndex: Int): Int =
+ if (fromIndex >= sourceCount)
+ if (targetCount == 0) sourceCount else -1
+ else {
+ val inx = if (fromIndex < 0) 0 else fromIndex
+ if (targetCount == 0)
+ inx
+ else {
+ val first = target(targetOffset)
+ val max = sourceOffset + (sourceCount - targetCount)
+
+ var i = sourceOffset + inx
+ while (i <= max) {
+ /* Look for first character. */
+ if (source(i) != first) {
+ i += 1
+ while (i <= max && source(i) != first) i += 1
+ }
+ /* Found first character, now look at the rest of v2 */
+ if (i <= max) {
+ var j = i + 1
+ val end = j + targetCount - 1
+ var k = targetOffset + 1
+ while (j < end && source(j) == target(k)) {
+ j += 1
+ k += 1
+ }
+ if (j == end) {
+ /* Found whole string. */
+ return i - sourceOffset
+ }
+ } // if
+ i += 1
+ } // while
+ -1
+ }
+ }
+
+ private def lastIndexOf(source: Array[Char], sourceOffset: Int, sourceCount: Int,
+ target: Array[Char], targetOffset: Int, targetCount: Int,
+ fromIndex: Int): Int = {
+ val rightIndex = sourceCount - targetCount
+ if (fromIndex < 0) return -1
+ val inx = if (fromIndex > rightIndex) rightIndex else fromIndex
+ // Empty string always matches
+ if (targetCount == 0) return inx
+
+ val strLastIndex = targetOffset + targetCount - 1
+ val strLastChar = target(strLastIndex)
+ val min = sourceOffset + targetCount - 1
+ var i = min + fromIndex
+
+ while (true) {
+ while (i >= min && source(i) != strLastChar) i -= 1
+ if (i < min) return -1
+ var j = i - 1
+ val start = j - (targetCount - 1)
+ var k = strLastIndex - 1
+ var outerWhile = false
+ while (j > start && !outerWhile) {
+ if (source(j) != target(k)) {
+ j -= 1
+ k -= 1
+ i -= 1
+ outerWhile = true
+ }
+ }
+ if (!outerWhile) return start - sourceOffset + 1
+ }
+ -1
+ }
+}
diff --git a/src/dotnet-library/scala/Symbol.scala b/src/dotnet-library/scala/Symbol.scala
new file mode 100644
index 0000000000..27bc2de7e1
--- /dev/null
+++ b/src/dotnet-library/scala/Symbol.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/** <p>
+ * Instances of <code>Symbol</code> can be created easily with
+ * Scala's built-in quote mechanism.
+ * </p>
+ * <p>
+ * For instance, the <a href="http://scala-lang.org/" target="_top">Scala</a>
+ * term <code>'mysym</code> will invoke the constructor of the
+ * <code>Symbol</code> class in the following way:
+ * <code>new Symbol("mysym")</code>.
+ * </p>
+ *
+ * @author Martin Odersky
+ * @version 1.7, 08/12/2003
+ */
+final case class Symbol(name: String) {
+
+ /** Converts this symbol to a string.
+ */
+ override def toString(): String = {
+ "'" + name
+ }
+
+ /** <p>
+ * Makes this symbol into a unique reference.
+ * </p>
+ * <p>
+ * If two interened symbols are equal (i.e. they have the same name)
+ * then they must be identical (wrt reference equality).
+ * </p>
+ *
+ * @return the unique reference to this symbol.
+ */
+ def intern: Symbol = this
+
+}
diff --git a/src/dotnet-library/scala/compat/Platform.scala b/src/dotnet-library/scala/compat/Platform.scala
new file mode 100644
index 0000000000..e589860bdc
--- /dev/null
+++ b/src/dotnet-library/scala/compat/Platform.scala
@@ -0,0 +1,64 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.compat
+
+
+import Predef._
+
+object Platform {
+
+ type StackOverflowError = System.StackOverflowException
+ type ConcurrentModificationException = System.Exception
+
+ /**
+ * @param src ..
+ * @param srcPos ..
+ * @param dest ..
+ * @param destPos ..
+ * @param length ..
+ */
+ def arraycopy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int) {
+ if (!src.isInstanceOf[System.Array]) throw new Exception("src for arraycopy is not an Array; use scala.Array.copy for boxed arrays");
+ if (!dest.isInstanceOf[System.Array]) throw new Exception("dest for arraycopy is not an Array; use scala.Array.copy for boxed arrays");
+ System.Array.Copy(src.asInstanceOf[System.Array], srcPos, dest.asInstanceOf[System.Array], destPos, length)
+ }
+
+ /** Create array of the same type as arrayInstance with the given
+ * length.
+ *
+ * @param elemClass ..
+ * @param length ..
+ * @return ..
+ */
+ def createArray(elemClass: Class[_], length: Int): AnyRef =
+ System.Array.CreateInstance(elemClass, length)
+
+ def arrayclear(arr: Array[Int]) {
+ System.Array.Clear(arr.asInstanceOf[System.Array], 0, arr.length)
+ }
+
+ def getClassForName(name: String): Class[_] = System.Type.GetType(name)
+
+ val EOL = System.Environment.NewLine
+
+ def currentTime: Long = 0L
+/* // compiler crash :-(
+ private lazy val baseTicks = (new System.DateTime(1970, 1, 1, 0, 0, 0)).Ticks
+ def currentTime: Long = {
+ val nowTicks = System.DateTime.UtcNow.Ticks
+ (nowTicks - baseTicks) / 10000
+ }
+*/
+ def collectGarbage { System.GC.Collect() }
+
+}
+
diff --git a/src/dotnet-library/scala/runtime/BooleanRef.cs b/src/dotnet-library/scala/runtime/BooleanRef.cs
new file mode 100644
index 0000000000..2680b30149
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BooleanRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class BooleanRef {
+ public bool elem;
+ public BooleanRef(bool elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedUnit.cs b/src/dotnet-library/scala/runtime/BoxedUnit.cs
new file mode 100644
index 0000000000..d3ef5a3e11
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedUnit.cs
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public sealed class BoxedUnit {
+
+ public static readonly BoxedUnit UNIT = new BoxedUnit();
+
+ private BoxedUnit() { }
+
+ override public bool Equals(object other) {
+ return this == other;
+ }
+
+ override public int GetHashCode() {
+ return 0;
+ }
+
+ override public string ToString() {
+ return "()";
+ }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/ByteRef.cs b/src/dotnet-library/scala/runtime/ByteRef.cs
new file mode 100644
index 0000000000..6a539a3afd
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ByteRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class ByteRef {
+ public byte elem;
+ public ByteRef(byte elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/CharRef.cs b/src/dotnet-library/scala/runtime/CharRef.cs
new file mode 100644
index 0000000000..75b2817b83
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/CharRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class CharRef {
+ public char elem;
+ public CharRef(char elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/Comparator.cs b/src/dotnet-library/scala/runtime/Comparator.cs
new file mode 100644
index 0000000000..4a1322d49c
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/Comparator.cs
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ public class Comparator {
+ public static bool equals(object a, object b) {
+ if (a == null)
+ return b == null;
+ if (a.Equals(b))
+ return true;
+ if (a == b)
+ return true;
+ IConvertible aa = a as IConvertible;
+ IConvertible bb = b as IConvertible;
+ if (aa != null && bb != null) {
+ if (a is Decimal || b is Decimal)
+ return aa.ToDecimal(null) == bb.ToDecimal(null);
+ if (a is Double || b is Double)
+ return aa.ToDouble(null) == bb.ToDouble(null);
+ if (a is Single || b is Single)
+ return aa.ToSingle(null) == bb.ToSingle(null);
+ if (a is Int64 || b is Int64)
+ return aa.ToInt64(null) == bb.ToInt64(null);
+ return aa.ToInt32(null) == bb.ToInt32(null);
+ }
+ return false;
+ }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/DoubleRef.cs b/src/dotnet-library/scala/runtime/DoubleRef.cs
new file mode 100644
index 0000000000..60a155f00b
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/DoubleRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class DoubleRef {
+ public double elem;
+ public DoubleRef(double elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/ExceptionHandling.cs b/src/dotnet-library/scala/runtime/ExceptionHandling.cs
new file mode 100644
index 0000000000..4448777f2e
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ExceptionHandling.cs
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ public abstract class ExceptionHandling {
+
+ public static Exception tryCatch(Runnable runnable) {
+ try {
+ runnable.run();
+ return null;
+ } catch (Exception exception) {
+ return exception;
+ }
+ }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/FloatRef.cs b/src/dotnet-library/scala/runtime/FloatRef.cs
new file mode 100644
index 0000000000..ee81ea3c9c
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/FloatRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class FloatRef {
+ public float elem;
+ public FloatRef(float elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/IntRef.cs b/src/dotnet-library/scala/runtime/IntRef.cs
new file mode 100644
index 0000000000..e305df145f
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/IntRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class IntRef {
+ public int elem;
+ public IntRef(int elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/LongRef.cs b/src/dotnet-library/scala/runtime/LongRef.cs
new file mode 100644
index 0000000000..e6387ed96f
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/LongRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class LongRef {
+ public long elem;
+ public LongRef(long elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/ObjectRef.cs b/src/dotnet-library/scala/runtime/ObjectRef.cs
new file mode 100644
index 0000000000..a25d61639e
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ObjectRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class ObjectRef {
+ public Object elem;
+ public ObjectRef(Object elem) { this.elem = elem; }
+ override public string ToString() { return "" + elem; }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichChar.scala b/src/dotnet-library/scala/runtime/RichChar.scala
new file mode 100644
index 0000000000..285530e5be
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichChar.scala
@@ -0,0 +1,70 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.NoSuchElementException
+
+/** <p>
+ * For example, in the following code
+ * </p>
+ * <pre>
+ * <b>object</b> test <b>extends</b> Application {
+ * Console.println(<chr>'\40'</chr>.isWhitespace)
+ * Console.println('\011'.isWhitespace)
+ * Console.println('1'.asDigit == 1)
+ * Console.println('A'.asDigit == 10)
+ * }</pre>
+ * <p>
+ * the implicit conversions are performed using the predefined view
+ * <a href="../Predef$object.html#charWrapper(scala.Char)"
+ * target="contentFrame"><code>Predef.charWrapper</code></a>.
+ * </p>
+ */
+final class RichChar(x: Char) extends Proxy with Ordered[Char] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Char].compare
+ def compare (y: Char): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def asDigit: Int = System.Char.GetNumericValue(x).toInt
+
+ def isControl: Boolean = System.Char.IsControl(x)
+ def isDigit: Boolean = System.Char.IsDigit(x)
+ def isLetter: Boolean = System.Char.IsLetter(x)
+ def isLetterOrDigit: Boolean = System.Char.IsLetterOrDigit(x)
+ def isLowerCase: Boolean = System.Char.IsLower(x)
+ def isUpperCase: Boolean = System.Char.IsUpper(x)
+ def isWhitespace: Boolean = System.Char.IsWhiteSpace(x)
+
+ def toLowerCase: Char = System.Char.ToLower(x)
+ def toUpperCase: Char = System.Char.ToUpper(x)
+
+ /** Create an Iterator[Char] over the characters from 'x' to 'y' - 1
+ */
+ def until(limit: Char): Iterator[Char] = new Iterator[Char] {
+ private var ch = x
+ def hasNext: Boolean = ch < limit
+ def next: Char =
+ if (hasNext) { val j = ch; ch = (ch + 1).toChar; j }
+ else throw new NoSuchElementException("next on empty iterator")
+ }
+
+ //def until(y: Char): Iterator[Char] = to(y)
+
+ /** Create an Iterator[Char] over the characters from 'x' to 'y'
+ */
+ def to(y: Char): Iterator[Char] = until((y + 1).toChar)
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichClass.scala b/src/dotnet-library/scala/runtime/RichClass.scala
new file mode 100644
index 0000000000..e964a66ab1
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichClass.scala
@@ -0,0 +1,25 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+import Predef.Class
+
+final class RichClass(val self: Class[_]) extends Proxy {
+
+ def isPrimitive(): Boolean = self.IsPrimitive
+ def isArray(): Boolean = self.IsArray
+
+ def getClass(): RichClass = this
+ def getName(): String = self.Name
+ def getComponentType(): Class[_] = self.GetElementType
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichDouble.scala b/src/dotnet-library/scala/runtime/RichDouble.scala
new file mode 100644
index 0000000000..6f22e8c836
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichDouble.scala
@@ -0,0 +1,52 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichDouble(x: Double) extends Proxy with Ordered[Double] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Double].compare
+ def compare(y: Double): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def min(y: Double): Double = Math.min(x, y)
+ def max(y: Double): Double = Math.max(x, y)
+ def abs: Double = Math.abs(x)
+
+ def round: Long = Math.round(x)
+ def ceil: Double = Math.ceil(x)
+ def floor: Double = Math.floor(x)
+
+ /** Converts an angle measured in degrees to an approximately equivalent
+ * angle measured in radians.
+ *
+ * @param x an angle, in degrees
+ * @return the measurement of the angle <code>x</code> in radians.
+ */
+ def toRadians: Double = Math.toRadians(x)
+
+ /** Converts an angle measured in radians to an approximately equivalent
+ * angle measured in degrees.
+ *
+ * @param x angle, in radians
+ * @return the measurement of the angle <code>x</code> in degrees.
+ */
+ def toDegrees: Double = Math.toDegrees(x)
+
+ def isNaN: Boolean = System.Double.IsNaN(x)
+ def isInfinity: Boolean = System.Double.IsInfinity(x)
+ def isPosInfinity: Boolean = System.Double.IsPositiveInfinity(x)
+ def isNegInfinity: Boolean = System.Double.IsNegativeInfinity(x)
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichException.scala b/src/dotnet-library/scala/runtime/RichException.scala
new file mode 100644
index 0000000000..d08e2e0edf
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichException.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichException(exc: System.Exception) {
+
+ def printStackTrace() = System.Console.WriteLine(exc.StackTrace)
+ def getMessage() = exc.Message
+ def getStackTraceString: String = exc.StackTrace
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichFloat.scala b/src/dotnet-library/scala/runtime/RichFloat.scala
new file mode 100644
index 0000000000..5f8849c1a3
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichFloat.scala
@@ -0,0 +1,54 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef._
+
+final class RichFloat(x: Float) extends Proxy with Ordered[Float] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Float].compare
+ def compare (y: Float): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def min(y: Float) = Math.min(x, y)
+ def max(y: Float) = Math.max(x, y)
+ def abs: Float = Math.abs(x)
+
+ def round: Int = Math.round(x)
+ def ceil: Float = Math.ceil(x).toFloat
+ def floor: Float = Math.floor(x).toFloat
+
+ /** Converts an angle measured in degrees to an approximately equivalent
+ * angle measured in radians.
+ *
+ * @param x an angle, in degrees
+ * @return the measurement of the angle <code>x</code> in radians.
+ */
+ def toRadians: Float = Math.toRadians(x).toFloat
+
+ /** Converts an angle measured in radians to an approximately equivalent
+ * angle measured in degrees.
+ *
+ * @param x angle, in radians
+ * @return the measurement of the angle <code>x</code> in degrees.
+ */
+ def toDegrees: Float = Math.toDegrees(x).toFloat
+
+ def isNaN: Boolean = System.Single.IsNaN(x)
+ def isInfinity: Boolean = System.Single.IsInfinity(x)
+ def isPosInfinity: Boolean = System.Single.IsPositiveInfinity(x)
+ def isNegInfinity: Boolean = System.Single.IsNegativeInfinity(x)
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichInt.scala b/src/dotnet-library/scala/runtime/RichInt.scala
new file mode 100644
index 0000000000..fc5080f9b3
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichInt.scala
@@ -0,0 +1,39 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichInt(start: Int) extends Proxy with Ordered[Int] {
+
+ // Proxy
+ def self: Any = start
+
+ // Ordered[Int]
+ def compare(that: Int): Int = if (start < that) -1 else if (start > that) 1 else 0
+
+ /** See <code>Iterator.range</code>. */
+ def until(end: Int): Range = new Range(start, end, 1)
+
+ /** See <code>Iterator.range</code>. */
+ def until(end: Int, step: Int): Range = new Range(start, end, step)
+
+ /** like <code>until</code>, but includes the last index */
+ def to(end: Int) = new Range.Inclusive(start, end, 1)
+
+ def min(that: Int): Int = if (start < that) start else that
+ def max(that: Int): Int = if (start > that) start else that
+ def abs: Int = if (start < 0) -start else start
+
+ def toBinaryString: String = System.Convert.ToString(start, 2)
+ def toHexString: String = System.Convert.ToString(start, 16)
+ def toOctalString: String = System.Convert.ToString(start, 8)
+}
diff --git a/src/dotnet-library/scala/runtime/RichLong.scala b/src/dotnet-library/scala/runtime/RichLong.scala
new file mode 100644
index 0000000000..743b24a79f
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichLong.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichLong(x: Long) extends Proxy with Ordered[Long] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Long].compare
+ def compare(y: Long): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def min(y: Long): Long = if (x < y) x else y
+ def max(y: Long): Long = if (x > y) x else y
+ def abs: Long = if (x < 0) -x else x
+
+ def toBinaryString: String = System.Convert.ToString(x, 2)
+ def toHexString: String = System.Convert.ToString(x, 16)
+ def toOctalString: String = System.Convert.ToString(x, 8)
+}
diff --git a/src/dotnet-library/scala/runtime/RichString.scala b/src/dotnet-library/scala/runtime/RichString.scala
new file mode 100644
index 0000000000..d94f7430c0
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichString.scala
@@ -0,0 +1,196 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef._
+
+final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char] with Ordered[String] {
+ override def apply(n: Int) = self charAt n
+ override def length = self.length
+ override def toString = self
+ override def mkString = self
+
+ override def slice(from: Int, until: Int): RichString = {
+ val len = self.length
+ new RichString(
+ if (from >= until || from >= len)
+ ""
+ else {
+ val from0 = if (from < 0) 0 else from
+ val until0 = if (until > len) len else until
+ self.substring(from0, until0)
+ }
+ )
+ }
+
+ //override def ++ [B >: A](that: Iterable[B]): Seq[B] = {
+ override def ++[B >: Char](that: Iterable[B]): RandomAccessSeq[B] = that match {
+ case that: RichString => new RichString(self + that.self)
+ case that => super.++(that)
+ }
+
+ override def take(until: Int): RichString = slice(0, until)
+
+ override def drop(from: Int): RichString = slice(from, self.length)
+
+ override def startsWith[B](that: Seq[B]) = that match {
+ case that: RichString => self startsWith that.self
+ case that => super.startsWith(that)
+ }
+
+ override def endsWith[B](that: Seq[B]) = that match {
+ case that: RichString => self endsWith that.self
+ case that => super.endsWith(that)
+ }
+
+ override def indexOf[B](that: Seq[B]) = that match {
+ case that: RichString => self indexOf that.self
+ case that => super.indexOf(that)
+ }
+
+ override def containsSlice[B](that: Seq[B]) = that match {
+ case that: RichString => self contains that.self
+ case that => super.containsSlice(that)
+ }
+
+ override def reverse: RichString = {
+ val buf = new StringBuilder
+ var i = self.length - 1
+ while (i >= 0) {
+ buf append (self charAt i)
+ i -= 1
+ }
+ new RichString(buf.toString)
+ }
+
+ override def compare(other: String) = self compareTo other
+
+ private final val LF: Char = 0x0A
+ private final val FF: Char = 0x0C
+ private final val CR: Char = 0x0D
+ private final val SU: Char = 0x1A
+
+ private def isLineBreak(c: Char) = c == LF || c == FF
+
+ /** <p>
+ * Strip trailing line end character from this string if it has one.
+ * A line end character is one of
+ * </p>
+ * <ul style="list-style-type: none;">
+ * <li>LF - line feed (0x0A hex)</li>
+ * <li>FF - form feed (0x0C hex)</li>
+ * </ul>
+ * <p>
+ * If a line feed character LF is preceded by a carriage return CR
+ * (0x0D hex), the CR character is also stripped (Windows convention).
+ * </p>
+ */
+ def stripLineEnd: String = {
+ val len = self.length
+ if (len == 0) self
+ else {
+ val last = apply(len - 1)
+ if (isLineBreak(last))
+ self.substring(0, if (last == LF && len >= 2 && apply(len - 2) == CR) len - 2 else len - 1)
+ else
+ self
+ }
+ }
+
+ /** <p>
+ * Return all lines in this string in an iterator, including trailing
+ * line end characters.
+ * </p>
+ * <p>
+ * The number of strings returned is one greater than the number of line
+ * end characters in this string. For an empty string, a single empty
+ * line is returned. A line end character is one of
+ * </p>
+ * <ul style="list-style-type: none;">
+ * <li>LF - line feed (0x0A hex)</li>
+ * <li>FF - form feed (0x0C hex)</li>
+ * </ul>
+ */
+ def linesWithSeparators = new Iterator[String] {
+ val len = self.length
+ var index = 0
+ def hasNext: Boolean = index < len
+ def next(): String = {
+ if (index >= len) throw new NoSuchElementException("next on empty iterator")
+ val start = index
+ while (index < len && !isLineBreak(apply(index))) index += 1
+ index += 1
+ self.substring(start, index min len)
+ }
+ }
+
+ /** Return all lines in this string in an iterator, excluding trailing line
+ * end characters, i.e. apply <code>.stripLineEnd</code> to all lines
+ * returned by <code>linesWithSeparators</code>.
+ */
+ def lines: Iterator[String] =
+ linesWithSeparators map (line => new RichString(line).stripLineEnd)
+
+ /** Returns this string with first character converted to upper case */
+ def capitalize: String =
+ if (self == null) null
+ else if (self.length == 0) ""
+ else {
+ val chars = self.toCharArray
+ chars(0) = chars(0).toUpperCase
+ new String(chars)
+ }
+
+ /** <p>
+ * For every line in this string:
+ * </p>
+ * <blockquote>
+ * Strip a leading prefix consisting of blanks or control characters
+ * followed by <code>marginChar</code> from the line.
+ * </blockquote>
+ */
+ def stripMargin(marginChar: Char): String = {
+ val buf = new StringBuilder
+ for (line <- linesWithSeparators) {
+ val len = line.length
+ var index = 0
+ while (index < len && line.charAt(index) <= ' ') index += 1
+ buf append
+ (if (index < len && line.charAt(index) == marginChar) line.substring(index + 1) else line)
+ }
+ buf.toString
+ }
+
+ /** <p>
+ * For every line in this string:
+ * </p>
+ * <blockquote>
+ * Strip a leading prefix consisting of blanks or control characters
+ * followed by <code>|</code> from the line.
+ * </blockquote>
+ */
+ def stripMargin: String = stripMargin('|')
+
+ def split(separator: Char): Array[String] = self.Split(Array(separator))
+
+ def split(separators: Array[Char]): Array[String] = self.Split(separators)
+
+ def toBoolean: Boolean = System.Boolean.Parse(self)
+ def toByte: Byte = System.Byte.Parse(self)
+ def toShort: Short = System.Int16.Parse(self)
+ def toInt: Int = System.Int32.Parse(self)
+ def toLong: Long = System.Int64.Parse(self)
+ def toFloat: Float = System.Single.Parse(self)
+ def toDouble: Double = System.Double.Parse(self)
+
+}
diff --git a/src/dotnet-library/scala/runtime/Runnable.cs b/src/dotnet-library/scala/runtime/Runnable.cs
new file mode 100644
index 0000000000..74ab3ea16a
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/Runnable.cs
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ public interface Runnable {
+ void run();
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/ShortRef.cs b/src/dotnet-library/scala/runtime/ShortRef.cs
new file mode 100644
index 0000000000..22f8f784e5
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ShortRef.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ [Serializable]
+ public class ShortRef {
+ public short elem;
+ public ShortRef(short elem) { this.elem = elem; }
+ override public string ToString() { return elem.ToString(); }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/StringAdd.scala b/src/dotnet-library/scala/runtime/StringAdd.scala
new file mode 100644
index 0000000000..439b2f7f65
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/StringAdd.scala
@@ -0,0 +1,28 @@
+/* *\
+** ________ ___ __ ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ |_| **
+** **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef._
+
+final class StringAdd(self: Any) {
+
+ def +(other: String) = self.toString + other
+
+ /** Formats string according to given <code>format</code> string.
+ * Format strings are as for <code>String.format</code> (@see
+ * http://msdn2.microsoft.com/en-us/library/system.string.format(VS.71).aspx
+ * and http://www.codeproject.com/books/0735616485.asp).
+ */
+ def formatted(format: String): String =
+ String.Format(format, Array(self.asInstanceOf[Object]))
+}
diff --git a/src/dotnet-library/scala/runtime/SymtabAttribute.cs b/src/dotnet-library/scala/runtime/SymtabAttribute.cs
new file mode 100644
index 0000000000..b5608fe208
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/SymtabAttribute.cs
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+namespace scala.runtime {
+
+ using System;
+
+ public class SymtabAttribute : Attribute {
+ public byte[] symtab;
+
+ public SymtabAttribute(byte[] symtab) { this.symtab = symtab; }
+ public SymtabAttribute() {}
+ }
+
+}
diff --git a/src/dotnet-library/scala/util/DynamicVariable.scala b/src/dotnet-library/scala/util/DynamicVariable.scala
new file mode 100644
index 0000000000..101ebe9573
--- /dev/null
+++ b/src/dotnet-library/scala/util/DynamicVariable.scala
@@ -0,0 +1,83 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util
+
+
+import Predef._
+import System.Threading.Thread
+import System.LocalDataStoreSlot
+
+/** <p>
+ * DynamicVariables provide a binding mechanism where the current
+ * value is found through <em>dynamic scope</em>, but where
+ * access to the variable itself is resolved through <em>static
+ * scope</em>.
+ * </p>
+ * <p>
+ * The current value can be retrieved with the
+ * <code>value</code> method. New values should be
+ * pushed using the <code>withValue</code> method.
+ * Values pushed via <code>withValue</code> only
+ * stay valid while the <code>withValue</code>'s
+ * <em>second</em> argument, a parameterless closure,
+ * executes. When the second argument finishes,
+ * the variable reverts to the previous value.
+ * </p>
+ * <p>
+ * Usage of <code>withValue</code> looks like this:
+ * </p>
+ * <blockquote><pre>
+ * someDynamicVariable.withValue(newValue) {
+ * // ... code called in here that calls value ...
+ * // ... will be given back the newValue ...
+ * }
+ * </pre></blockquote>
+ * <p>
+ * Each thread gets its own stack of bindings. When a
+ * new thread is created, the fluid gets a copy of
+ * the stack of bindings from the parent thread, and
+ * from then on the bindings for the new thread
+ * are independent of those for the original thread.
+ * </p>
+ *
+ * @author Lex Spoon
+ * @version 1.1, 2007-5-21
+ */
+class DynamicVariable[T](init: T) {
+ private val slot: LocalDataStoreSlot = Thread.AllocateDataSlot()
+ value = init
+
+ /** Retrieve the current value */
+ def value: T = Thread.GetData(slot).asInstanceOf[T]
+
+ /** Set the value of the fluid while executing the specified
+ * thunk.
+ *
+ * @param newval The value to which to set the fluid
+ * @param thunk The code to evaluate under the new setting
+ */
+ def withValue[S](newval: T)(thunk: =>S): S = {
+ val oldval = value
+ value = newval
+
+ try { thunk } finally {
+ value = oldval
+ }
+ }
+
+ /** Change the currently bound value, discarding the old value.
+ * Usually withValue() gives better semantics.
+ */
+ def value_=(newval: T) = { Thread.SetData(slot, newval.asInstanceOf[AnyRef]) }
+
+ override def toString: String = "DynamicVariable(" + value +")"
+}