aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/DottyPredef.scala14
-rw-r--r--src/dotty/runtime/vc/VCPrototype.scala486
-rw-r--r--src/dotty/tools/dotc/config/ScalaSettings.scala1
-rw-r--r--src/dotty/tools/dotc/transform/ValueClasses.scala1
-rw-r--r--src/scala/runtime/ScalaRunTime/ScalaRunTime.scala371
5 files changed, 873 insertions, 0 deletions
diff --git a/src/dotty/DottyPredef.scala b/src/dotty/DottyPredef.scala
index 4b68e4029..7c8098bd1 100644
--- a/src/dotty/DottyPredef.scala
+++ b/src/dotty/DottyPredef.scala
@@ -8,4 +8,18 @@ object DottyPredef {
/** implicits for ClassTag and TypeTag. Should be implemented with macros */
implicit def classTag[T]: ClassTag[T] = scala.Predef.???
implicit def typeTag[T]: TypeTag[T] = scala.Predef.???
+
+
+ /** ClassTags for final classes */
+ implicit val IntClassTag: ClassTag[Int] = ClassTag.Int
+ implicit val ByteClassTag: ClassTag[Byte] = ClassTag.Byte
+ implicit val ShortClassTag: ClassTag[Short] = ClassTag.Short
+ implicit val CharClassTag: ClassTag[Char] = ClassTag.Char
+ implicit val LongClassTag: ClassTag[Long] = ClassTag.Long
+ implicit val FloatClassTag: ClassTag[Float] = ClassTag.Float
+ implicit val DoubleClassTag: ClassTag[Double] = ClassTag.Double
+ implicit val BooleanClassTag: ClassTag[Boolean] = ClassTag.Boolean
+ implicit val UnitClassTag: ClassTag[Unit] = ClassTag.Unit
+ implicit val NullClassTag: ClassTag[Null] = ClassTag.Null
+ implicit val NothingClassTag: ClassTag[Nothing] = ClassTag.Nothing
}
diff --git a/src/dotty/runtime/vc/VCPrototype.scala b/src/dotty/runtime/vc/VCPrototype.scala
new file mode 100644
index 000000000..0a3abe5a2
--- /dev/null
+++ b/src/dotty/runtime/vc/VCPrototype.scala
@@ -0,0 +1,486 @@
+package dotty.runtime.vc
+
+import scala.reflect.ClassTag
+
+abstract class VCPrototype {
+}
+
+
+abstract class VCArrayPrototype[T <: VCPrototype] extends Object with Cloneable {
+ def apply(idx: Int): Object
+ def update(idx: Int, el: T): Unit
+ def length: Int
+ override def clone: Object = super.clone()
+}
+
+
+abstract class VCFloatPrototype(val underlying: Float) extends VCPrototype {}
+
+abstract class VCFloatCasePrototype(underlying: Float) extends VCFloatPrototype(underlying) with Product1[Float] {
+
+ final def _1: Float = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCFloatCompanion[T <: VCFloatPrototype] extends ClassTag[T] {
+ def box(underlying: Float): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCFloatArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Float) = underlying
+ final def hashCode$extension(underlying: Float) = underlying.hashCode()
+ final def toString$extension(underlying: Float) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Float): String
+}
+
+final class VCFloatArray[T <: VCFloatPrototype] private (val arr: Array[Float], val ct: VCFloatCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCFloatCompanion[T], sz: Int) =
+ this(new Array[Float](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+ def length: Int = arr.length
+
+ override def clone(): VCFloatArray[T] = {
+ new VCFloatArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+}
+
+
+abstract class VCObjectPrototype(val underlying: Object) extends VCPrototype {}
+
+abstract class VCObjectCasePrototype(underlying: Object) extends VCObjectPrototype(underlying) with Product1[Object] {
+
+ final def _1: Object = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCObjectCompanion[T <: VCObjectPrototype] extends ClassTag[T] {
+ def box(underlying: Object): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCObjectArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Object) = underlying
+ final def hashCode$extension(underlying: Object) = underlying.hashCode()
+ final def toString$extension(underlying: Object) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Object): String
+}
+
+final class VCObjectArray[T <: VCObjectPrototype] private (val arr: Array[Object], val ct: VCObjectCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCObjectCompanion[T], sz: Int) =
+ this(new Array[Object](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+
+ def length: Int = arr.length
+
+ override def clone(): VCObjectArray[T] = {
+ new VCObjectArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+}
+
+
+abstract class VCShortPrototype(val underlying: Short) extends VCPrototype {}
+
+abstract class VCShortCasePrototype(underlying: Short) extends VCShortPrototype(underlying) with Product1[Short] {
+
+ final def _1: Short = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCShortCompanion[T <: VCShortPrototype] extends ClassTag[T] {
+ def box(underlying: Short): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCShortArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Short) = underlying
+ final def hashCode$extension(underlying: Short) = underlying.hashCode()
+ final def toString$extension(underlying: Short) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Short): String
+}
+
+final class VCShortArray[T <: VCShortPrototype] private (val arr: Array[Short], val ct: VCShortCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCShortCompanion[T], sz: Int) =
+ this(new Array[Short](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+
+ def length: Int = arr.length
+
+ override def clone(): VCShortArray[T] = {
+ new VCShortArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+
+}
+
+
+abstract class VCLongPrototype(val underlying: Long) extends VCPrototype {}
+
+abstract class VCLongCasePrototype(underlying: Long) extends VCLongPrototype(underlying) with Product1[Long] {
+
+ final def _1: Long = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCLongCompanion[T <: VCLongPrototype] extends ClassTag[T] {
+ def box(underlying: Long): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCLongArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Long) = underlying
+ final def hashCode$extension(underlying: Long) = underlying.hashCode()
+ final def toString$extension(underlying: Long) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Long): String
+}
+
+final class VCLongArray[T <: VCLongPrototype] private (val arr: Array[Long], val ct: VCLongCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCLongCompanion[T], sz: Int) =
+ this(new Array[Long](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+
+ def length: Int = arr.length
+
+ override def clone(): VCLongArray[T] = {
+ new VCLongArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+}
+
+
+abstract class VCIntPrototype(val underlying: Int) extends VCPrototype {}
+
+abstract class VCIntCasePrototype(underlying: Int) extends VCIntPrototype(underlying) with Product1[Int] {
+
+ final def _1: Int = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCIntCompanion[T <: VCIntPrototype] extends ClassTag[T] {
+ def box(underlying: Int): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCIntArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Int) = underlying
+ final def hashCode$extension(underlying: Int) = underlying.hashCode()
+ final def toString$extension(underlying: Int) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Int): String
+}
+
+final class VCIntArray[T <: VCIntPrototype] private (val arr: Array[Int], val ct: VCIntCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCIntCompanion[T], sz: Int) =
+ this(new Array[Int](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+ def length: Int = arr.length
+
+ override def clone(): VCIntArray[T] = {
+ new VCIntArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+}
+
+
+abstract class VCDoublePrototype(val underlying: Double) extends VCPrototype {}
+
+abstract class VCDoubleCasePrototype(underlying: Double) extends VCDoublePrototype(underlying) with Product1[Double] {
+
+ final def _1: Double = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCDoubleCompanion[T <: VCDoublePrototype] extends ClassTag[T] {
+ def box(underlying: Double): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCDoubleArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Double) = underlying
+ final def hashCode$extension(underlying: Double) = underlying.hashCode()
+ final def toString$extension(underlying: Double) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Double): String
+}
+
+final class VCDoubleArray[T <: VCDoublePrototype] private (val arr: Array[Double], val ct: VCDoubleCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCDoubleCompanion[T], sz: Int) =
+ this(new Array[Double](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+ def length: Int = arr.length
+
+ override def clone(): VCDoubleArray[T] = {
+ new VCDoubleArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+}
+
+
+abstract class VCBooleanPrototype(val underlying: Boolean) extends VCPrototype {}
+
+abstract class VCBooleanCasePrototype(underlying: Boolean) extends VCBooleanPrototype(underlying) with Product1[Boolean] {
+
+ final def _1: Boolean = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCBooleanCompanion[T <: VCBooleanPrototype] extends ClassTag[T] {
+ def box(underlying: Boolean): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCBooleanArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Boolean) = underlying
+ final def hashCode$extension(underlying: Boolean) = underlying.hashCode()
+ final def toString$extension(underlying: Boolean) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Boolean): String
+}
+
+final class VCBooleanArray[T <: VCBooleanPrototype] private (val arr: Array[Boolean], val ct: VCBooleanCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCBooleanCompanion[T], sz: Int) =
+ this(new Array[Boolean](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+
+ def length: Int = arr.length
+
+ override def clone(): VCBooleanArray[T] = {
+ new VCBooleanArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+}
+
+
+abstract class VCCharPrototype(val underlying: Char) extends VCPrototype {}
+
+abstract class VCCharCasePrototype(underlying: Char) extends VCCharPrototype(underlying) with Product1[Char] {
+
+ final def _1: Char = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+
+ // subclasses are expected to implement equals, productPrefix, and canEqual
+}
+
+abstract class VCCharCompanion[T <: VCCharPrototype] extends ClassTag[T] {
+ def box(underlying: Char): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCCharArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Char) = underlying
+ final def hashCode$extension(underlying: Char) = underlying.hashCode()
+ final def toString$extension(underlying: Char) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Char): String
+}
+
+final class VCCharArray[T <: VCCharPrototype] private (val arr: Array[Char], val ct: VCCharCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCCharCompanion[T], sz: Int) =
+ this(new Array[Char](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+ def length: Int = arr.length
+
+ override def clone(): VCCharArray[T] = {
+ new VCCharArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+}
+
+
+abstract class VCBytePrototype(val underlying: Byte) extends VCPrototype {}
+
+abstract class VCByteCasePrototype(underlying: Byte) extends VCBytePrototype(underlying) with Product1[Byte] {
+
+ final def _1: Byte = underlying
+
+ override final def hashCode(): Int = {
+ underlying.hashCode()
+ }
+
+ override final def toString: String = {
+ s"$productPrefix($underlying)"
+ }
+}
+
+abstract class VCByteCompanion[T <: VCBytePrototype] extends ClassTag[T] {
+ def box(underlying: Byte): T
+ final def unbox(boxed: T) = boxed.underlying
+
+ implicit def classTag: this.type = this
+ override def newArray(len: Int): Array[T] =
+ new VCByteArray(this, len).asInstanceOf[Array[T]]
+
+
+ final def _1$extension(underlying: Byte) = underlying
+ final def hashCode$extension(underlying: Byte) = underlying.hashCode()
+ final def toString$extension(underlying: Byte) = s"${productPrefix$extension(underlying)}($underlying)"
+ def productPrefix$extension(underlying: Byte): String
+}
+
+final class VCByteArray[T <: VCBytePrototype] private (val arr: Array[Byte], val ct: VCByteCompanion[T])
+ extends VCArrayPrototype[T] {
+ def this(ct: VCByteCompanion[T], sz: Int) =
+ this(new Array[Byte](sz), ct)
+
+ def apply(idx: Int) =
+ ct.box(arr(idx))
+ def update(idx: Int, elem: T) =
+ arr(idx) = ct.unbox(elem)
+ def length: Int = arr.length
+
+ override def clone(): VCByteArray[T] = {
+ new VCByteArray[T](arr.clone(), ct)
+ }
+
+ override def toString: String = {
+ "[" + ct.runtimeClass
+ }
+
+}
+
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala
index 2ad39c3c0..2ba907084 100644
--- a/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -88,6 +88,7 @@ class ScalaSettings extends Settings.SettingGroup {
val Xshowobj = StringSetting("-Xshow-object", "object", "Show internal representation of object.", "")
val showPhases = BooleanSetting("-Xshow-phases", "Print a synopsis of compiler phases.")
val sourceReader = StringSetting("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "")
+ val XnoValueClasses = BooleanSetting("-Xno-value-classes", "Do not use value classes. Helps debugging.")
val XoldPatmat = BooleanSetting("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.")
val XnoPatmatAnalysis = BooleanSetting("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
diff --git a/src/dotty/tools/dotc/transform/ValueClasses.scala b/src/dotty/tools/dotc/transform/ValueClasses.scala
index 30802f426..93005c57a 100644
--- a/src/dotty/tools/dotc/transform/ValueClasses.scala
+++ b/src/dotty/tools/dotc/transform/ValueClasses.scala
@@ -13,6 +13,7 @@ import StdNames._
object ValueClasses {
def isDerivedValueClass(d: SymDenotation)(implicit ctx: Context) = {
+ !ctx.settings.XnoValueClasses.value &&
!d.isRefinementClass &&
d.isValueClass &&
(d.initial.symbol ne defn.AnyValClass) && // Compare the initial symbol because AnyVal does not exist after erasure
diff --git a/src/scala/runtime/ScalaRunTime/ScalaRunTime.scala b/src/scala/runtime/ScalaRunTime/ScalaRunTime.scala
new file mode 100644
index 000000000..b875b4d1e
--- /dev/null
+++ b/src/scala/runtime/ScalaRunTime/ScalaRunTime.scala
@@ -0,0 +1,371 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+package runtime
+
+import dotty.runtime.vc.VCArrayPrototype
+
+import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator }
+import scala.collection.mutable.WrappedArray
+import scala.collection.immutable.{ StringLike, NumericRange, List, Stream, Nil, :: }
+import scala.collection.generic.{ Sorted, IsTraversableLike }
+import scala.reflect.{ ClassTag, classTag }
+import scala.util.control.ControlThrowable
+import java.lang.{ Class => jClass }
+
+import java.lang.Double.doubleToLongBits
+import java.lang.reflect.{ Modifier, Method => JMethod }
+
+/** The object ScalaRunTime provides support methods required by
+ * the scala runtime. All these methods should be considered
+ * outside the API and subject to change or removal without notice.
+ */
+object ScalaRunTime {
+ def isArray(x: Any, atLevel: Int = 1): Boolean =
+ x != null && isArrayClass(x.getClass, atLevel)
+
+ private def isArrayClass(clazz: jClass[_], atLevel: Int): Boolean =
+ (clazz.isArray || classOf[VCArrayPrototype[_]].isAssignableFrom(clazz)) &&
+ (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))
+
+ def isValueClass(clazz: jClass[_]) = clazz.isPrimitive()
+
+ // includes specialized subclasses and future proofed against hypothetical TupleN (for N > 22)
+ def isTuple(x: Any) = x != null && x.getClass.getName.startsWith("scala.Tuple")
+ def isAnyVal(x: Any) = x match {
+ case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true
+ case _ => false
+ }
+
+ // A helper method to make my life in the pattern matcher a lot easier.
+ def drop[Repr](coll: Repr, num: Int)(implicit traversable: IsTraversableLike[Repr]): Repr =
+ traversable conversion coll drop num
+
+ /** Return the class object representing an array with element class `clazz`.
+ */
+ def arrayClass(clazz: jClass[_]): jClass[_] = {
+ ??? // Dmitry: I want to see where this method is used to know how to fix it
+ // newInstance throws an exception if the erasure is Void.TYPE. see SI-5680
+ if (clazz == java.lang.Void.TYPE) classOf[Array[Unit]]
+ else java.lang.reflect.Array.newInstance(clazz, 0).getClass
+ }
+
+ /** Return the class object representing elements in arrays described by a given schematic.
+ */
+ def arrayElementClass(schematic: Any): jClass[_] = schematic match {
+ case cls: jClass[_] => cls.getComponentType
+ case tag: ClassTag[_] => tag.runtimeClass
+ case _ =>
+ throw new UnsupportedOperationException(s"unsupported schematic $schematic (${schematic.getClass})")
+ }
+
+ /** Return the class object representing an unboxed value type,
+ * e.g., classOf[int], not classOf[java.lang.Integer]. The compiler
+ * rewrites expressions like 5.getClass to come here.
+ */
+ def anyValClass[T <: AnyVal : ClassTag](value: T): jClass[T] =
+ classTag[T].runtimeClass.asInstanceOf[jClass[T]]
+
+ /** Retrieve generic array element */
+ def array_apply(xs: AnyRef, idx: Int): Any = {
+ xs match {
+ case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
+ case x: Array[Int] => x(idx).asInstanceOf[Any]
+ case x: Array[Double] => x(idx).asInstanceOf[Any]
+ case x: Array[Long] => x(idx).asInstanceOf[Any]
+ case x: Array[Float] => x(idx).asInstanceOf[Any]
+ case x: Array[Char] => x(idx).asInstanceOf[Any]
+ case x: Array[Byte] => x(idx).asInstanceOf[Any]
+ case x: Array[Short] => x(idx).asInstanceOf[Any]
+ case x: Array[Boolean] => x(idx).asInstanceOf[Any]
+ case x: Array[Unit] => x(idx).asInstanceOf[Any]
+ case x: VCArrayPrototype[_] => x.apply(idx)
+ case null => throw new NullPointerException
+ }
+ }
+
+ /** update generic array element */
+ def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
+ xs match {
+ case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
+ case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
+ case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
+ case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
+ case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
+ case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
+ case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
+ case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
+ case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
+ case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
+ case x: VCArrayPrototype[t] => x.update(idx, value.asInstanceOf[t])
+ case null => throw new NullPointerException
+ }
+ }
+
+ /** Get generic array length */
+ def array_length(xs: AnyRef): Int = xs match {
+ case x: Array[AnyRef] => x.length
+ case x: Array[Int] => x.length
+ case x: Array[Double] => x.length
+ case x: Array[Long] => x.length
+ case x: Array[Float] => x.length
+ case x: Array[Char] => x.length
+ case x: Array[Byte] => x.length
+ case x: Array[Short] => x.length
+ case x: Array[Boolean] => x.length
+ case x: Array[Unit] => x.length
+ case x: VCArrayPrototype[_] => x.length
+ case null => throw new NullPointerException
+ }
+
+ def array_clone(xs: AnyRef): AnyRef = xs match {
+ case x: Array[AnyRef] => ArrayRuntime.cloneArray(x)
+ case x: Array[Int] => ArrayRuntime.cloneArray(x)
+ case x: Array[Double] => ArrayRuntime.cloneArray(x)
+ case x: Array[Long] => ArrayRuntime.cloneArray(x)
+ case x: Array[Float] => ArrayRuntime.cloneArray(x)
+ case x: Array[Char] => ArrayRuntime.cloneArray(x)
+ case x: Array[Byte] => ArrayRuntime.cloneArray(x)
+ case x: Array[Short] => ArrayRuntime.cloneArray(x)
+ case x: Array[Boolean] => ArrayRuntime.cloneArray(x)
+ case x: Array[Unit] => x
+ case x: VCArrayPrototype[_] => x.clone()
+ case null => throw new NullPointerException
+ }
+
+ /** Convert an array to an object array.
+ * Needed to deal with vararg arguments of primitive types that are passed
+ * to a generic Java vararg parameter T ...
+ */
+ def toObjectArray(src: AnyRef): Array[Object] = src match {
+ case x: Array[AnyRef] => x
+ case _ =>
+ 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]
+ i += 1
+ }
+ arr
+ }
+
+ // Java bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957
+ // More background at ticket #2318.
+ def ensureAccessible(m: JMethod): JMethod = scala.reflect.ensureAccessible(m)
+
+ def checkInitialized[T <: AnyRef](x: T): T =
+ if (x == null) throw new UninitializedError else x
+
+ def _toString(x: Product): String =
+ x.productIterator.mkString(x.productPrefix + "(", ",", ")")
+
+ def _hashCode(x: Product): Int = scala.util.hashing.MurmurHash3.productHash(x)
+
+ /** A helper for case classes. */
+ def typedProductIterator[T](x: Product): Iterator[T] = {
+ new AbstractIterator[T] {
+ private var c: Int = 0
+ private val cmax = x.productArity
+ def hasNext = c < cmax
+ def next() = {
+ val result = x.productElement(c)
+ c += 1
+ result.asInstanceOf[T]
+ }
+ }
+ }
+
+ /** Fast path equality method for inlining; used when -optimise is set.
+ */
+ @inline def inlinedEquals(x: Object, y: Object): Boolean =
+ if (x eq y) true
+ else if (x eq null) false
+ else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.equalsNumObject(x.asInstanceOf[java.lang.Number], y)
+ else if (x.isInstanceOf[java.lang.Character]) BoxesRunTime.equalsCharObject(x.asInstanceOf[java.lang.Character], y)
+ else x.equals(y)
+
+ def _equals(x: Product, y: Any): Boolean = y match {
+ case y: Product if x.productArity == y.productArity => x.productIterator sameElements y.productIterator
+ case _ => false
+ }
+
+ // hashcode -----------------------------------------------------------
+ //
+ // Note that these are the implementations called by ##, so they
+ // must not call ## themselves.
+
+ def hash(x: Any): Int =
+ if (x == null) 0
+ else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number])
+ else x.hashCode
+
+ def hash(dv: Double): Int = {
+ val iv = dv.toInt
+ if (iv == dv) return iv
+
+ val lv = dv.toLong
+ if (lv == dv) return lv.hashCode
+
+ val fv = dv.toFloat
+ if (fv == dv) fv.hashCode else dv.hashCode
+ }
+ def hash(fv: Float): Int = {
+ val iv = fv.toInt
+ if (iv == fv) return iv
+
+ val lv = fv.toLong
+ if (lv == fv) hash(lv)
+ else fv.hashCode
+ }
+ def hash(lv: Long): Int = {
+ val low = lv.toInt
+ val lowSign = low >>> 31
+ val high = (lv >>> 32).toInt
+ low ^ (high + lowSign)
+ }
+ def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x)
+
+ // The remaining overloads are here for completeness, but the compiler
+ // inlines these definitions directly so they're not generally used.
+ def hash(x: Int): Int = x
+ def hash(x: Short): Int = x.toInt
+ def hash(x: Byte): Int = x.toInt
+ def hash(x: Char): Int = x.toInt
+ def hash(x: Boolean): Int = if (x) true.hashCode else false.hashCode
+ def hash(x: Unit): Int = 0
+
+ /** A helper method for constructing case class equality methods,
+ * because existential types get in the way of a clean outcome and
+ * it's performing a series of Any/Any equals comparisons anyway.
+ * See ticket #2867 for specifics.
+ */
+ def sameElements(xs1: scala.collection.Seq[Any], xs2: scala.collection.Seq[Any]) = xs1 sameElements xs2
+
+ /** 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 = stringOf(arg, scala.Int.MaxValue)
+ def stringOf(arg: Any, maxElements: Int): String = {
+ def packageOf(x: AnyRef) = x.getClass.getPackage match {
+ case null => ""
+ case p => p.getName
+ }
+ def isScalaClass(x: AnyRef) = packageOf(x) startsWith "scala."
+ def isScalaCompilerClass(x: AnyRef) = packageOf(x) startsWith "scala.tools.nsc."
+
+ // We use reflection because the scala.xml package might not be available
+ def isSubClassOf(potentialSubClass: Class[_], ofClass: String) =
+ try {
+ val classLoader = potentialSubClass.getClassLoader
+ val clazz = Class.forName(ofClass, /*initialize =*/ false, classLoader)
+ clazz.isAssignableFrom(potentialSubClass)
+ } catch {
+ case cnfe: ClassNotFoundException => false
+ }
+ def isXmlNode(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.Node")
+ def isXmlMetaData(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.MetaData")
+
+ // When doing our own iteration is dangerous
+ def useOwnToString(x: Any) = x match {
+ // Range/NumericRange have a custom toString to avoid walking a gazillion elements
+ case _: Range | _: NumericRange[_] => true
+ // Sorted collections to the wrong thing (for us) on iteration - ticket #3493
+ case _: Sorted[_, _] => true
+ // StringBuilder(a, b, c) and similar not so attractive
+ case _: StringLike[_] => true
+ // Don't want to evaluate any elements in a view
+ case _: TraversableView[_, _] => true
+ // Node extends NodeSeq extends Seq[Node] and MetaData extends Iterable[MetaData]
+ // -> catch those by isXmlNode and isXmlMetaData.
+ // Don't want to a) traverse infinity or b) be overly helpful with peoples' custom
+ // collections which may have useful toString methods - ticket #3710
+ // or c) print AbstractFiles which are somehow also Iterable[AbstractFile]s.
+ case x: Traversable[_] => !x.hasDefiniteSize || !isScalaClass(x) || isScalaCompilerClass(x) || isXmlNode(x.getClass) || isXmlMetaData(x.getClass)
+ // Otherwise, nothing could possibly go wrong
+ case _ => false
+ }
+
+ // A variation on inner for maps so they print -> instead of bare tuples
+ def mapInner(arg: Any): String = arg match {
+ case (k, v) => inner(k) + " -> " + inner(v)
+ case _ => inner(arg)
+ }
+
+ // Special casing Unit arrays, the value class which uses a reference array type.
+ def arrayToString(x: AnyRef) = {
+ if (x.getClass.getComponentType == classOf[BoxedUnit])
+ 0 until (array_length(x) min maxElements) map (_ => "()") mkString ("Array(", ", ", ")")
+ else
+ WrappedArray make x take maxElements map inner mkString ("Array(", ", ", ")")
+ }
+
+ // The recursively applied attempt to prettify Array printing.
+ // Note that iterator is used if possible and foreach is used as a
+ // last resort, because the parallel collections "foreach" in a
+ // random order even on sequences.
+ def inner(arg: Any): String = arg match {
+ case null => "null"
+ case "" => "\"\""
+ case x: String => if (x.head.isWhitespace || x.last.isWhitespace) "\"" + x + "\"" else x
+ case x if useOwnToString(x) => x.toString
+ case x: AnyRef if isArray(x) => arrayToString(x)
+ case x: scala.collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.stringPrefix + "(", ", ", ")")
+ case x: Iterable[_] => x.iterator take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
+ case x: Traversable[_] => x take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
+ case x: Product1[_] if isTuple(x) => "(" + inner(x._1) + ",)" // that special trailing comma
+ case x: Product if isTuple(x) => x.productIterator map inner mkString ("(", ",", ")")
+ case x => x.toString
+ }
+
+ // The try/catch is defense against iterables which aren't actually designed
+ // to be iterated, such as some scala.tools.nsc.io.AbstractFile derived classes.
+ try inner(arg)
+ catch {
+ case _: UnsupportedOperationException | _: AssertionError => "" + arg
+ }
+ }
+
+ /** stringOf formatted for use in a repl result. */
+ def replStringOf(arg: Any, maxElements: Int): String = {
+ val s = stringOf(arg, maxElements)
+ val nl = if (s contains "\n") "\n" else ""
+
+ nl + s + "\n"
+ }
+
+ def box[T](clazz: jClass[T]): jClass[_] = clazz match {
+ case java.lang.Byte.TYPE => classOf[java.lang.Byte]
+ case java.lang.Short.TYPE => classOf[java.lang.Short]
+ case java.lang.Character.TYPE => classOf[java.lang.Character]
+ case java.lang.Integer.TYPE => classOf[java.lang.Integer]
+ case java.lang.Long.TYPE => classOf[java.lang.Long]
+ case java.lang.Float.TYPE => classOf[java.lang.Float]
+ case java.lang.Double.TYPE => classOf[java.lang.Double]
+ case java.lang.Void.TYPE => classOf[scala.runtime.BoxedUnit]
+ case java.lang.Boolean.TYPE => classOf[java.lang.Boolean]
+ case _ => clazz
+ }
+}