diff options
author | Geoffrey Washburn <geoffrey.washburn@epfl.ch> | 2008-04-07 12:15:54 +0000 |
---|---|---|
committer | Geoffrey Washburn <geoffrey.washburn@epfl.ch> | 2008-04-07 12:15:54 +0000 |
commit | 48fdb8620aeb3253f0048667044b39301c1d77c8 (patch) | |
tree | 1677e938deef28b99a0d0cd2022c34f05c906d92 /src/dotnet-library | |
parent | 09d3a7bb5b1a96300b78e7f1b38f135c5ab80d20 (diff) | |
download | scala-48fdb8620aeb3253f0048667044b39301c1d77c8.tar.gz scala-48fdb8620aeb3253f0048667044b39301c1d77c8.tar.bz2 scala-48fdb8620aeb3253f0048667044b39301c1d77c8.zip |
New reorg plan
Diffstat (limited to 'src/dotnet-library')
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>) && + * ... && 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 && (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><(e1: a, e2: a) => 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><(e1: a, e2: a) => Boolean</code>. + * @ex <pre> + * List("Steve", "Tom", "John", "Bob") + * .sort((e1, e2) => (e1 compareTo e2) < 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 > 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 +")" +} |