diff options
author | Martin Odersky <odersky@gmail.com> | 2009-02-05 19:25:43 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-02-05 19:25:43 +0000 |
commit | 0ecacced0347e4e3b83989a274b9de53868a3a57 (patch) | |
tree | cf5bb351b3acef82ad88862bee320b9c6e32a4c3 /src/library/scalax/runtime | |
parent | 48355ee28a930f19000901d761f24ca44b324c1f (diff) | |
download | scala-0ecacced0347e4e3b83989a274b9de53868a3a57.tar.gz scala-0ecacced0347e4e3b83989a274b9de53868a3a57.tar.bz2 scala-0ecacced0347e4e3b83989a274b9de53868a3a57.zip |
added support for Strings, arrays, sets.
Diffstat (limited to 'src/library/scalax/runtime')
-rw-r--r-- | src/library/scalax/runtime/Boxed.scala | 4 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedAnyArray.scala | 239 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedArray.scala | 138 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedBooleanArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedByteArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedCharArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedDoubleArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedFloatArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedIntArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedLongArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/BoxedShortArray.scala | 25 | ||||
-rwxr-xr-x | src/library/scalax/runtime/ScalaRunTime.scala | 152 | ||||
-rw-r--r-- | src/library/scalax/runtime/StringVector.scala | 15 |
13 files changed, 737 insertions, 11 deletions
diff --git a/src/library/scalax/runtime/Boxed.scala b/src/library/scalax/runtime/Boxed.scala index ace7c73753..241b12e485 100644 --- a/src/library/scalax/runtime/Boxed.scala +++ b/src/library/scalax/runtime/Boxed.scala @@ -11,9 +11,7 @@ package scalax.runtime -trait Boxed[T] { - - def unbox: T +trait Boxed { } diff --git a/src/library/scalax/runtime/BoxedAnyArray.scala b/src/library/scalax/runtime/BoxedAnyArray.scala new file mode 100755 index 0000000000..6e14cafdfc --- /dev/null +++ b/src/library/scalax/runtime/BoxedAnyArray.scala @@ -0,0 +1,239 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedAnyArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +import compat.Platform + +/** + * Arrays created by <code>new Array[T](length)</code> where <code>T</code> + * is a type variable. + * + * @author Martin Odersky + */ +@serializable +final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { + + private var boxed = new Array[AnyRef](length) + private val hash = boxed.hashCode() + private var unboxed: AnyRef = null + private var elemClass: Class[_] = null + + def apply(index: Int): A = synchronized { + if (unboxed eq null) + boxed(index) + else if (elemClass eq classOf[Int]) + Int.box(unboxed.asInstanceOf[Array[Int]](index)) + else if (elemClass eq classOf[Double]) + Double.box(unboxed.asInstanceOf[Array[Double]](index)) + else if (elemClass eq classOf[Float]) + Float.box(unboxed.asInstanceOf[Array[Float]](index)) + else if (elemClass eq classOf[Long]) + Long.box(unboxed.asInstanceOf[Array[Long]](index)) + else if (elemClass eq classOf[Char]) + Char.box(unboxed.asInstanceOf[Array[Char]](index)) + else if (elemClass eq classOf[Byte]) + Byte.box(unboxed.asInstanceOf[Array[Byte]](index)) + else if (elemClass eq classOf[Short]) + Short.box(unboxed.asInstanceOf[Array[Short]](index)) + else if (elemClass eq classOf[Boolean]) + Boolean.box(unboxed.asInstanceOf[Array[Boolean]](index)) + else + unboxed.asInstanceOf[Array[AnyRef]](index) + }.asInstanceOf[A] + + def update(index: Int, _elem: A): Unit = synchronized { + val elem = _elem.asInstanceOf[AnyRef] + if (unboxed eq null) + boxed(index) = elem + else if (elemClass eq classOf[Int]) + unboxed.asInstanceOf[Array[Int]](index) = Int.unbox(elem) + else if (elemClass eq classOf[Double]) + unboxed.asInstanceOf[Array[Double]](index) = Double.unbox(elem) + else if (elemClass eq classOf[Float]) + unboxed.asInstanceOf[Array[Float]](index) = Float.unbox(elem) + else if (elemClass eq classOf[Long]) + unboxed.asInstanceOf[Array[Long]](index) = Long.unbox(elem) + else if (elemClass eq classOf[Char]) + unboxed.asInstanceOf[Array[Char]](index) = Char.unbox(elem) + else if (elemClass eq classOf[Byte]) + unboxed.asInstanceOf[Array[Byte]](index) = Byte.unbox(elem) + else if (elemClass eq classOf[Short]) + unboxed.asInstanceOf[Array[Short]](index) = Short.unbox(elem) + else if (elemClass eq classOf[Boolean]) + unboxed.asInstanceOf[Array[Boolean]](index) = Boolean.unbox(elem) + else + unboxed.asInstanceOf[Array[AnyRef]](index) = elem + } + + def unbox(elemClass: Class[_]): AnyRef = synchronized { + if (unboxed eq null) { + this.elemClass = elemClass; + if (elemClass eq classOf[Int]) { + val newvalue = new Array[Int](length) + var i = 0 + while (i < length) { + newvalue(i) = Int.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue + } else if (elemClass eq classOf[Double]) { + val newvalue = new Array[Double](length) + var i = 0 + while (i < length) { + newvalue(i) = Double.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Float]) { + val newvalue = new Array[Float](length) + var i = 0 + while (i < length) { + newvalue(i) = Float.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Long]) { + val newvalue = new Array[Long](length) + var i = 0 + while (i < length) { + newvalue(i) = Long.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Char]) { + val newvalue = new Array[Char](length) + var i = 0 + while (i < length) { + newvalue(i) = Char.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue + } else if (elemClass eq classOf[Byte]) { + val newvalue = new Array[Byte](length) + var i = 0 + while (i < length) { + newvalue(i) = Byte.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Short]) { + val newvalue = new Array[Short](length) + var i = 0 + while (i < length) { + newvalue(i) = Short.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Boolean]) { + val newvalue = new Array[Boolean](length) + var i = 0 + while (i < length) { + newvalue(i) = Boolean.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass == classOf[AnyRef]) { + unboxed = boxed + } else { + unboxed = Platform.createArray(elemClass, length) + if (elemClass.isArray) { + var i = 0 + while (i < length) { + boxed(i) match { + case ba: BoxedArray[_] => boxed(i) = ba.unbox(elemClass.getComponentType()) + case _ => + } + i += 1 + } + } + Platform.arraycopy(boxed, 0, unboxed, 0, length) + } + boxed = null + } + unboxed + } + + override def equals(other: Any): Boolean = + other.isInstanceOf[BoxedAnyArray[_]] && (this eq (other.asInstanceOf[BoxedAnyArray[_]])) || + (if (unboxed eq null) boxed == other else unboxed == other) + + override def hashCode(): Int = hash + + def value: AnyRef = { + if (unboxed eq null) throw new NotDefinedError("BoxedAnyArray.value") + unboxed + } + + private def adapt(other: AnyRef): AnyRef = + if (this.unboxed eq null) + other match { + case that: BoxedAnyArray[_] => + if (that.unboxed eq null) { + that.boxed + } else { + if (ScalaRunTime.isValueClass(that.elemClass)) unbox(that.elemClass); + that.unboxed + } + case that: BoxedArray[_] => + adapt(that.value) + case that: Array[Int] => + unbox(classOf[Int]); that + case that: Array[Double] => + unbox(classOf[Double]); that + case that: Array[Float] => + unbox(classOf[Float]); that + case that: Array[Long] => + unbox(classOf[Long]); that + case that: Array[Char] => + unbox(classOf[Char]); that + case that: Array[Short] => + unbox(classOf[Short]); that + case that: Array[Byte] => + unbox(classOf[Byte]); that + case that: Array[Boolean] => + unbox(classOf[Boolean]); that + case _ => + other + } + else + other match { + case that: BoxedAnyArray[_] => + if (that.unboxed ne null) that.unboxed + else if (ScalaRunTime.isValueClass(this.elemClass)) that.unbox(this.elemClass) + else that.boxed + case that: BoxedArray[_] => + adapt(that.value) + case _ => + other + } + + override def copyFrom(src: AnyRef, from: Int, to: Int, len: Int) { + val src1 = adapt(src) + Array.copy(src1, from, if (unboxed ne null) unboxed else boxed, to, len) + } + + override def copyTo(from: Int, dest: AnyRef, to: Int, len: Int) { + var dest1 = adapt(dest) + Array.copy(if (unboxed ne null) unboxed else boxed, from, dest1, to, len) + } + + final override def filter(p: A => Boolean): BoxedArray[A] = { + val (len, include) = countAndMemo(p) + val result = new BoxedAnyArray[A](len) + var i, j = 0 + while (j < len) { + if (include(i)) { result(j) = this(i); j += 1 } + i += 1 + } + result + } +} diff --git a/src/library/scalax/runtime/BoxedArray.scala b/src/library/scalax/runtime/BoxedArray.scala new file mode 100755 index 0000000000..388d652882 --- /dev/null +++ b/src/library/scalax/runtime/BoxedArray.scala @@ -0,0 +1,138 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +import Predef._ +import collection.mutable.{Vector, ArrayBuffer} +import collection.generic._ + +/** + * <p>A class representing <code>Array[T]</code></p> + * + * @author Martin Odersky, Stephane Micheloud + * @version 1.0 + */ +abstract class BoxedArray[A] extends Vector[A] with mutable.VectorTemplate[BoxedArray, A] with Boxed { + + /** The length of the array */ + def length: Int + + /** The element at given index */ + def apply(index: Int): A + + /** Update element at given index */ + def update(index: Int, elem: A): Unit + + /** Creates new builder for this collection ==> move to subclasses + * + * */ + def newBuilder[B] = new ArrayBuffer[B].mapResult[BoxedArray] { // !!! Adriaan: can't drop [BoxedArray] here + _.toArray.asInstanceOf[BoxedArray[B]] + } + + /** Convert to Java array. + * @param elemTag Either one of the tags ".N" where N is the name of a primitive type + * (@see ScalaRunTime), or a full class name. + */ + def unbox(elemClass: Class[_]): AnyRef + + /** The underlying array value + */ + def value: AnyRef + + def copyFrom(src: AnyRef, from: Int, to: Int, len: Int): Unit = + Array.copy(src, from, value, to, len) + + def copyTo(from: Int, dest: AnyRef, to: Int, len: Int): Unit = { + Array.copy(value, from, dest, to, len) + } + + override def equals(other: Any) = + (value == other) || + other.isInstanceOf[BoxedArray[_]] && (value == other.asInstanceOf[BoxedArray[_]].value) + + override def hashCode(): Int = value.hashCode() + + /** Fills the given array <code>xs</code> with the elements of + * this sequence starting at position <code>start</code>. + * + * @param xs the array to fill. + * @param start starting index. + * @pre the array must be large enough to hold all elements. + */ + override def copyToArray[B](xs: Array[B], start: Int, len: Int): Unit = + copyTo(0, xs, start, len) + + final def deepToString() = deepMkString(stringPrefix + "(", ", ", ")") + + final def deepMkString(start: String, sep: String, end: String): String = { + def _deepToString(x: Any) = x match { + case a: AnyRef if ScalaRunTime.isArray(a) => + ScalaRunTime.boxArray(a).deepMkString(start, sep, end) + case _ => + ScalaRunTime.stringOf(x) + } + val buf = new StringBuilder() + buf.append(start) + val elems = elements + if (elems.hasNext) buf.append(_deepToString(elems.next)) + while (elems.hasNext) { + buf.append(sep); buf.append(_deepToString(elems.next)) + } + buf.append(end) + buf.toString + } + + final def deepMkString(sep: String): String = this.deepMkString("", sep, "") + + final def deepEquals(that: Any): Boolean = { + def _deepEquals(x1: Any, x2: Any) = (x1, x2) match { + case (a1: BoxedArray[_], a2: BoxedArray[_]) => + _sameElements(a1, a2) + case (a1: AnyRef, a2: AnyRef) + if ScalaRunTime.isArray(a1) && ScalaRunTime.isArray(a2) => + _sameElements(ScalaRunTime.boxArray(a1), ScalaRunTime.boxArray(a2)) + case _ => + x1.equals(x2) + } + def _sameElements(a1: BoxedArray[_], a2: BoxedArray[_]): Boolean = { + val it1 = a1.elements + val it2 = a2.elements + var res = true + while (res && it1.hasNext && it2.hasNext) + res = _deepEquals(it1.next, it2.next) + !it1.hasNext && !it2.hasNext && res + } + that match { + case a: BoxedArray[_] => + _sameElements(this, a) + case a: AnyRef if ScalaRunTime.isArray(a) => + _sameElements(this, ScalaRunTime.boxArray(a)) + case _ => + false + } + } + + override final def stringPrefix: String = "Array" + + protected def countAndMemo(p: A => Boolean): (Int, Array[Boolean]) = { + val len = length + val memo = new Array[Boolean](len) + var count = 0 + var i = 0 + while (i < len) { + if (p(this(i))) { memo(i) = true; count += 1 } + i += 1 + } + (count, memo) + } +} diff --git a/src/library/scalax/runtime/BoxedBooleanArray.scala b/src/library/scalax/runtime/BoxedBooleanArray.scala new file mode 100755 index 0000000000..1dc136a50f --- /dev/null +++ b/src/library/scalax/runtime/BoxedBooleanArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedBooleanArray(val value: Array[Boolean]) extends BoxedArray[Boolean] { + + def length: Int = value.length + + def apply(index: Int): Boolean = value(index) + + def update(index: Int, elem: Boolean) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedByteArray.scala b/src/library/scalax/runtime/BoxedByteArray.scala new file mode 100755 index 0000000000..f42dbdda38 --- /dev/null +++ b/src/library/scalax/runtime/BoxedByteArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedByteArray(val value: Array[Byte]) extends BoxedArray[Byte] { + + def length: Int = value.length + + def apply(index: Int): Byte = value(index) + + def update(index: Int, elem: Byte) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedCharArray.scala b/src/library/scalax/runtime/BoxedCharArray.scala new file mode 100755 index 0000000000..c6f19d26e0 --- /dev/null +++ b/src/library/scalax/runtime/BoxedCharArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedCharArray(val value: Array[Char]) extends BoxedArray[Char] { + + def length: Int = value.length + + def apply(index: Int): Char = value(index) + + def update(index: Int, elem: Char) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedDoubleArray.scala b/src/library/scalax/runtime/BoxedDoubleArray.scala new file mode 100755 index 0000000000..16fc3e1056 --- /dev/null +++ b/src/library/scalax/runtime/BoxedDoubleArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedDoubleArray(val value: Array[Double]) extends BoxedArray[Double] { + + def length: Int = value.length + + def apply(index: Int): Double = value(index) + + def update(index: Int, elem: Double) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedFloatArray.scala b/src/library/scalax/runtime/BoxedFloatArray.scala new file mode 100755 index 0000000000..d10f16f6f6 --- /dev/null +++ b/src/library/scalax/runtime/BoxedFloatArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedFloatArray(val value: Array[Float]) extends BoxedArray[Float] { + + def length: Int = value.length + + def apply(index: Int): Float = value(index) + + def update(index: Int, elem: Float) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedIntArray.scala b/src/library/scalax/runtime/BoxedIntArray.scala new file mode 100755 index 0000000000..78a033190a --- /dev/null +++ b/src/library/scalax/runtime/BoxedIntArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedIntArray(val value: Array[Int]) extends BoxedArray[Int] { + + def length: Int = value.length + + def apply(index: Int): Int = value(index) + + def update(index: Int, elem: Int) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedLongArray.scala b/src/library/scalax/runtime/BoxedLongArray.scala new file mode 100755 index 0000000000..86816d6638 --- /dev/null +++ b/src/library/scalax/runtime/BoxedLongArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedLongArray(val value: Array[Long]) extends BoxedArray[Long] { + + def length: Int = value.length + + def apply(index: Int): Long = value(index) + + def update(index: Int, elem: Long) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedShortArray.scala b/src/library/scalax/runtime/BoxedShortArray.scala new file mode 100755 index 0000000000..6d5c82e7ba --- /dev/null +++ b/src/library/scalax/runtime/BoxedShortArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedShortArray(val value: Array[Short]) extends BoxedArray[Short] { + + def length: Int = value.length + + def apply(index: Int): Short = value(index) + + def update(index: Int, elem: Short) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/ScalaRunTime.scala b/src/library/scalax/runtime/ScalaRunTime.scala new file mode 100755 index 0000000000..0c8416be89 --- /dev/null +++ b/src/library/scalax/runtime/ScalaRunTime.scala @@ -0,0 +1,152 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: ScalaRunTime.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +/* The object <code>ScalaRunTime</code> provides ... + */ +object ScalaRunTime { + + def isArray(x: AnyRef): Boolean = (x != null && x.getClass.isArray) || (x != null && x.isInstanceOf[BoxedArray[_]]) + def isValueClass(clazz: Class[_]) = clazz.isPrimitive() + + def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] = { + val array = new Array[A](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def checkInitialized[T <: AnyRef](x: T): T = + if (x == null) throw new UninitializedError else x + + abstract class Try[a] { + def Catch[b >: a](handler: PartialFunction[Throwable, b]): b + def Finally(handler: Unit): a + } + + def Try[a](block: => a): Try[a] = new Try[a] with Runnable { + var result: a = _ + var exception: Throwable = scala.runtime.ExceptionHandling.tryCatch(this) + + def run(): Unit = result = block + + def Catch[b >: a](handler: PartialFunction[Throwable, b]): b = + if (exception eq null) + result.asInstanceOf[b] + // !!! else if (exception is LocalReturn) + // !!! // ... + else if (handler isDefinedAt exception) + handler(exception) + else + throw exception + + def Finally(handler: Unit): a = + if (exception eq null) + result.asInstanceOf[a] + else + throw exception + } + + def caseFields(x: Product): List[Any] = { + val arity = x.productArity + def fields(from: Int): List[Any] = + if (from == arity) List() + else x.productElement(from) :: fields(from + 1) + fields(0) + } + + def _toString(x: Product): String = + caseFields(x).mkString(x.productPrefix + "(", ",", ")") + + def _hashCode(x: Product): Int = { + var code = x.getClass().hashCode() + val arr = x.productArity + var i = 0 + while (i < arr) { + val elem = x.productElement(i) + code = code * 41 + (if (elem == null) 0 else elem.hashCode()) + i += 1 + } + code + } + + def _equals(x: Product, y: Any): Boolean = y match { + case y1: Product if x.productArity == y1.productArity => + val arity = x.productArity + var i = 0 + while (i < arity && x.productElement(i) == y1.productElement(i)) + i += 1 + i == arity + case _ => + false + } + + def _equalsWithVarArgs(x: Product, y: Any): Boolean = y match { + case y1: Product if x.productArity == y1.productArity => + val arity = x.productArity + var i = 0 + while (i < arity - 1 && x.productElement(i) == y1.productElement(i)) + i += 1 + i == arity - 1 && { + x.productElement(i) match { + case xs: Seq[_] => + y1.productElement(i) match { + case ys: Seq[_] => xs sameElements ys + } + } + } + case _ => + false + } + + //def checkDefined[T >: Null](x: T): T = + // if (x == null) throw new UndefinedException else x + + def Seq[a](xs: a*): Seq[a] = null // interpreted specially by new backend. + + def arrayValue[A](x: BoxedArray[A], elemClass: Class[_]): AnyRef = + if (x eq null) null else x.unbox(elemClass) + + def boxArray(value: AnyRef): BoxedArray[_] = value match { + case x: Array[Byte] => new BoxedByteArray(x) +/* + case x: Array[Short] => new BoxedShortArray(x) + case x: Array[Char] => new BoxedCharArray(x) + case x: Array[Int] => new BoxedIntArray(x) + case x: Array[Long] => new BoxedLongArray(x) + case x: Array[Float] => new BoxedFloatArray(x) + case x: Array[Double] => new BoxedDoubleArray(x) + case x: Array[Boolean] => new BoxedBooleanArray(x) + case x: Array[AnyRef] => new BoxedObjectArray(x) +*/ + case x: BoxedArray[_] => x + } + + /** Given any Scala value, convert it to a String. + * + * The primary motivation for this method is to provide a means for + * correctly obtaining a String representation of a value, while + * avoiding the pitfalls of naïvely calling toString on said value. + * In particular, it addresses the fact that (a) toString cannot be + * called on null and (b) depending on the apparent type of an + * array, toString may or may not print it in a human-readable form. + * + * @param arg the value to stringify + * @return a string representation of <code>arg</code> + * + */ + def stringOf(arg : Any): String = arg match { + case null => "null" + case (arg : AnyRef) if isArray(arg) => boxArray(arg).deepToString + case arg => arg.toString + } +} diff --git a/src/library/scalax/runtime/StringVector.scala b/src/library/scalax/runtime/StringVector.scala index ee7a805449..c12243bed7 100644 --- a/src/library/scalax/runtime/StringVector.scala +++ b/src/library/scalax/runtime/StringVector.scala @@ -12,7 +12,7 @@ package scalax.runtime import collection.immutable.Vector -import collection.mutable.{ArrayBuffer, BuilderProxy} +import collection.mutable.ArrayBuffer import collection.generic.covariant.VectorTemplate object StringVector { @@ -22,7 +22,7 @@ object StringVector { } @cloneable -abstract class StringVector[+A] extends VectorTemplate[StringVector, A] with Vector[A] with Boxed[String] { +abstract class StringVector[+A] extends VectorTemplate[StringVector, A] with Vector[A] { /** The length of the string */ def length: Int @@ -31,12 +31,11 @@ abstract class StringVector[+A] extends VectorTemplate[StringVector, A] with Vec def apply(idx: Int): A /** Creates new builder for this collection */ - def newBuilder[B] = new BuilderProxy[StringVector, B] { - val self = new ArrayBuffer[B] - def result: StringVector[B] = new StringVector[B] { - def length = self.length - def apply(n: Int) = self.apply(n) - override def foreach(f: B => Unit) = self.foreach(f) + def newBuilder[B] = new ArrayBuffer[B].mapResult[StringVector] { // !!! Adriaan: can't drop [StringVector] here + buf => new StringVector[B] { + def length = buf.length + def apply(n: Int) = buf.apply(n) + override def foreach(f: B => Unit) = buf.foreach(f) } } |