summaryrefslogtreecommitdiff
path: root/test/instrumented/library
diff options
context:
space:
mode:
Diffstat (limited to 'test/instrumented/library')
-rw-r--r--test/instrumented/library/scala/runtime/BoxesRunTime.java116
-rw-r--r--test/instrumented/library/scala/runtime/ScalaRunTime.scala255
2 files changed, 222 insertions, 149 deletions
diff --git a/test/instrumented/library/scala/runtime/BoxesRunTime.java b/test/instrumented/library/scala/runtime/BoxesRunTime.java
index 797e9f89dd..f06f86f2f2 100644
--- a/test/instrumented/library/scala/runtime/BoxesRunTime.java
+++ b/test/instrumented/library/scala/runtime/BoxesRunTime.java
@@ -30,9 +30,9 @@ import scala.math.ScalaNumber;
* @contributor Stepan Koltsov
* @version 2.0 */
public final class BoxesRunTime
-{
+{
private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7;
-
+
private static int typeCode(Object a) {
if (a instanceof java.lang.Integer) return INT;
if (a instanceof java.lang.Byte) return BYTE;
@@ -43,13 +43,13 @@ public final class BoxesRunTime
if (a instanceof java.lang.Float) return FLOAT;
return OTHER;
}
-
+
private static String boxDescription(Object a) {
return "" + a.getClass().getSimpleName() + "(" + a + ")";
}
-
+
/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */
-
+
public static int booleanBoxCount = 0;
public static int characterBoxCount = 0;
public static int byteBoxCount = 0;
@@ -63,58 +63,58 @@ public final class BoxesRunTime
booleanBoxCount++;
return java.lang.Boolean.valueOf(b);
}
-
+
public static java.lang.Character boxToCharacter(char c) {
characterBoxCount++;
return java.lang.Character.valueOf(c);
}
-
+
public static java.lang.Byte boxToByte(byte b) {
byteBoxCount++;
return java.lang.Byte.valueOf(b);
}
-
+
public static java.lang.Short boxToShort(short s) {
shortBoxCount++;
return java.lang.Short.valueOf(s);
}
-
+
public static java.lang.Integer boxToInteger(int i) {
integerBoxCount++;
return java.lang.Integer.valueOf(i);
}
-
+
public static java.lang.Long boxToLong(long l) {
longBoxCount++;
return java.lang.Long.valueOf(l);
}
-
+
public static java.lang.Float boxToFloat(float f) {
floatBoxCount++;
return java.lang.Float.valueOf(f);
}
-
+
public static java.lang.Double boxToDouble(double d) {
doubleBoxCount++;
// System.out.println("box " + d);
// (new Throwable()).printStackTrace();
return java.lang.Double.valueOf(d);
}
-
+
/* UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING */
-
+
public static boolean unboxToBoolean(Object b) {
return b == null ? false : ((java.lang.Boolean)b).booleanValue();
}
-
+
public static char unboxToChar(Object c) {
return c == null ? 0 : ((java.lang.Character)c).charValue();
}
-
+
public static byte unboxToByte(Object b) {
return b == null ? 0 : ((java.lang.Byte)b).byteValue();
}
-
+
public static short unboxToShort(Object s) {
return s == null ? 0 : ((java.lang.Short)s).shortValue();
}
@@ -122,22 +122,22 @@ public final class BoxesRunTime
public static int unboxToInt(Object i) {
return i == null ? 0 : ((java.lang.Integer)i).intValue();
}
-
+
public static long unboxToLong(Object l) {
return l == null ? 0 : ((java.lang.Long)l).longValue();
}
-
+
public static float unboxToFloat(Object f) {
return f == null ? 0.0f : ((java.lang.Float)f).floatValue();
}
-
+
public static double unboxToDouble(Object d) {
// System.out.println("unbox " + d);
return d == null ? 0.0d : ((java.lang.Double)d).doubleValue();
}
/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */
-
+
private static int eqTypeCode(Number a) {
if ((a instanceof java.lang.Integer) || (a instanceof java.lang.Byte)) return INT;
if (a instanceof java.lang.Long) return LONG;
@@ -146,8 +146,8 @@ public final class BoxesRunTime
if (a instanceof java.lang.Float) return FLOAT;
return OTHER;
}
-
- public static boolean equals(Object x, Object y) {
+
+ public static boolean equals(Object x, Object y) {
if (x == y) return true;
return equals2(x, y);
}
@@ -162,10 +162,10 @@ public final class BoxesRunTime
return equalsCharObject((java.lang.Character)x, y);
if (x == null)
return y == null;
-
+
return x.equals(y);
}
-
+
public static boolean equalsNumObject(java.lang.Number xn, Object y) {
if (y instanceof java.lang.Number)
return equalsNumNum(xn, (java.lang.Number)y);
@@ -173,10 +173,10 @@ public final class BoxesRunTime
return equalsNumChar(xn, (java.lang.Character)y);
if (xn == null)
return y == null;
-
+
return xn.equals(y);
}
-
+
public static boolean equalsNumNum(java.lang.Number xn, java.lang.Number yn) {
int xcode = eqTypeCode(xn);
int ycode = eqTypeCode(yn);
@@ -195,10 +195,10 @@ public final class BoxesRunTime
}
if (xn == null)
return yn == null;
-
+
return xn.equals(yn);
}
-
+
public static boolean equalsCharObject(java.lang.Character xc, Object y) {
if (y instanceof java.lang.Character)
return xc.charValue() == ((java.lang.Character)y).charValue();
@@ -206,7 +206,7 @@ public final class BoxesRunTime
return equalsNumChar((java.lang.Number)y, xc);
if (xc == null)
return y == null;
-
+
return xc.equals(y);
}
@@ -224,11 +224,11 @@ public final class BoxesRunTime
default:
if (xn == null)
return yc == null;
-
+
return xn.equals(yc);
}
}
-
+
/** Hashcode algorithm is driven by the requirements imposed
* by primitive equality semantics, namely that equal objects
* have equal hashCodes. The first priority are the integral/char
@@ -262,16 +262,16 @@ public final class BoxesRunTime
else return n.hashCode();
}
public static int hashFromDouble(java.lang.Double n) {
- int iv = n.intValue();
+ int iv = n.intValue();
double dv = n.doubleValue();
if (iv == dv) return iv;
-
+
long lv = n.longValue();
if (lv == dv) return java.lang.Long.valueOf(lv).hashCode();
else return n.hashCode();
}
public static int hashFromFloat(java.lang.Float n) {
- int iv = n.intValue();
+ int iv = n.intValue();
float fv = n.floatValue();
if (iv == fv) return iv;
@@ -289,9 +289,9 @@ public final class BoxesRunTime
if (a instanceof Number) return hashFromNumber((Number)a);
else return a.hashCode();
}
-
+
/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */
-
+
/** arg1 + arg2 */
public static Object add(Object arg1, Object arg2) throws NoSuchMethodException {
int code1 = typeCode(arg1);
@@ -518,7 +518,7 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
/** -arg */
public static Object negate(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
@@ -540,7 +540,7 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
/** +arg */
public static Object positive(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
@@ -650,7 +650,7 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
/** ~arg */
public static Object complement(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
@@ -664,7 +664,7 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
/** !arg */
public static Object takeNot(Object arg) throws NoSuchMethodException {
if (arg instanceof Boolean) {
@@ -672,15 +672,15 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
public static Object testEqual(Object arg1, Object arg2) throws NoSuchMethodException {
return boxToBoolean(arg1 == arg2);
}
-
+
public static Object testNotEqual(Object arg1, Object arg2) throws NoSuchMethodException {
return boxToBoolean(arg1 != arg2);
}
-
+
public static Object testLessThan(Object arg1, Object arg2) throws NoSuchMethodException {
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
@@ -707,7 +707,7 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
public static Object testLessOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException {
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
@@ -734,7 +734,7 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
public static Object testGreaterOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException {
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
@@ -761,7 +761,7 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
public static Object testGreaterThan(Object arg1, Object arg2) throws NoSuchMethodException {
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
@@ -788,7 +788,25 @@ public final class BoxesRunTime
}
throw new NoSuchMethodException();
}
-
+
+ public static boolean isBoxedNumberOrBoolean(Object arg) {
+ if (arg instanceof java.lang.Boolean)
+ return true;
+ else
+ return isBoxedNumber(arg);
+ }
+ public static boolean isBoxedNumber(Object arg) {
+ return (
+ (arg instanceof java.lang.Integer)
+ || (arg instanceof java.lang.Long)
+ || (arg instanceof java.lang.Double)
+ || (arg instanceof java.lang.Float)
+ || (arg instanceof java.lang.Short)
+ || (arg instanceof java.lang.Character)
+ || (arg instanceof java.lang.Byte)
+ );
+ }
+
/** arg.toChar */
public static java.lang.Character toCharacter(Object arg) throws NoSuchMethodException {
if (arg instanceof java.lang.Integer) return boxToCharacter((char)unboxToInt(arg));
@@ -872,5 +890,5 @@ public final class BoxesRunTime
if (arg instanceof java.lang.Short) return boxToDouble((double)unboxToShort(arg));
throw new NoSuchMethodException();
}
-
+
}
diff --git a/test/instrumented/library/scala/runtime/ScalaRunTime.scala b/test/instrumented/library/scala/runtime/ScalaRunTime.scala
index a8a74dd8ab..9eb93a418d 100644
--- a/test/instrumented/library/scala/runtime/ScalaRunTime.scala
+++ b/test/instrumented/library/scala/runtime/ScalaRunTime.scala
@@ -6,70 +6,102 @@
** |/ **
\* */
-
+package scala.runtime
/* INSTRUMENTED VERSION */
-package scala.runtime
-
-import scala.reflect.ClassManifest
-import scala.collection.{ Seq, IndexedSeq, TraversableView }
+import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator }
import scala.collection.mutable.WrappedArray
-import scala.collection.immutable.{ NumericRange, List, Stream, Nil, :: }
+import scala.collection.immutable.{ StringLike, NumericRange, List, Stream, Nil, :: }
import scala.collection.generic.{ Sorted }
-import scala.xml.{ Node, MetaData }
import scala.util.control.ControlThrowable
+import scala.xml.{ Node, MetaData }
+
+import java.lang.Double.doubleToLongBits
import java.lang.reflect.{ Modifier, Method => JMethod }
-/* The object <code>ScalaRunTime</code> provides ...
+/** 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: AnyRef): Boolean = isArray(x, 1)
- def isArray(x: Any, atLevel: Int): Boolean =
- x != null && isArrayClass(x.asInstanceOf[AnyRef].getClass, atLevel)
+ def isArray(x: Any, atLevel: Int): Boolean =
+ x != null && isArrayClass(x.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()
-
+ def isValueClass(clazz: Class[_]) = clazz.isPrimitive()
var arrayApplyCount = 0
var arrayUpdateCount = 0
-
+
+ def isTuple(x: Any) = tupleNames(x.getClass.getName)
+ def isAnyVal(x: Any) = x match {
+ case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true
+ case _ => false
+ }
+ // Avoiding boxing which messes up the specialized tests. Don't ask.
+ private val tupleNames = {
+ var i = 22
+ var names: List[String] = Nil
+ while (i >= 1) {
+ names ::= ("scala.Tuple" + String.valueOf(i))
+ i -= 1
+ }
+ names.toSet
+ }
+
+ /** 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](value: T): Class[T] = (value match {
+ case x: Byte => java.lang.Byte.TYPE
+ case x: Short => java.lang.Short.TYPE
+ case x: Char => java.lang.Character.TYPE
+ case x: Int => java.lang.Integer.TYPE
+ case x: Long => java.lang.Long.TYPE
+ case x: Float => java.lang.Float.TYPE
+ case x: Double => java.lang.Double.TYPE
+ case x: Boolean => java.lang.Boolean.TYPE
+ case x: Unit => java.lang.Void.TYPE
+ }).asInstanceOf[Class[T]]
+
/** Retrieve generic array element */
def array_apply(xs: AnyRef, idx: Int): Any = {
arrayApplyCount += 1
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 null => throw new NullPointerException
- }
+ 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 null => throw new NullPointerException
+ }
}
/** update generic array element */
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
arrayUpdateCount += 1
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 null => throw new NullPointerException
- }
+ 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 null => throw new NullPointerException
+ }
}
/** Get generic array length */
@@ -85,7 +117,7 @@ object ScalaRunTime {
case x: Array[Boolean] => x.length
case x: Array[Unit] => x.length
case null => throw new NullPointerException
- }
+ }
def array_clone(xs: AnyRef): AnyRef = xs match {
case x: Array[AnyRef] => ArrayRuntime.cloneArray(x)
@@ -122,7 +154,7 @@ object ScalaRunTime {
}
arr
}
-
+
// Java bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957
// More background at ticket #2318.
def ensureAccessible(m: JMethod): JMethod = {
@@ -130,10 +162,10 @@ object ScalaRunTime {
try m setAccessible true
catch { case _: SecurityException => () }
}
- m
+ m
}
- def checkInitialized[T <: AnyRef](x: T): T =
+ def checkInitialized[T <: AnyRef](x: T): T =
if (x == null) throw new UninitializedError else x
abstract class Try[+A] {
@@ -143,9 +175,9 @@ object ScalaRunTime {
def Try[A](block: => A): Try[A] = new Try[A] with Runnable {
private var result: A = _
- private var exception: Throwable =
+ private var exception: Throwable =
try { run() ; null }
- catch {
+ catch {
case e: ControlThrowable => throw e // don't catch non-local returns etc
case e: Throwable => e
}
@@ -167,27 +199,26 @@ object ScalaRunTime {
def _toString(x: Product): String =
x.productIterator.mkString(x.productPrefix + "(", ",", ")")
-
- def _hashCode(x: Product): Int = {
- import scala.util.MurmurHash._
- val arr = x.productArity
- var h = startHash(arr)
- var c = startMagicA
- var k = startMagicB
- var i = 0
- while (i < arr) {
- val elem = x.productElement(i)
- h = extendHash(h, if (elem == null) 0 else elem.##, c, k)
- c = nextMagicA(c)
- k = nextMagicB(k)
- i += 1
+
+ def _hashCode(x: Product): Int = scala.util.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]
+ }
}
- finalizeHash(h)
}
/** Fast path equality method for inlining; used when -optimise is set.
*/
- @inline def inlinedEquals(x: Object, y: Object): Boolean =
+ @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)
@@ -198,20 +229,21 @@ object ScalaRunTime {
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.
-
+
@inline def hash(x: Any): Int =
- if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number])
+ if (x == null) 0
+ else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number])
else x.hashCode
-
+
@inline def hash(dv: Double): Int = {
val iv = dv.toInt
if (iv == dv) return iv
-
+
val lv = dv.toLong
if (lv == dv) return lv.hashCode
@@ -221,31 +253,27 @@ object ScalaRunTime {
@inline def hash(fv: Float): Int = {
val iv = fv.toInt
if (iv == fv) return iv
-
+
val lv = fv.toLong
- if (lv == fv) return lv.hashCode
+ if (lv == fv) return hash(lv)
else fv.hashCode
}
@inline def hash(lv: Long): Int = {
- val iv = lv.toInt
- if (iv == lv) iv else lv.hashCode
+ val low = lv.toInt
+ val lowSign = low >>> 31
+ val high = (lv >>> 32).toInt
+ low ^ (high + lowSign)
}
+ @inline 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.
@inline def hash(x: Int): Int = x
@inline def hash(x: Short): Int = x.toInt
@inline def hash(x: Byte): Int = x.toInt
@inline def hash(x: Char): Int = x.toInt
- @inline def hash(x: Boolean): Int = x.hashCode
+ @inline def hash(x: Boolean): Int = if (x) true.hashCode else false.hashCode
@inline def hash(x: Unit): Int = 0
-
- @inline def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x)
-
- /** XXX Why is there one boxed implementation in here? It would seem
- * we should have all the numbers or none of them.
- */
- @inline def hash(x: java.lang.Long): Int = {
- val iv = x.intValue
- if (iv == x.longValue) iv else x.hashCode
- }
/** A helper method for constructing case class equality methods,
* because existential types get in the way of a clean outcome and
@@ -263,17 +291,13 @@ object ScalaRunTime {
* 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>
- *
- */
+ * @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 stringOf(arg: Any, maxElements: Int): String = {
def isScalaClass(x: AnyRef) =
Option(x.getClass.getPackage) exists (_.getName startsWith "scala.")
-
- def isTuple(x: AnyRef) =
- x.getClass.getName matches """^scala\.Tuple(\d+).*"""
// When doing our own iteration is dangerous
def useOwnToString(x: Any) = x match {
@@ -283,8 +307,8 @@ object ScalaRunTime {
case _: Range | _: NumericRange[_] => true
// Sorted collections to the wrong thing (for us) on iteration - ticket #3493
case _: Sorted[_, _] => true
- // StringBuilder(a, b, c) is not so attractive
- case _: StringBuilder => 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
// Don't want to a) traverse infinity or b) be overly helpful with peoples' custom
@@ -299,14 +323,27 @@ object ScalaRunTime {
case (k, v) => inner(k) + " -> " + inner(v)
case _ => inner(arg)
}
- // The recursively applied attempt to prettify Array printing
+
+ // 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) => WrappedArray make x take maxElements map inner mkString ("Array(", ", ", ")")
- case x: collection.Map[_, _] => x take maxElements map mapInner mkString (x.stringPrefix + "(", ", ", ")")
+ case x if useOwnToString(x) => x toString
+ case x: AnyRef if isArray(x) => arrayToString(x)
+ case x: 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 ("(", ",", ")")
@@ -315,13 +352,31 @@ object ScalaRunTime {
// 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.
- val s =
- try inner(arg)
- catch {
- case _: StackOverflowError | _: UnsupportedOperationException => arg.toString
- }
-
+ try inner(arg)
+ catch {
+ case _: StackOverflowError | _: 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"
+
+ nl + s + "\n"
+ }
+ private[scala] def checkZip(what: String, coll1: TraversableOnce[_], coll2: TraversableOnce[_]) {
+ if (sys.props contains "scala.debug.zip") {
+ val xs = coll1.toIndexedSeq
+ val ys = coll2.toIndexedSeq
+ if (xs.length != ys.length) {
+ Console.err.println(
+ "Mismatched zip in " + what + ":\n" +
+ " this: " + xs.mkString(", ") + "\n" +
+ " that: " + ys.mkString(", ")
+ )
+ (new Exception).getStackTrace.drop(2).take(10).foreach(println)
+ }
+ }
}
}