summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/runtime/Mirror.scala10
-rw-r--r--src/compiler/scala/reflect/runtime/RuntimeTypes.scala31
-rw-r--r--src/library/scala/reflect/ClassManifest.scala47
-rw-r--r--src/library/scala/reflect/Manifest.scala18
-rw-r--r--src/library/scala/reflect/api/Mirror.scala36
-rw-r--r--src/library/scala/reflect/api/RuntimeTypes.scala20
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala4
-rwxr-xr-xsrc/library/scala/reflect/api/Types.scala1
8 files changed, 143 insertions, 24 deletions
diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala
index b1724d6450..d2f043c2e2 100644
--- a/src/compiler/scala/reflect/runtime/Mirror.scala
+++ b/src/compiler/scala/reflect/runtime/Mirror.scala
@@ -6,7 +6,7 @@ import java.lang.reflect.Array
/** The mirror for standard runtime reflection from Java.
*/
-class Mirror extends Universe with api.Mirror {
+class Mirror extends Universe with RuntimeTypes with api.Mirror {
import definitions._
@@ -33,12 +33,8 @@ class Mirror extends Universe with api.Mirror {
methodToJava(meth).invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
}
- def freeValue(x: Any): Tree = FreeValue(x)
-
- // to do: replace with generalized
- // case class Literal(x: Any),
- // once calls to the deprecated factory Literal(x: Any) has been eliminated from all code.
- case class FreeValue(any: Any) extends Tree
+ override def classToType(jclazz: java.lang.Class[_]): Type = typeToScala(jclazz)
+ override def classToSymbol(jclazz: java.lang.Class[_]): Symbol = classToScala(jclazz)
}
diff --git a/src/compiler/scala/reflect/runtime/RuntimeTypes.scala b/src/compiler/scala/reflect/runtime/RuntimeTypes.scala
new file mode 100644
index 0000000000..818596d7b3
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/RuntimeTypes.scala
@@ -0,0 +1,31 @@
+package scala.reflect
+package runtime
+
+import collection.mutable.ListBuffer
+
+trait RuntimeTypes extends Universe with api.RuntimeTypes {
+
+ def freeValue(x: Any): Tree = FreeValue(x)
+
+ // to do: replace with generalized
+ // case class Literal(x: Any),
+ // once calls to the deprecated factory Literal(x: Any) has been eliminated from all code.
+ case class FreeValue(any: Any) extends Tree
+
+ case class InstanceRefSymbol(value: AnyRef) extends TermSymbol(NoSymbol, NoPosition, nme.EMPTY)
+ object InstanceRefSymbol extends InstanceRefSymbolExtractor
+
+ override private[reflect] def namedType(pre: Type, sym: Symbol, args: List[Type]): Type = {
+ val tparamBuf = new ListBuffer[Symbol]
+ val args1 = for (arg <- args) yield arg match {
+ case _: TypeBounds =>
+ val ex = pre.typeSymbol.freshExistential("$ex") setInfo arg
+ tparamBuf += ex
+ TypeRef(NoPrefix, ex, List())
+ case _ =>
+ arg
+ }
+ existentialAbstraction(tparamBuf.toList, typeRef(pre, sym, args1))
+ }
+
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala
index 3dff72659a..acd28f04f5 100644
--- a/src/library/scala/reflect/ClassManifest.scala
+++ b/src/library/scala/reflect/ClassManifest.scala
@@ -6,10 +6,27 @@
** |/ **
\* */
+/* [Martin]
+ * Todo: ClassManifests currently contain all available type arguments.
+ * That's a waste of cycles if all that's needed is the class.
+ * We should have instead consider a structure like this:
+ *
+ * OptManifest
+ * / \
+ * / \
+ * PartialManifest ClassManifest
+ * \ /
+ * \ /
+ * Manifest
+ *
+ * where PartialManifest means: generate as much as you can, use NoManifest
+ * where nothing is known, and
+ * ClassManifest means: generate exactly the top-level class, and nothing else.
+ */
package scala.reflect
import scala.collection.mutable.{ WrappedArray, ArrayBuilder }
-import java.lang.{ Class => JClass }
+import java.lang.{ Class => jClass }
/** A `ClassManifest[T]` is an opaque descriptor for type `T`.
* It is used by the compiler to preserve information necessary
@@ -25,10 +42,14 @@ import java.lang.{ Class => JClass }
trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
/** A class representing the type `U` to which `T` would be erased. Note
* that there is no subtyping relationship between `T` and `U`. */
- def erasure: JClass[_]
+ def erasure: jClass[_]
+
+ /** The Scala type described by this manifest.
+ */
+ lazy val tpe: mirror.Type = reflect.mirror.classToType(erasure)
- private def subtype(sub: JClass[_], sup: JClass[_]): Boolean = {
- def loop(left: Set[JClass[_]], seen: Set[JClass[_]]): Boolean = {
+ private def subtype(sub: jClass[_], sup: jClass[_]): Boolean = {
+ def loop(left: Set[jClass[_]], seen: Set[jClass[_]]): Boolean = {
left.nonEmpty && {
val next = left.head
val supers = next.getInterfaces.toSet ++ Option(next.getSuperclass)
@@ -102,8 +123,8 @@ trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
}
override def hashCode = this.erasure.##
- protected def arrayClass[T](tp: JClass[_]): JClass[Array[T]] =
- java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[JClass[Array[T]]]
+ protected def arrayClass[T](tp: jClass[_]): jClass[Array[T]] =
+ java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[jClass[Array[T]]]
def arrayManifest: ClassManifest[Array[T]] =
ClassManifest.classType[Array[T]](arrayClass[T](erasure))
@@ -162,7 +183,7 @@ object ClassManifest {
val Nothing = Manifest.Nothing
val Null = Manifest.Null
- def fromClass[T](clazz: JClass[T]): ClassManifest[T] = clazz match {
+ def fromClass[T](clazz: jClass[T]): ClassManifest[T] = clazz match {
case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]]
case java.lang.Short.TYPE => Short.asInstanceOf[ClassManifest[T]]
case java.lang.Character.TYPE => Char.asInstanceOf[ClassManifest[T]]
@@ -184,18 +205,18 @@ object ClassManifest {
* pass varargs as arrays into this, we get an infinitely recursive call
* to boxArray. (Besides, having a separate case is more efficient)
*/
- def classType[T <: AnyRef](clazz: JClass[_]): ClassManifest[T] =
+ def classType[T <: AnyRef](clazz: jClass[_]): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, Nil)
/** ClassManifest for the class type `clazz[args]`, where `clazz` is
* a top-level or static class and `args` are its type arguments */
- def classType[T <: AnyRef](clazz: JClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
+ def classType[T <: AnyRef](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)
/** ClassManifest for the class type `clazz[args]`, where `clazz` is
* a class with non-package prefix type `prefix` and type arguments `args`.
*/
- def classType[T <: AnyRef](prefix: OptManifest[_], clazz: JClass[_], args: OptManifest[_]*): ClassManifest[T] =
+ def classType[T <: AnyRef](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match {
@@ -206,7 +227,7 @@ object ClassManifest {
/** ClassManifest for the abstract type `prefix # name`. `upperBound` is not
* strictly necessary as it could be obtained by reflection. It was
* added so that erasure can be calculated without reflection. */
- def abstractType[T](prefix: OptManifest[_], name: String, clazz: JClass[_], args: OptManifest[_]*): ClassManifest[T] =
+ def abstractType[T](prefix: OptManifest[_], name: String, clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassManifest[T] {
def erasure = clazz
override val typeArguments = args.toList
@@ -227,10 +248,10 @@ object ClassManifest {
}
/** Manifest for the class type `clazz[args]`, where `clazz` is
- * a top-level or static class. */
+ * a top-level or static class: todo: we should try to merge this with Manifest's class */
private class ClassTypeManifest[T <: AnyRef](
prefix: Option[OptManifest[_]],
- val erasure: JClass[_],
+ val erasure: jClass[_],
override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T]
{
override def toString =
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index 10512e134a..c1f10146c4 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -9,6 +9,7 @@
package scala.reflect
import scala.collection.mutable.{ ArrayBuilder, WrappedArray }
+import mirror._
/** A `Manifest[T]` is an opaque descriptor for type T. Its supported use
* is to give access to the erasure of the type as a `Class` instance, as
@@ -201,6 +202,7 @@ object Manifest {
private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] {
lazy val erasure = value.getClass
+ override lazy val tpe = mirror.SingleType(mirror.NoPrefix, InstanceRefSymbol(value))
override lazy val toString = value.toString + ".type"
}
@@ -234,6 +236,15 @@ object Manifest {
private class ClassTypeManifest[T](prefix: Option[Manifest[_]],
val erasure: Predef.Class[_],
override val typeArguments: List[Manifest[_]]) extends Manifest[T] {
+ override lazy val tpe = {
+ val clazz = classToSymbol(erasure)
+ val pre = prefix match {
+ case Some(pm) => pm.tpe
+ case None => clazz.owner.thisType
+ }
+ namedType(pre, clazz, typeArguments map (_.tpe))
+ }
+
override def toString =
(if (prefix.isEmpty) "" else prefix.get.toString+"#") +
(if (erasure.isArray) "Array" else erasure.getName) +
@@ -246,9 +257,10 @@ object Manifest {
/** Manifest for the abstract type `prefix # name'. `upperBound` is not
* strictly necessary as it could be obtained by reflection. It was
* added so that erasure can be calculated without reflection. */
- def abstractType[T](prefix: Manifest[_], name: String, clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
new Manifest[T] {
- def erasure = clazz
+ def erasure = upperBound
+ override lazy val tpe = namedType(prefix.tpe, prefix.tpe.member(newTypeName(name)), args map (_.tpe) toList)
override val typeArguments = args.toList
override def toString = prefix.toString+"#"+name+argString
}
@@ -258,6 +270,7 @@ object Manifest {
def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] =
new Manifest[T] {
def erasure = upperBound.erasure
+ override lazy val tpe = mirror.TypeBounds(lowerBound.tpe, upperBound.tpe)
override def toString =
"_" +
(if (lowerBound eq Nothing) "" else " >: "+lowerBound) +
@@ -268,6 +281,7 @@ object Manifest {
def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
new Manifest[T] {
def erasure = parents.head.erasure
+ override lazy val tpe = mirror.RefinedType((parents map (_.tpe)).toList, newScope)
override def toString = parents.mkString(" with ")
}
}
diff --git a/src/library/scala/reflect/api/Mirror.scala b/src/library/scala/reflect/api/Mirror.scala
index b6a9304617..94b6eeeb43 100644
--- a/src/library/scala/reflect/api/Mirror.scala
+++ b/src/library/scala/reflect/api/Mirror.scala
@@ -5,7 +5,7 @@ package api
* runtime entities such as class names and object instances
* with a refexive universe.
*/
-trait Mirror extends Universe {
+trait Mirror extends Universe with RuntimeTypes {
/** The Scala class symbol that has given fully qualified name
* @param name The fully qualified name of the class to be returned
@@ -29,7 +29,39 @@ trait Mirror extends Universe {
*/
def getType(obj: AnyRef): Type
+ /** The value of a field on a receiver instance.
+ * @param receiver The receiver instance
+ * @param field The field
+ * @return The value contained in `receiver.field`.
+ */
def getValue(receiver: AnyRef, field: Symbol): Any
+
+ /** Sets the value of a field on a receiver instance.
+ * @param receiver The receiver instance
+ * @param field The field
+ * @param value The new value to be stored in the field.
+ */
def setValue(receiver: AnyRef, field: Symbol, value: Any): Unit
+
+ /** Invokes a method on a reciver instance with some arguments
+ * @param receiver The receiver instance
+ * @param meth The method
+ * @param args The method call's arguments
+ * @return The result of invoking `receiver.meth(args)`
+ */
def invoke(receiver: AnyRef, meth: Symbol, args: Any*): Any
-} \ No newline at end of file
+
+ /** Maps a Java class to a Scala type reference
+ * @param clazz The Java class object
+ * @return A type (of kind `TypeRef`, or `ExistentialType` if `clazz` is polymorphic)
+ * that represents the class with all type parameters unknown
+ * (i.e. any type parameters of `clazz` are existentially quantified).
+ * */
+ def classToType(clazz: java.lang.Class[_]): Type
+
+ /** Maps a Java class to a Scala class symbol
+ * @param clazz The Java class object
+ * @return A symbol that represents the Scala view of the class.
+ */
+ def classToSymbol(clazz: java.lang.Class[_]): Symbol
+}
diff --git a/src/library/scala/reflect/api/RuntimeTypes.scala b/src/library/scala/reflect/api/RuntimeTypes.scala
new file mode 100644
index 0000000000..f58b328868
--- /dev/null
+++ b/src/library/scala/reflect/api/RuntimeTypes.scala
@@ -0,0 +1,20 @@
+package scala.reflect
+package api
+
+/** A mirror establishes connections of
+ * runtime entities such as class names and object instances
+ * with a refexive universe.
+ */
+private[reflect] trait RuntimeTypes extends Universe {
+
+ type InstanceRefSymbol >: Null <: Symbol
+
+ val InstanceRefSymbol: InstanceRefSymbolExtractor
+
+ private[reflect] def namedType(pre: Type, sym: Symbol, args: List[Type]): Type
+
+ abstract class InstanceRefSymbolExtractor {
+ def apply(value: AnyRef): InstanceRefSymbol
+ def unapply(tpe: InstanceRefSymbol): Option[AnyRef]
+ }
+}
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index c2fed361f0..0f0fdf06af 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -84,6 +84,10 @@ trait Symbols { self: Universe =>
*/
def typeOfThis: Type
+ /** The type `C.this`, where `C` is the current class.
+ */
+ def thisType: Type
+
/** For a class: the module or case class factory with the same name in the same package.
* For all others: NoSymbol
*/
diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala
index 646c93ad5f..0f6cdcd2e9 100755
--- a/src/library/scala/reflect/api/Types.scala
+++ b/src/library/scala/reflect/api/Types.scala
@@ -6,6 +6,7 @@ trait Types { self: Universe =>
abstract class AbsType {
def typeSymbol: Symbol
def decl(name: Name): Symbol
+ def member(name: Name): Symbol
}
type Type >: Null <: AbsType