From ecbb25a311daee09be6ec67bd482d5d6e1ee0fea Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Wed, 19 Sep 2012 12:15:53 +0200 Subject: improved/fixed reflection docs based on comments --- src/library/scala/reflect/ClassTag.scala | 4 +-- src/library/scala/reflect/base/Annotations.scala | 21 ++++++------ src/library/scala/reflect/base/Attachments.scala | 14 +++++--- src/library/scala/reflect/base/Exprs.scala | 23 +++++++++++-- src/library/scala/reflect/base/MirrorOf.scala | 2 +- src/library/scala/reflect/base/Mirrors.scala | 5 ++- src/library/scala/reflect/base/Names.scala | 8 ++--- .../scala/reflect/base/StandardDefinitions.scala | 2 +- src/library/scala/reflect/base/Symbols.scala | 6 ++-- src/library/scala/reflect/base/TreeCreator.scala | 20 +++++++++++ src/library/scala/reflect/base/Trees.scala | 34 ++++++++++--------- src/library/scala/reflect/base/TypeCreator.scala | 20 +++++++++++ src/library/scala/reflect/base/TypeTags.scala | 17 ++++++---- src/library/scala/reflect/base/Universe.scala | 10 +++--- src/library/scala/reflect/package.scala | 39 +++++++++++++++++----- 15 files changed, 155 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 0bafa7c505..1a574836c0 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -9,10 +9,10 @@ import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass } * * If an implicit value of type ClassTag[T] is requested, the compiler will create one. * The runtime class (i.e. the erasure, a java.lang.Class on the JVM) of T can be accessed - * via the `runtimeClass` field. References to type parameters or abstract types are + * via the `runtimeClass` field. References to type parameters or abstract type members are * replaced by the concrete types if ClassTags are available for them. * - * Besides accessing the erasure, a ClassTag knows how instantiate single- and multi- + * Besides accessing the erasure, a ClassTag knows how to instantiate single- and multi- * dimensional `Arrays` where the element type is unknown at compile time. * * [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]]. diff --git a/src/library/scala/reflect/base/Annotations.scala b/src/library/scala/reflect/base/Annotations.scala index c6ef7b721c..107443f09b 100644 --- a/src/library/scala/reflect/base/Annotations.scala +++ b/src/library/scala/reflect/base/Annotations.scala @@ -10,8 +10,8 @@ trait Annotations { self: Universe => /** Typed information about an annotation. It can be attached to either a symbol or an annotated type. * - * Annotations are either ''Scala annotations'', which conform to [[scala.annotation.Annotation]] or [[scala.annotation.StaticAnnotation]] - * but not [[scala.annotation.ClassfileAnnotation]] or ''Java annotations'', which conform to [[scala.annotation.ClassfileAnnotation]]. + * Annotations are either ''Scala annotations'', which conform to [[scala.annotation.StaticAnnotation]] + * or ''Java annotations'', which conform to [[scala.annotation.ClassfileAnnotation]]. * Trait `ClassfileAnnotation` is automatically added to every Java annotation by the scalac classfile parser. */ type Annotation >: Null <: AnyRef @@ -24,17 +24,16 @@ trait Annotations { self: Universe => /** The constructor/deconstructor for `Annotation` instances. */ val Annotation: AnnotationExtractor - /** An extractor class to create and pattern match with syntax `Annotation(atp, args, javaArgs)`. - * Here, `atp` is the annotation type, `args` the arguments, and `javaArgs` the annotation's key-value + /** An extractor class to create and pattern match with syntax `Annotation(atp, scalaArgs, javaArgs)`. + * Here, `atp` is the annotation type, `scalaArgs` the arguments, and `javaArgs` the annotation's key-value * pairs. * - * Annotations are written to the classfile as Java annotations if `atp` conforms to - * `ClassfileAnnotation`. Annotations are pickled, i.e., written to scala symtab attribute in the classfile, - * if `atp` inherits from `StaticAnnotation` but not `ClassfileAnnotation`. + * Annotations are pickled, i.e. written to scala symtab attribute in the classfile. + * Annotations are written to the classfile as Java annotations if `atp` conforms to `ClassfileAnnotation`. * - * For Scala annotations, arguments are stored in `args` and `javaArgs` is empty. Arguments in - * `args` are represented as typed trees. Note that these trees are not transformed by any phases - * following the type-checker. For Java annotations, `args` is empty and arguments are stored in + * For Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty. Arguments in + * `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases + * following the type-checker. For Java annotations, `scalaArgs` is empty and arguments are stored in * `javaArgs`. */ abstract class AnnotationExtractor { @@ -85,7 +84,7 @@ trait Annotations { self: Universe => def unapply(arg: ArrayArgument): Option[Array[JavaArgument]] } - /** A nested argument to a Java annotation as `@Nested` in `@Outer(@Nested)`. + /** A nested annotation argument to a Java annotation as `@Nested` in `@Outer(@Nested)`. */ type NestedArgument >: Null <: AnyRef with JavaArgument diff --git a/src/library/scala/reflect/base/Attachments.scala b/src/library/scala/reflect/base/Attachments.scala index 0082066fdb..479ab9a857 100644 --- a/src/library/scala/reflect/base/Attachments.scala +++ b/src/library/scala/reflect/base/Attachments.scala @@ -1,8 +1,9 @@ package scala.reflect package base -/** Attachments is a generalisation of Position. Typically it stores a Position of a tree, but this can be extended to - * encompass arbitrary payloads. +/** Attachments is a generalization of Position. Typically it stores a Position of a tree, but this can be extended to + * encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written + * with `update[T]` and `remove[T]`. * * Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree` * imposing an unnecessary memory tax because of something that will not be used in most cases. @@ -18,7 +19,7 @@ abstract class Attachments { self => /** Creates a copy of this attachment with the position replaced by `newPos` */ def withPos(newPos: Pos): Attachments { type Pos = self.Pos } - /** The underlying payload. */ + /** The underlying payload with the guarantee that no two elements have the same type. */ def all: Set[Any] = Set.empty private def matchesTag[T: ClassTag](datum: Any) = @@ -28,11 +29,14 @@ abstract class Attachments { self => def get[T: ClassTag]: Option[T] = (all filter matchesTag[T]).headOption.asInstanceOf[Option[T]] - /** Creates a copy of this attachment with a new payload added */ + /** Creates a copy of this attachment with the payload slot of T added/updated with the provided value. + * + * Replaces an existing payload of the same type, if exists. + */ def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } = new NonemptyAttachments(this.pos, remove[T].all + attachment) - /** Creates a copy of this attachment with all payloads of the given class type `T` removed. */ + /** Creates a copy of this attachment with the payload of the given class type `T` removed. */ def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = { val newAll = all filterNot matchesTag[T] if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }] diff --git a/src/library/scala/reflect/base/Exprs.scala b/src/library/scala/reflect/base/Exprs.scala index 0fd383e8b2..bd15c65711 100644 --- a/src/library/scala/reflect/base/Exprs.scala +++ b/src/library/scala/reflect/base/Exprs.scala @@ -12,7 +12,10 @@ trait Exprs { self: Universe => trait Expr[+T] extends Equals with Serializable { val mirror: Mirror /** - * Migrates the expression into another universe given its corresponding mirror. + * Migrates the expression into another mirror, jumping into a different universe if necessary. + * + * This means that all symbolic references to classes/objects/packages in the expression + * will be re-resolved within the new mirror (typically using that mirror's classloader). */ def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # Expr[T] @@ -32,6 +35,7 @@ trait Exprs { self: Universe => /** * A dummy method to mark expression splicing in reification. + * * It should only be used within a `reify` call, which eliminates the `splice` call and embeds * the wrapped tree into the reified surrounding expression. * If used alone `splice` throws an exception when called at runtime. @@ -52,10 +56,23 @@ trait Exprs { self: Universe => * {{{ * reify{ expr.foo } * }}} - * because expr of type Expr[T] does not have a method foo. + * because expr of type Expr[T] itself does not have a method foo. */ def splice: T - // TODO: document this + /** + * A dummy value to denote cross-stage path-dependent type dependencies. + * + * For example for the following macro definition: + * {{{ + * class X { type T } + * object Macros { def foo(x: X): x.T = macro Impls.foo_impl } + * }}} + * + * The corresponding macro implementation should have the following signature (note how the return type denotes path-dependency on x): + * {{{ + * object Impls { def foo_impl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ... } + * }}} + */ val value: T /** case class accessories */ diff --git a/src/library/scala/reflect/base/MirrorOf.scala b/src/library/scala/reflect/base/MirrorOf.scala index 6115a622bc..4e54a2fae7 100644 --- a/src/library/scala/reflect/base/MirrorOf.scala +++ b/src/library/scala/reflect/base/MirrorOf.scala @@ -24,7 +24,7 @@ abstract class MirrorOf[U <: base.Universe with Singleton] { /** The module symbol of the `_root_` package */ def RootPackage: U#ModuleSymbol - /** The class symbol of the default (unnamed) package */ + /** The module class symbol of the default (unnamed) package */ def EmptyPackageClass: U#ClassSymbol /** The module symbol of the default (unnamed) package */ diff --git a/src/library/scala/reflect/base/Mirrors.scala b/src/library/scala/reflect/base/Mirrors.scala index 8cb6811dca..e38a3d1cdd 100644 --- a/src/library/scala/reflect/base/Mirrors.scala +++ b/src/library/scala/reflect/base/Mirrors.scala @@ -15,9 +15,8 @@ trait Mirrors { /** The base type of all mirrors of this universe */ type Mirror >: Null <: MirrorOf[self.type] - /** The roor mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`, - * `Nothing`, `Null`, and all classes loaded from scala-library. The root package of this mirror contains the root - * packages of all other mirrors of this universe as members. + /** The root mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`, + * `Nothing`, `Null`, and all classes loaded from scala-library, which are shared across all mirrors within the enclosing universe. */ val rootMirror: Mirror } diff --git a/src/library/scala/reflect/base/Names.scala b/src/library/scala/reflect/base/Names.scala index 8afdb8f69b..b02038a920 100644 --- a/src/library/scala/reflect/base/Names.scala +++ b/src/library/scala/reflect/base/Names.scala @@ -37,10 +37,10 @@ trait Names { /** The base API that all names support */ abstract class NameBase { - /** Checks weather the name is a a term name */ + /** Checks wether the name is a a term name */ def isTermName: Boolean - /** Checks weather the name is a a type name */ + /** Checks wether the name is a a type name */ def isTypeName: Boolean /** Returns a term name that wraps the same string as `this` */ @@ -58,11 +58,11 @@ trait Names { */ def newTypeName(s: String): TypeName - /** Wraps the empty string + /** Wraps the empty string. Can be used as the null object for term name. */ def EmptyTermName: TermName = newTermName("") - /** Wraps the empty string + /** Wraps the empty string. Can be used as the null object for term name. */ def EmptyTypeName: TypeName = EmptyTermName.toTypeName } diff --git a/src/library/scala/reflect/base/StandardDefinitions.scala b/src/library/scala/reflect/base/StandardDefinitions.scala index 6d85ae9d2a..4df8501b3d 100644 --- a/src/library/scala/reflect/base/StandardDefinitions.scala +++ b/src/library/scala/reflect/base/StandardDefinitions.scala @@ -20,7 +20,7 @@ trait StandardDefinitions { /** The class symbol of package `scala`. */ def ScalaPackageClass: ClassSymbol - /** The module symbol of package `scala`. */ + /** The module class symbol of package `scala`. */ def ScalaPackage: ModuleSymbol // top types diff --git a/src/library/scala/reflect/base/Symbols.scala b/src/library/scala/reflect/base/Symbols.scala index efdd4cb19e..4a1eef014c 100644 --- a/src/library/scala/reflect/base/Symbols.scala +++ b/src/library/scala/reflect/base/Symbols.scala @@ -86,10 +86,10 @@ trait Symbols { self: Universe => * that directly contains the current symbol's definition. * The `NoSymbol` symbol does not have an owner, and calling this method * on one causes an internal error. - * The owner of the Scala root class [[scala.reflect.api.mirror.RootClass]] - * and the Scala root object [[scala.reflect.api.mirror.RootPackage]] is `NoSymbol`. + * The owner of the Scala root class [[scala.reflect.base.MirrorOf.RootClass]] + * and the Scala root object [[scala.reflect.base.MirrorOf.RootPackage]] is `NoSymbol`. * Every other symbol has a chain of owners that ends in - * [[scala.reflect.api.mirror.RootClass]]. + * [[scala.reflect.base.MirrorOf.RootClass]]. */ def owner: Symbol diff --git a/src/library/scala/reflect/base/TreeCreator.scala b/src/library/scala/reflect/base/TreeCreator.scala index c9c8de2307..5de0094f1f 100644 --- a/src/library/scala/reflect/base/TreeCreator.scala +++ b/src/library/scala/reflect/base/TreeCreator.scala @@ -1,6 +1,26 @@ package scala.reflect package base +/** A mirror-aware factory for trees. + * + * In the reflection API, artifacts are specific to universes and + * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors. + * + * Therefore to build a tree one needs to know a universe that the tree is going to be bound to + * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int` + * points to a core class `Int` from scala-library.jar). + * + * `TreeCreator` implements this notion by providing a standalone tree factory. + * + * This is immediately useful for reification. When the compiler reifies an expression, + * the end result needs to make sense in any mirror. That's because the compiler knows + * the universe it's reifying an expression into (specified by the target of the `reify` call), + * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM + * it doesn't know what classloader use to resolve symbolic names in the reifee). + * + * Due to a typechecker restriction (no eta-expansion for dependent method types), + * `TreeCreator` can't have a functional type, so it's implemented as class with an apply method. + */ abstract class TreeCreator { def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Tree } diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala index 666870cb10..428b493478 100644 --- a/src/library/scala/reflect/base/Trees.scala +++ b/src/library/scala/reflect/base/Trees.scala @@ -88,7 +88,7 @@ trait Trees { self: Universe => /** The empty tree */ val EmptyTree: Tree - /** A tree for a term. Not all trees are TermTrees; use isTerm + /** A tree for a term. Not all trees representing terms are TermTrees; use isTerm * to reliably identify terms. */ type TermTree >: Null <: AnyRef with Tree @@ -98,7 +98,7 @@ trait Trees { self: Universe => */ implicit val TermTreeTag: ClassTag[TermTree] - /** A tree for a type. Not all trees are TypTrees; use isType + /** A tree for a type. Not all trees representing types are TypTrees; use isType * to reliably identify types. */ type TypTree >: Null <: AnyRef with Tree @@ -250,7 +250,6 @@ trait Trees { self: Universe => */ implicit val ValOrDefDefTag: ClassTag[ValOrDefDef] - // FIXME: document how ValDef in self-types can be recognized. (Only private modifier is set there.) /** Broadly speaking, a value definition. All these are encoded as ValDefs: * * - immutable values, e.g. "val x" @@ -513,7 +512,7 @@ trait Trees { self: Universe => /** Case clause in a pattern match. * (except for occurrences in switch statements). - * Eliminated by compiler phases patmat/explicitouter. + * Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher) */ type CaseDef >: Null <: AnyRef with Tree @@ -538,7 +537,10 @@ trait Trees { self: Universe => def unapply(caseDef: CaseDef): Option[(Tree, Tree, Tree)] } - /** Alternatives of patterns, eliminated by compiler phases patmat/explicitouter, except for + /** Alternatives of patterns. + * + * Eliminated by compiler phases Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher), + * except for * occurrences in encoded Switch stmt (i.e. remaining Match(CaseDef(...))) */ type Alternative >: Null <: TermTree @@ -562,7 +564,8 @@ trait Trees { self: Universe => } /** Repetition of pattern. - * Eliminated by compiler phase patmat/explicitouter. + * + * Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). */ type Star >: Null <: TermTree @@ -585,7 +588,8 @@ trait Trees { self: Universe => } /** Bind a variable to a rhs pattern. - * Eliminated by compiler phase patmat/explicitouter. + * + * Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). * * @param name * @param body @@ -610,12 +614,9 @@ trait Trees { self: Universe => def unapply(bind: Bind): Option[(Name, Tree)] } - // TODO: evaluate if UnApply can be removed or at least moved out of reflection. /** * Used to represent `unapply` methods in pattern matching. * - * Introduced by typer, eliminated by patmat/explicitouter. - * * For example: * {{{ * 2 match { case Foo(x) => x } @@ -637,6 +638,8 @@ trait Trees { self: Universe => * EmptyTree, * Ident(newTermName("x"))))) * }}} + * + * Introduced by typer. Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). */ type UnApply >: Null <: TermTree @@ -705,7 +708,7 @@ trait Trees { self: Universe => * * vparams => body * - * The symbol of a Function is a synthetic TermSymbol having its name set to nme.ANON_FUN_NAME. + * The symbol of a Function is a synthetic TermSymbol. * It is the owner of the function's parameters. */ abstract class FunctionExtractor { @@ -786,10 +789,10 @@ trait Trees { self: Universe => def unapply(if_ : If): Option[(Tree, Tree, Tree)] } - /** - Pattern matching expression (before compiler phase explicitouter) - * - Switch statements (after compiler phase explicitouter) + /** - Pattern matching expression (before compiler phase explicitouter before 2.10 / patmat from 2.10) + * - Switch statements (after compiler phase explicitouter before 2.10 / patmat from 2.10) * - * After compiler phase explicitouter, cases will satisfy the following constraints: + * After compiler phase explicitouter before 2.10 / patmat from 2.10, cases will satisfy the following constraints: * * - all guards are `EmptyTree`, * - all patterns will be either `Literal(Constant(x:Int))` @@ -1002,9 +1005,8 @@ trait Trees { self: Universe => def unapply(apply: Apply): Option[(Tree, List[Tree])] } - // TODO: what is it used for exactly? extend docs! /** Super reference, where `qual` is the corresponding `this` reference. - * A super reference C.super[M] is represented as Super(This(C), M). + * A super reference `C.super[M]` is represented as `Super(This(C), M)`. */ type Super >: Null <: TermTree diff --git a/src/library/scala/reflect/base/TypeCreator.scala b/src/library/scala/reflect/base/TypeCreator.scala index 8a14e53dd3..0260fe1410 100644 --- a/src/library/scala/reflect/base/TypeCreator.scala +++ b/src/library/scala/reflect/base/TypeCreator.scala @@ -1,6 +1,26 @@ package scala.reflect package base +/** A mirror-aware factory for types. + * + * In the reflection API, artifacts are specific to universes and + * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors. + * + * Therefore to build a type one needs to know a universe that the type is going to be bound to + * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int` + * points to a core class `Int` from scala-library.jar). + * + * `TypeCreator` implements this notion by providing a standalone type factory. + * + * This is immediately useful for type tags. When the compiler creates a type tag, + * the end result needs to make sense in any mirror. That's because the compiler knows + * the universe it's creating a type tag for (since `TypeTag` is path-dependent on a universe), + * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM + * it doesn't know what classloader use to resolve symbolic names in the type tag). + * + * Due to a typechecker restriction (no eta-expansion for dependent method types), + * `TypeCreator` can't have a functional type, so it's implemented as class with an apply method. + */ abstract class TypeCreator { def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type } diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala index eeda6cb143..db9fa95553 100644 --- a/src/library/scala/reflect/base/TypeTags.scala +++ b/src/library/scala/reflect/base/TypeTags.scala @@ -20,16 +20,14 @@ import scala.language.implicitConversions /** * A type tag encapsulates a representation of type T. * - * Type tags replace the pre-2.10 concept of a [[scala.reflect.Manifest]] and are much better integrated with reflection. + * Type tags replace the pre-2.10 concept of a [[scala.reflect.Manifest]] and are integrated with reflection. * * === Overview and examples === * * Type tags are organized in a hierarchy of three classes: * [[scala.reflect.ClassTag]], [[scala.reflect.base.Universe#TypeTag]] and [[scala.reflect.base.Universe#WeakTypeTag]]. * - * @see scala.reflect.ClassTag - * @see scala.reflect.base.Universe#TypeTag - * @see scala.reflect.base.Universe#WeakTypeTag + * @see [[scala.reflect.ClassTag]], [[scala.reflect.base.Universe#TypeTag]], [[scala.reflect.base.Universe#WeakTypeTag]] * * Examples: * {{{ @@ -82,8 +80,9 @@ import scala.language.implicitConversions * * {{{ * tag.in( other_mirror ) - * }}} - * + * }}} + * + * See [[scala.reflect.base.TypeTags#WeakTypeTag.in]] * * === WeakTypeTag vs TypeTag === * @@ -163,6 +162,9 @@ trait TypeTags { self: Universe => * * Type tags are path dependent on their universe. This methods allows migration * given the mirror corresponding to the target universe. + * + * Migration means that all symbolic references to classes/objects/packages in the expression + * will be re-resolved within the new mirror (typically using that mirror's classloader). */ def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # WeakTypeTag[T] @@ -306,7 +308,7 @@ trait TypeTags { self: Universe => } } - private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe # TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) { + private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe#TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) { override lazy val tpe: Type = _tpe private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true) } @@ -314,6 +316,7 @@ trait TypeTags { self: Universe => /** * Shortcut for `implicitly[WeakTypeTag[T]]` */ + def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag /** * Shortcut for `implicitly[TypeTag[T]]` diff --git a/src/library/scala/reflect/base/Universe.scala b/src/library/scala/reflect/base/Universe.scala index be1b60933a..0b5d5ed685 100644 --- a/src/library/scala/reflect/base/Universe.scala +++ b/src/library/scala/reflect/base/Universe.scala @@ -28,13 +28,13 @@ abstract class Universe extends Symbols * reify{ five.splice + 4 } // Apply( Select( Literal(Constant(5)), newTermName("$plus")), List( Literal(Constant(4)) ) ) * }}} * - * The produced tree is path dependent on the Universe `refiy` was called from. + * The produced tree is path dependent on the Universe `reify` was called from. * - * Use [[splice]] to embed an existing expression into a reify call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced. + * Use [[scala.reflect.base.Exprs#Expr.splice]] to embed an existing expression into a reify call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced. * * == Further info and implementation details == * - * `refiy` is implemented as a macro, which given an expression, generates a tree that when compiled and executed produces the original tree. + * `reify` is implemented as a macro, which given an expression, generates a tree that when compiled and executed produces the original tree. * * For instance in `reify{ x + 1 }` the macro `reify` receives the abstract syntax tree of `x + 1` as its argument, which is * @@ -71,10 +71,8 @@ abstract class Universe extends Symbols * The transformation looks mostly straightforward, but it has its tricky parts: * - Reifier retains symbols and types defined outside the reified tree, however * locally defined entities get erased and replaced with their original trees - * - Free variables are detected and wrapped in symbols of the type FreeVar + * - Free variables are detected and wrapped in symbols of the type `FreeTermSymbol` or `FreeTypeSymbol` * - Mutable variables that are accessed from a local function are wrapped in refs - * - Since reified trees can be compiled outside of the scope they've been created in, - * special measures are taken to ensure that all members accessed in the reifee remain visible */ // implementation is hardwired to `scala.reflect.reify.Taggers` // using the mechanism implemented in `scala.tools.reflect.FastTrack` diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index e78ec7599a..046491ae10 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -3,23 +3,23 @@ package scala /** * The base package of Scala's reflection library. * - * The refection library is structured according to the 'cake pattern'. The base layer + * The reflection library is structured according to the 'cake pattern'. The base layer * resides in package [[scala.reflect.base]] and defines an interface to the following main types: * * - [[scala.reflect.base.Types#Type Types]] represent types - * - [[scala.reflect.base.Symbol#Symbol Symbols]] represent definitions + * - [[scala.reflect.base.Symbols#Symbol Symbols]] represent definitions * - [[scala.reflect.base.Trees#Tree Trees]] represent abstract syntax trees * - [[scala.reflect.base.Names#Name Names]] represent term and type names - * - [[scala.reflect.base.AnnotationInfos#AnnotationInfo AnnotationInfos]] represent annotations - * - [[scala.reflect.base.Position#Positions Positions]] represent source positions of tree nodes + * - [[scala.reflect.base.Annotations#Annotation Annotations]] represent annotations + * - [[scala.reflect.base.Positions#Position Positions]] represent source positions of tree nodes * - [[scala.reflect.base.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and * definition trees - * - [[scala.reflect.base.Constansts#Constant Constants]] represent compile-time constants. + * - [[scala.reflect.base.Constants#Constant Constants]] represent compile-time constants. * * Each of these types are defined in their own enclosing traits, which are ultimately all inherited by class * [[scala.reflect.base.Universe Universe]]. The base universe defines a minimal interface to the above types. * Universes that provide additional functionality such as deeper introspection or runtime code generation, - * are defined in packages [[scala.reflect.api]] and [[scala.tools.reflect]]. + * are defined in packages [[scala.reflect.api]] and `scala.tools.reflect`. * * The cake pattern employed here requires to write certain Scala idioms with more indirections that usual. * What follows is a description of these indirections, which will help to navigate the Scaladocs easily. @@ -32,10 +32,33 @@ package scala * It does not come with a class `IfBase`, since it does not add anything to the interface of its upper * bound `TermTree`. However, it is defined next to a value `If` of type [[scala.reflect.base.Trees#IfExtractor]]. * This value serves as the companion object defining a factory method `apply` and a corresponding `unapply` - * for pattern matching. Moreover, there is an implicit value [[scala.reflect.base.Trees#IfTag]] of type + * for pattern matching. + * + * {{{ + * import scala.reflect.runtime.universe._ + * val cond = reify{ condition }.tree // <- just some tree representing a condition + * val body = Literal(Constant(1)) + * val other = Literal(Constant(2)) + * val iftree = If(cond,body,other) + * }}} + * + * is equivalent to + * + * {{{ + * import scala.reflect.runtime.universe._ + * val iftree = reify{ if( condition ) 1 else 2 }.tree + * }}} + * + * and can be pattern matched as + * + * {{{ + * iftree match { case If(cond,body,other) => ... } + * }}} + * + * Moreover, there is an implicit value [[scala.reflect.base.Trees#IfTag]] of type * `ClassTag[If]` that is used by the Scala compiler so that we can indeed pattern match on `If`: * {{{ - * tree match { case ifTree: If => ... } + * iftree match { case _:If => ... } * }}} * Without the given implicit value, this pattern match would raise an "unchecked" warning at compile time * since `If` is an abstract type that gets erased at runtime. See [[scala.reflect.ClassTag]] for details. -- cgit v1.2.3