diff options
author | Martin Odersky <odersky@gmail.com> | 2011-11-15 18:33:07 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-11-15 18:33:07 +0000 |
commit | 8a64ed85b9a63fd08c13f6730f038ba233d27fb6 (patch) | |
tree | 02770db6dbae39192acd196205b9c45bb0df017a /src/library | |
parent | 7abc466d64681ea7f2610068702019fee66b0579 (diff) | |
download | scala-8a64ed85b9a63fd08c13f6730f038ba233d27fb6.tar.gz scala-8a64ed85b9a63fd08c13f6730f038ba233d27fb6.tar.bz2 scala-8a64ed85b9a63fd08c13f6730f038ba233d27fb6.zip |
Towards better reflection APIs.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/reflect/Code.scala | 2 | ||||
-rw-r--r-- | src/library/scala/reflect/Manifest.scala | 20 | ||||
-rw-r--r-- | src/library/scala/reflect/api/Mirror.scala | 20 | ||||
-rwxr-xr-x | src/library/scala/reflect/api/Symbols.scala | 47 | ||||
-rw-r--r-- | src/library/scala/reflect/api/Trees.scala | 6 | ||||
-rwxr-xr-x | src/library/scala/reflect/api/Types.scala | 396 |
6 files changed, 438 insertions, 53 deletions
diff --git a/src/library/scala/reflect/Code.scala b/src/library/scala/reflect/Code.scala index 65954c7970..52705d302c 100644 --- a/src/library/scala/reflect/Code.scala +++ b/src/library/scala/reflect/Code.scala @@ -13,7 +13,7 @@ package scala.reflect /** This type is required by the compiler and <b>should not be used in client code</b>. */ class Code[T: Manifest](val tree: scala.reflect.mirror.Tree) { val manifest = implicitly[Manifest[T]] - override def toString = "Code(manifest = " + manifest + ")" + override def toString = "Code(tree = "+tree+", manifest = "+manifest+")" } /** This type is required by the compiler and <b>should not be used in client code</b>. */ diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 9151b0c2a7..df5f64cdf6 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -284,4 +284,24 @@ object Manifest { override lazy val tpe = mirror.RefinedType((parents map (_.tpe)).toList, newScope) override def toString = parents.mkString(" with ") } + + /** A generic manifest factory from a reflect.Type. Except where + * mandated by performance considerations, we should replace most + * other manifest factories by this one. There's just one thing + * that needs to be done first: A Manifest's type can refer + * to type variables that are controlled by manifests. In that + * case the reified type needs to contain the type passed in the manifest + * instead of the reference to the manifest. Note that splicing manifests + * into manfifests is completely analogous to splicing code blocks into + * code blocks. Manifest[T] and Code[T] are really the same thing, only one + * works for types, the other for trees. + * Another complication is that once we generate manifests from types, we really + * should have reflection as a standard component shipped with the standard library, + * instead of in scala-compiler.jar. + */ + def apply[T](_tpe: mirror.Type): Manifest[T] = new Manifest[T] { + override lazy val tpe = _tpe + override def erasure = mirror.typeToClass(_tpe.erasedType) + override def toString = _tpe.toString + } } diff --git a/src/library/scala/reflect/api/Mirror.scala b/src/library/scala/reflect/api/Mirror.scala index 9dc861464a..53ac84f8cb 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 with RuntimeTypes { +trait Mirror extends Universe with RuntimeTypes with TreeBuildUtil { /** The Scala class symbol that has given fully qualified name * @param name The fully qualified name of the class to be returned @@ -65,17 +65,15 @@ trait Mirror extends Universe with RuntimeTypes { */ def classToSymbol(clazz: java.lang.Class[_]): Symbol -/* - /** Selects term symbol with given name and type from the defined members of prefix type - * @pre The prefix type - * @name The name of the selected member - * @tpe The type of the selected member + /** Maps a Scala type to the corresponding Java class object */ - def selectTerm(pre: Type, name: String, tpe: Type) : Symbol + def typeToClass(tpe: Type): java.lang.Class[_] - /** Selects type symbol with given name from the defined members of prefix type + /** Maps a Scala symbol to the corresponding Java class object + * @throws ClassNotFoundException if there is no Java class + * corresponding to the given Scala symbol. + * Note: If the Scala symbol is ArrayClass, a ClassNotFound exception is thrown + * because there is no unique Java class corresponding to a Scala generic array */ - def selectType(pre: Type, name: String): Symbol - -*/ + def symbolToClass(sym: Symbol): java.lang.Class[_] } diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala index 0f0fdf06af..3c4408aacd 100755 --- a/src/library/scala/reflect/api/Symbols.scala +++ b/src/library/scala/reflect/api/Symbols.scala @@ -103,10 +103,10 @@ trait Symbols { self: Universe => */ def sourceModule: Symbol - /** If symbol is an object definition, it's implied associated class, + /** If symbol is an object definition, its implied associated class, * otherwise NoSymbol */ - def moduleClass: Symbol + def moduleClass: Symbol // needed for LiftCode /** The top-level class containing this symbol. */ def toplevelClass: Symbol @@ -122,6 +122,49 @@ trait Symbols { self: Universe => def isClass : Boolean def isAliasType : Boolean def isAbstractType : Boolean + + /** The type signature of this symbol. + * Note if symbol is a member of a class, one almost always is interested + * in `typeSigIn` with a site type instead. + */ + def typeSig: Type + + /** The type signature of this symbol seen as a member of given type `site`. + */ + def typeSigIn(site: Type): Type + + /** The type constructor corresponding to this type symbol. + */ + def asTypeConstructor: Type // needed by LiftCode + + /** A type reference that refers to this type symbol + * Note if symbol is a member of a class, one almost always is interested + * in `asTypeIn` with a site type instead. + */ + def asType: Type + + /** A type reference that refers to this type symbol seen as a member of given type `site`. + */ + def asTypeIn(site: Type): Type + + /** A fresh symbol with given position `pos` and name `name` that has + * the current symbol as its owner. + */ + def newNestedSymbol(pos: Position, name: Name): Symbol // needed by LiftCode + + /** Low-level operation to set the symbol's flags + * @return the symbol itself + */ + def setInternalFlags(flags: Long): this.type // needed by LiftCode + + /** Set symbol's type signature to given type + * @return the symbol itself + */ + def setTypeSig(tpe: Type): this.type // needed by LiftCode + + /** Set symbol's annotations to given annotations `annots`. + */ + def setAnnotations(annots: AnnotationInfo*): this.type // needed by LiftCode } val NoSymbol: Symbol diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index de01c0b862..3e5dae739d 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -542,9 +542,15 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => case class Select(qualifier: Tree, name: Name) extends RefTree + def Select(qualifier: Tree, sym: Symbol): Select = + Select(qualifier, sym.name) setSymbol sym + /** Identifier <name> */ case class Ident(name: Name) extends RefTree { } + def Ident(sym: Symbol): Ident = + Ident(sym.name) setSymbol sym + class BackQuotedIdent(name: Name) extends Ident(name) /** Literal */ diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala index 0f6cdcd2e9..75189d51cb 100755 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/api/Types.scala @@ -3,46 +3,324 @@ package api trait Types { self: Universe => + /** This class declares operations that are visible in a Type. + */ abstract class AbsType { + + /** The type symbol associated with the type, or `NoSymbol` for types + * that do not refer to a type symbol. + */ def typeSymbol: Symbol - def decl(name: Name): Symbol + + /** The defined or declared members with name `name` in this type; + * an OverloadedSymbol if several exist, NoSymbol if none exist. + * Alternatives of overloaded symbol appear in the order they are declared. + */ + def declaration(name: Name): Symbol + + /** The member with given name, either directly declared or inherited, + * an OverloadedSymbol if several exist, NoSymbol if none exist. + */ def member(name: Name): Symbol + + /** The non-private member with given name, either directly declared or inherited, + * an OverloadedSymbol if several exist, NoSymbol if none exist. + */ + def nonPrivateMember(name: Name): Symbol + + /** An iterable containing all members of this type (directly declared or inherited) + * Members appear in the linearization order of their owners. + * Members with the same owner appear in reverse order of their declarations. + */ + def allMembers: Iterable[Symbol] + + /** An iterable containing all non-private members of this type (directly declared or inherited) + * Members appear in the linearization order of their owners. + * Members with the same owner appear in reverse order of their declarations. + */ + def nonPrivateMembers: Iterable[Symbol] + + /** Substitute types in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def subst(from: List[Symbol], to: List[Type]): Type + + /** If this is a parameterized types, the type arguments. + * Otherwise the empty list + */ + def typeArguments: List[Type] + + /** Is this type a type constructor that is missing its type arguments? + */ + def isHigherKinded: Boolean + + /** + * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes. + * Functions on types are also implemented as PolyTypes. + * + * Example: (in the below, <List> is the type constructor of List) + * TypeRef(pre, <List>, List()) is replaced by + * PolyType(X, TypeRef(pre, <List>, List(X))) + */ + def normalize: Type + + /** Does this type conform to given type argument `that`? */ + def <:< (that: Type): Boolean + + /** Is this type equivalent to given type argument `that`? */ + def =:= (that: Type): Boolean + + /** The list of all baseclasses of this type (including its own typeSymbol) + * in reverse linearization order, starting with the class itself and ending + * in class Any. + */ + def baseClasses: List[Symbol] + + /** The least type instance of given class which is a supertype + * of this type. Example: + * {{{ + * class D[T] + * class C extends p.D[Int] + * ThisType(C).baseType(D) = p.D[Int] + * }}} + */ + def baseType(clazz: Symbol): Type + + /** This type as seen from prefix `pre` and class `clazz`. This means: + * Replace all thistypes of `clazz` or one of its subclasses + * by `pre` and instantiate all parameters by arguments of `pre`. + * Proceed analogously for thistypes referring to outer classes. + * + * Example: + * class D[T] { def m: T } + * class C extends p.D[Int] + * T.asSeenFrom(ThisType(C), D) (where D is owner of m) + * = Int + */ + def asSeenFrom(pre: Type, clazz: Symbol): Type + + /** The erased type corresponding to this type after + * all transcformations from Scala to Java have been performed. + */ + def erasedType: Type + + /** Apply `f` to each part of this type, returning + * a new type. children get mapped before their parents */ + def map(f: Type => Type): Type + + /** Apply `f` to each part of this type, for side effects only */ + def foreach(f: Type => Unit) + + /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`, + * or None if none exists. + */ + def find(p: Type => Boolean): Option[Type] + + /** Is there part of this type which satisfies predicate `p`? */ + def exists(p: Type => Boolean): Boolean + + /** Does this type contain a reference to given symbol? */ + def contains(sym: Symbol): Boolean } + /** This class declares methods that are visible in a `SingleType`. + */ + trait AbsSingletonType extends AbsType { + + /** The type underlying a singleton type */ + def underlying: Type + + /** Widen from singleton type to its underlying non-singleton + * base type by applying one or more `underlying` dereferences, + * identity for all other types. + * + * class Outer { class C ; val x: C } + * val o: Outer + * <o.x.type>.widen = o.C + */ + def widen: Type + } + + /** This class declares methods that are visible in a `CompoundType` (i.e. + * a class/trait/object template or refined type of the form + * {{{ + * P_1 with ... with P_m { D_1; ...; D_n } + * }}} + * P_n + */ + trait AbsCompoundType extends AbsType { + + /** The list of parent types of this compound type */ + def parents: List[Type] + + /** The collection of declarations in this compound type + */ + def allDeclarations: Iterable[Symbol] + } + + /** The type of Scala types, and also Scala type signatures. + * (No difference is internally made between the two). + */ type Type >: Null <: AbsType + + /** The type of Scala singleton types, i.e. types that are inhabited + * by only one nun-null value. These include types of the forms + * {{{ + * C.this.type + * C.super.type + * x.type + * }}} + * as well as constant types. + */ type SingletonType >: Null <: Type + /** This constant is used as a special value that indicates that no meaningful type exists. + */ val NoType: Type + + /** This constant is used as a special value denoting the empty prefix in a path dependent type. + * For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for + * the symbol for `x`. + */ val NoPrefix: Type + /** The `ThisType` type describes types of the form on the left with the + * correspnding ThisType representations to the right. + * {{{ + * C.this.type ThisType(C) + * }}} + */ type ThisType <: SingletonType + + /** The constructor/deconstructor for `ThisType` instances. */ val ThisType: ThisTypeExtractor + /** An extractor class to create and pattern match with syntax `ThisType(sym)` + * where `sym` is the class prefix of the this type. + */ + abstract class ThisTypeExtractor { + def apply(sym: Symbol): Type + def unapply(tpe: ThisType): Option[Symbol] + } + + /** The `TypeRef` type describes types of any of the forms on the left, + * with their TypeRef representations to the right. + * {{{ + * T # C[T_1, ..., T_n] TypeRef(T, C, List(T_1, ..., T_n)) + * p.C[T_1, ..., T_n] TypeRef(p.type, C, List(T_1, ..., T_n)) + * C[T_1, ..., T_n] TypeRef(NoPrefix, C, List(T_1, ..., T_n)) + * T # C TypeRef(T, C, Nil) + * p.C TypeRef(p.type, C, Nil) + * C TypeRef(NoPrefix, C, Nil) + * }}} + */ type TypeRef <: Type + + /** The constructor/deconstructor for `TypeRef` instances. */ val TypeRef: TypeRefExtractor + /** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)` + * Here, `pre` is the prefix of the type reference, `sym` is the symbol + * referred to by the type reference, and `args` is a possible empty list of + * type argumenrts. + */ + abstract class TypeRefExtractor { + def apply(pre: Type, sym: Symbol, args: List[Type]): Type + def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] + } + + /** The `SingleType` type describes types of any of the forms on the left, + * with their TypeRef representations to the right. + * {{{ + * (T # x).type SingleType(T, x) + * p.x.type SingleType(p.type, x) + * x.type SingleType(NoPrefix, x) + */ type SingleType <: SingletonType + + /** The constructor/deconstructor for `SingleType` instances. */ val SingleType: SingleTypeExtractor + /** An extractor class to create and pattern match with syntax `SingleType(pre, sym)` + * Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol + * referred to by the single-type. + */ + abstract class SingleTypeExtractor { + def apply(pre: Type, sym: Symbol): Type + def unapply(tpe: SingleType): Option[(Type, Symbol)] + } + + /** The `SuperType` type is not directly written, but arises when `C.super` is used + * as a prefix in a `TypeRef` or `SingleType`. It's internal presentation is + * {{{ + * SuperType(thistpe, supertpe) + * }}} + * Here, `thistpe` is the type of the corresponding this-type. For instance, + * in the type arising from C.super, the `thistpe` part would be `ThisType(C)`. + * `supertpe` is the type of the super class referred to by the `super`. + */ type SuperType <: SingletonType + + /** The constructor/deconstructor for `SuperType` instances. */ val SuperType: SuperTypeExtractor - type TypeBounds <: Type - val TypeBounds: TypeBoundsExtractor + /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)` + */ + abstract class SuperTypeExtractor { + def apply(thistpe: Type, supertpe: Type): Type + def unapply(tpe: SuperType): Option[(Type, Type)] + } + + /** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant. + * The REPL expresses constant types like Int(11). Here are some constants with their types. + * {{{ + * 1 ConstantType(Constant(1)) + * "abc" ConstantType(Constant("abc")) + * }}} + */ + type ConstantType <: SingletonType + + /** The constructor/deconstructor for `ConstantType` instances. */ + val ConstantType: ConstantTypeExtractor - type CompoundType <: Type + /** An extractor class to create and pattern match with syntax `ConstantType(constant)` + * Here, `constant` is the constant value represented by the type. + */ + abstract class ConstantTypeExtractor { + def apply(value: Constant): ConstantType + def unapply(tpe: ConstantType): Option[Constant] + } + /** A subtype of Type representing refined types as well as `ClassInfo` signatures. + */ + type CompoundType <: /*AbsCompoundType with*/ Type + + /** The `RefinedType` type defines types of any of the forms on the left, + * with their RefinedType representations to the right. + * {{{ + * P_1 with ... with P_m { D_1; ...; D_n} RefinedType(List(P_1, ..., P_m), Scope(D_1, ..., D_n)) + * P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope()) + * { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n)) + * }}} + */ type RefinedType <: CompoundType - val RefinedType: RefinedTypeExtractor - type ClassInfoType <: CompoundType - val ClassInfoType: ClassInfoTypeExtractor + /** The constructor/deconstructor for `RefinedType` instances. */ + val RefinedType: RefinedTypeExtractor - type ConstantType <: Type - val ConstantType: ConstantTypeExtractor + /** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)` + * Here, `parents` is the list of parent types of the class, and `decls` is the scope + * containing all declarations in the class. + */ + abstract class RefinedTypeExtractor { + def apply(parents: List[Type], decls: Scope): RefinedType - type MethodType <: Type - val MethodType: MethodTypeExtractor + /** An alternative constructor that passes in the synthetic classs symbol + * that backs the refined type. (Normally, a fresh class symbol is created automatically). + */ + def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType + def unapply(tpe: RefinedType): Option[(List[Type], Scope)] + } type NullaryMethodType <: Type val NullaryMethodType: NullaryMethodTypeExtractor @@ -56,51 +334,85 @@ trait Types { self: Universe => type AnnotatedType <: Type val AnnotatedType: AnnotatedTypeExtractor - abstract class ThisTypeExtractor { - def apply(sym: Symbol): Type - def unapply(tpe: ThisType): Option[Symbol] - } + /** The `MethodType` type signature is used to indicate parameters and result type of a method + */ + type MethodType <: Type - abstract class SingleTypeExtractor { - def apply(pre: Type, sym: Symbol): Type - def unapply(tpe: SingleType): Option[(Type, Symbol)] - } + /** The constructor/deconstructor for `MethodType` instances. */ + val MethodType: MethodTypeExtractor - abstract class SuperTypeExtractor { - def apply(thistpe: Type, supertpe: Type): Type - def unapply(tpe: SuperType): Option[(Type, Type)] + /** An extractor class to create and pattern match with syntax `MethodType(params, respte)` + * Here, `params` is a potentially empty list of parameter symbols of the method, + * and `restpe` is the result type of the method. If the method is curried, `restpe` would + * be another `MethodType`. + * Note: `MethodType(Nil, Int)` would be the type of a method defined with an empty parameter list. + * {{{ + * def f(): Int + * }}} + * If the method is completely parameterless, as in + * {{{ + * def f: Int + * }}} + * its type is a `NullaryMethodType`. + */ + abstract class MethodTypeExtractor { + def apply(params: List[Symbol], resultType: Type): MethodType + def unapply(tpe: MethodType): Option[(List[Symbol], Type)] } - abstract class TypeRefExtractor { - def apply(pre: Type, sym: Symbol, args: List[Type]): Type - def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] - } + /** The `TypeBounds` type signature is used to indicate lower and upper type bounds + * of type parameters and abstract types. It is not a first-class type. + * If an abstract type or type parameter is declared with any of the forms + * on the left, its type signature is the TypeBounds type on the right. + * {{{ + * T >: L <: U TypeBounds(L, U) + * T >: L TypeBounds(L, Any) + * T <: U TypeBounds(Nothing, U) + * }}} + */ + type TypeBounds <: Type + + /** The constructor/deconstructor for `TypeBounds` instances. */ + val TypeBounds: TypeBoundsExtractor + /** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)` + * Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is + * the upper bound. + */ abstract class TypeBoundsExtractor { def apply(lo: Type, hi: Type): TypeBounds def unapply(tpe: TypeBounds): Option[(Type, Type)] } - abstract class RefinedTypeExtractor { - def apply(parents: List[Type], decls: Scope): RefinedType - def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType - def unapply(tpe: RefinedType): Option[(List[Type], Scope)] - } + /** The `ClassInfo` type signature is used to define parents and declarations + * of classes, traits, and objects. If a class, trait, or object C is declared like this + * {{{ + * C extends P_1 with ... with P_m { D_1; ...; D_n} + * }}} + * its `ClassInfo` type has the following form: + * {{{ + * ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C) + * }}} + */ + type ClassInfoType <: CompoundType + /** The constructor/deconstructor for `ClassInfoType` instances. */ + val ClassInfoType: ClassInfoTypeExtractor + + /** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)` + * Here, `parents` is the list of parent types of the class, `decls` is the scope + * containing all declarations in the class, and `clazz` is the symbol of the class + * itself. + */ abstract class ClassInfoTypeExtractor { def apply(parents: List[Type], decls: Scope, clazz: Symbol): ClassInfoType def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] } - abstract class ConstantTypeExtractor { - def apply(value: Constant): ConstantType - def unapply(tpe: ConstantType): Option[Constant] - } - abstract class MethodTypeExtractor { - def apply(params: List[Symbol], resultType: Type): MethodType - def unapply(tpe: MethodType): Option[(List[Symbol], Type)] - } + + + abstract class NullaryMethodTypeExtractor { def apply(resultType: Type): NullaryMethodType @@ -121,5 +433,11 @@ trait Types { self: Universe => def apply(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol): AnnotatedType def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)] } + + /** The least upper bound wrt <:< of a list of types */ + def lub(xs: List[Type]): Type + + /** The greatest lower bound wrt <:< of a list of types */ + def glb(ts: List[Type]): Type } |