diff options
author | Martin Odersky <odersky@gmail.com> | 2011-08-15 12:00:44 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-08-15 12:00:44 +0000 |
commit | 5522aeafa7ac3c5c8cdd6be4fa13afe52b558445 (patch) | |
tree | c20019707f702edd7c2aa9ed1eb40bc04300c3a1 /src/library | |
parent | 3fff0d0caf8a65c7bd8826f23f1a1e12be802ccd (diff) | |
download | scala-5522aeafa7ac3c5c8cdd6be4fa13afe52b558445.tar.gz scala-5522aeafa7ac3c5c8cdd6be4fa13afe52b558445.tar.bz2 scala-5522aeafa7ac3c5c8cdd6be4fa13afe52b558445.zip |
Linked Manifests up with Reflection.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/reflect/ClassManifest.scala | 47 | ||||
-rw-r--r-- | src/library/scala/reflect/Manifest.scala | 18 | ||||
-rw-r--r-- | src/library/scala/reflect/api/Mirror.scala | 36 | ||||
-rw-r--r-- | src/library/scala/reflect/api/RuntimeTypes.scala | 20 | ||||
-rwxr-xr-x | src/library/scala/reflect/api/Symbols.scala | 4 | ||||
-rwxr-xr-x | src/library/scala/reflect/api/Types.scala | 1 |
6 files changed, 109 insertions, 17 deletions
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 |