summaryrefslogblamecommitdiff
path: root/src/library/scala/runtime/ScalaRunTime.scala
blob: ca8549bffaeeca7ae43e271aae7f9913866891a4 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                                                          
                                                                          
                                                                          



                                                                          

       
 
                     
 
                                  
                                           
                                            
                                                           
                                   
                                          
 

                                                    
                     
                                                 

                                                                       



                                                                                        
                                                         
 
                                       












                                                         
 
                                     












                                                                       

                                 












                                                
 













                                                        











                                                                            
                                                 

                                          



                                     


       


                                                      
                          
                                                                
                                

   










                                                                                  
                                                                  









                                                                
   
 
                                     
                                                               
 


                                                                                    
                                    
                             
                  
             
                     
                                    
                                                                   
            


        
 


                                                                         

                             
                                                                                                                

                    
                                                      

                                                                                                           

   












                                                                      




                                                             

                                                           
                                                                                                   
                                                                


                                                                            
                                             
                                                                          
                                                                     




                                                 
   
 
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2010, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala.runtime

import scala.reflect.ClassManifest
import scala.collection.{ Seq, IndexedSeq }
import scala.collection.mutable.WrappedArray
import scala.collection.immutable.{ List, Stream, Nil, :: }
import scala.xml.{ Node, MetaData }
import scala.util.control.ControlException

/* The object <code>ScalaRunTime</code> provides ...
 */
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)

  private def isArrayClass(clazz: Class[_], atLevel: Int): Boolean =
    clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))

  def isValueClass(clazz: Class[_]) = clazz.isPrimitive()

  /** 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 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 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 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 null => throw new NullPointerException
  }

  /** 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]
      i += 1
    }
    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(fin: => Unit): A
  }

  def Try[A](block: => A): Try[A] = new Try[A] with Runnable {
    private var result: A = _
    private var exception: Throwable =
      try   { run() ; null }
      catch {
        case e: ControlException  => throw e  // don't catch non-local returns etc
        case e: Throwable         => e
      }

    def run() { result = block }

    def Catch[B >: A](handler: PartialFunction[Throwable, B]): B =
      if (exception == null) result
      else if (handler isDefinedAt exception) handler(exception)
      else throw exception

    def Finally(fin: => Unit): A = {
      fin

      if (exception == null) result
      else throw exception
    }
  }

  def _toString(x: Product): String =
    x.productIterator.mkString(x.productPrefix + "(", ",", ")")

  def _hashCodeJenkins(x: Product): Int =
    scala.util.JenkinsHash.hashSeq(x.productPrefix.toSeq ++ x.productIterator.toSeq)

  def _hashCode(x: Product): Int = {
    val arr =  x.productArity
    var code = arr
    var i = 0
    while (i < arr) {
      val elem = x.productElement(i)
      code = code * 41 + (if (elem == null) 0 else elem.hashCode())
      i += 1
    }
    code
  }

  /** 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] || x.isInstanceOf[java.lang.Character]) BoxesRunTime.equals2(x, 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
  }

  /** 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 = {
    def inner(arg: Any): String = arg match {
      case null                     => "null"
      // Node extends NodeSeq extends Seq[Node] strikes again
      case x: Node                  => x toString
      // Not to mention MetaData extends Iterable[MetaData]
      case x: MetaData              => x toString
      case x: AnyRef if isArray(x)  => WrappedArray make x map inner mkString ("Array(", ", ", ")")
      case x: Traversable[_] if !x.hasDefiniteSize => x.toString
      case x: Traversable[_]        =>
        // Some subclasses of AbstractFile implement Iterable, then throw an
        // exception if you call iterator.  What a world.
        // And they can't be infinite either.
        if (x.getClass.getName startsWith "scala.tools.nsc.io") x.toString
        else (x map inner) mkString (x.stringPrefix + "(", ", ", ")")
      case x                        => x toString
    }
    val s = inner(arg)
    val nl = if (s contains "\n") "\n" else ""
    nl + s + "\n"
  }
}