/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
// $Id$
package scala.runtime
import scala.reflect.ClassManifest
import scala.collection.Seq
import scala.collection.mutable._
import scala.collection.immutable.{List, Stream, Nil, ::}
/* The object ScalaRunTime
provides ...
*/
object ScalaRunTime {
def isArray(x: AnyRef): Boolean = // !!! remove once newarrays
x != null && (x.getClass.isArray || x.isInstanceOf[BoxedArray[_]])
def isArray(x: Any, atLevel: Int): Boolean =
x != null && isArrayClass(x.asInstanceOf[AnyRef].getClass, atLevel)
private def isArrayClass(clazz: Class[_], atLevel: Int): Boolean =
clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))
def isValueClass(clazz: Class[_]) = clazz.isPrimitive()
// todo: remove?
def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] =
throw new Error(" not implemented: forceBoxedArray")
/** Retrieve generic array element */
def array_apply(xs: AnyRef, idx: Int): Any = java.lang.reflect.Array.get(xs, idx)
/** update generic array element */
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = java.lang.reflect.Array.set(xs, idx, value)
/** Get generic array length */
def array_length(xs: AnyRef): Int = java.lang.reflect.Array.getLength(xs)
/** Convert a numeric value array to an object array.
* Needed to deal with vararg arguments of primtive types that are passed
* to a generic Java vararg parameter T ...
*/
def toObjectArray(src: AnyRef): Array[Object] = {
val length = array_length(src)
val dest = new Array[Object](length)
for (i <- 0 until length)
array_update(dest, i, array_apply(src, i))
dest
}
def toArray[T](xs: scala.collection.Seq[T]) = {
val arr = new Array[AnyRef](xs.length)
var i = 0
for (x <- xs) arr(i) = x.asInstanceOf[AnyRef]
arr
}
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 = 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 _hashCodeJenkins(x: Product): Int =
scala.util.JenkinsHash.hashSeq(x.productPrefix.toSeq ++ x.productIterator.toSeq)
def _hashCode(x: Product): Int = {
var code = x.productPrefix.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)
/** Temporary method to go to new array representation
* !!! can be reomved once bootstrap is complete !!!
*/
def unboxedArray[A](x: AnyRef): AnyRef = x match {
case ba: BoxedArray[_] => ba.value
case _ => x
}
def boxArray(value: AnyRef): BoxedArray[_] = value match {
case x: Array[AnyRef] => new BoxedObjectArray(x, ClassManifest.classType(x.getClass.getComponentType))
case x: Array[Int] => new BoxedIntArray(x)
case x: Array[Double] => new BoxedDoubleArray(x)
case x: Array[Long] => new BoxedLongArray(x)
case x: Array[Float] => new BoxedFloatArray(x)
case x: Array[Char] => new BoxedCharArray(x)
case x: Array[Byte] => new BoxedByteArray(x)
case x: Array[Short] => new BoxedShortArray(x)
case x: Array[Boolean] => new BoxedBooleanArray(x)
case x: BoxedArray[_] => x
case null => null
}
/** 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 arg
*
*/
def stringOf(arg : Any): String = arg match {
case null => "null"
case arg: AnyRef if isArray(arg) =>
val d: collection.IndexedSeq[Any] = WrappedArray.make(arg).deep
d.toString
case arg: WrappedArray[_] => arg.deep.toString
case arg => arg.toString
}
}