summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/api/Universe.scala
diff options
context:
space:
mode:
authorHeather Miller <heather.miller@epfl.ch>2012-10-11 20:31:42 +0200
committerHeather Miller <heather.miller@epfl.ch>2012-10-11 20:31:42 +0200
commite95a00992599f59f7c74bcc171bb290f859ab848 (patch)
treefcafe4836f532311790b32c46180c4222fd933b7 /src/reflect/scala/reflect/api/Universe.scala
parentb55ca84dbc34f3337d4e95df3a045156d71f77d7 (diff)
downloadscala-e95a00992599f59f7c74bcc171bb290f859ab848.tar.gz
scala-e95a00992599f59f7c74bcc171bb290f859ab848.tar.bz2
scala-e95a00992599f59f7c74bcc171bb290f859ab848.zip
Adds lots of new documentation for TypeTags, Mirrors, Universes and more
Additionally includes improvements, formatting fixes, and link additions and fixes.
Diffstat (limited to 'src/reflect/scala/reflect/api/Universe.scala')
-rw-r--r--src/reflect/scala/reflect/api/Universe.scala131
1 files changed, 34 insertions, 97 deletions
diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala
index d9be73fde9..7d1f5c9df1 100644
--- a/src/reflect/scala/reflect/api/Universe.scala
+++ b/src/reflect/scala/reflect/api/Universe.scala
@@ -2,13 +2,18 @@ package scala.reflect
package api
/**
- * The Scala reflection cake.
+ * `Universe` provides a complete set of reflection operations which make it possible for one
+ * to reflectively inspect Scala type relations, such as membership or subtyping.
*
- * See [[scala.reflect.api.package the overview page]] for a description of universes and infomation on getting started with Scala reflection API.
- * This page lists the most important layers of the cake, and describes paculiarities of cake APIs.
+ * [[scala.reflect.api.Universe]] has two specialized sub-universes for different scenarios.
+ * [[scala.reflect.api.JavaUniverse]] adds operations that link symbols and types to the underlying
+ * classes and runtime values of a JVM instance-- this can be thought of as the `Universe` that
+ * should be used for all typical use-cases of Scala reflection. [[scala.reflect.macros.Universe]]
+ * adds operations which allow macros to access selected compiler data structures and operations--
+ * this type of `Universe` should only ever exist within the implementation of a Scala macro.
*
- * The reflection library is structured according to the 'cake pattern'. The main layer
- * resides in package [[scala.reflect.api]] and defines an interface to the following main types:
+ * `Universe` can be thought of as the entry point to Scala reflection. It mixes-in, and thus provides
+ * an interface to the following main types:
*
* - [[scala.reflect.api.Types#Type Types]] represent types
* - [[scala.reflect.api.Symbols#Symbol Symbols]] represent definitions
@@ -19,58 +24,32 @@ package api
* - [[scala.reflect.api.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and
* definition trees
* - [[scala.reflect.api.Constants#Constant Constants]] represent compile-time constants.
+ *
+ * To obtain a `Universe` to use with Scala runtime reflection, simply make sure to use or import
+ * `scala.reflect.runtime.universe._`
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> typeOf[List[Int]]
+ * res0: reflect.runtime.universe.Type = scala.List[Int]
+ *
+ * scala> typeOf[Either[String, Int]]
+ * res1: reflect.runtime.universe.Type = scala.Either[String,Int]
+ * }}}
*
- * Each of these types are defined in their own enclosing traits, which are ultimately all inherited by class
- * [[scala.reflect.api.Universe Universe]]. The main 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.macros]] 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.
- *
- * For instance, consider the base type of all abstract syntax trees: [[scala.reflect.api.Trees#Tree]].
- * This type is not a class but is abstract and has an upper bound of [[scala.reflect.api.Trees#TreeApi]],
- * which is a class defining the minimal base interface for all trees.
- *
- * For a more interesting tree type, consider [[scala.reflect.api.Trees#If]] representing if-expressions.
- * It is defined next to a value `If` of type [[scala.reflect.api.Trees#IfExtractor]].
- * This value serves as the companion object defining a factory method `apply` and a corresponding `unapply`
- * for pattern matching.
- *
+ * To obtain a `Universe` for use within a Scala macro, use [[scala.reflect.macros.Context#universe]]. For example:
* {{{
- * 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)
+ * def printf(format: String, params: Any*): Unit = macro impl
+ * def impl(c: Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = {
+ * import c.universe._
+ * ...
+ * }
* }}}
*
- * is equivalent to
- *
- * {{{
- * import scala.reflect.runtime.universe._
- * val iftree = reify{ if( condition ) 1 else 2 }.tree
- * }}}
+ * For more information about `Universe`s, see the [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]]
*
- * and can be pattern matched as
- *
- * {{{
- * iftree match { case If(cond,body,other) => ... }
- * }}}
- *
- * Moreover, there is an implicit value [[scala.reflect.api.Trees#IfTag]] of type
- * `ClassTag[If]` that is used by the Scala compiler so that we can indeed pattern match on `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.
- *
- * To summarize: each tree type `X` (and similarly for other types such as `Type` or `Symbol`) is represented
- * by an abstract type `X`, optionally together with a class `XApi` that defines `X`'s' interface.
- * `X`'s companion object, if it exists, is represented by a value `X` that is of type `XExtractor`.
- * Moreover, for each type `X`, there is a value `XTag` of type `ClassTag[X]` that allows to pattern match on `X`.
- * @groupprio Universe -1
+ * @groupprio Universe -1
*
* @contentDiagram hideNodes "*Api"
*/
@@ -93,9 +72,9 @@ abstract class Universe extends Symbols
with Printers
with Importers
{
- /** Produce the abstract syntax tree representing the given Scala expression.
+ /** Use `refiy` to produce the abstract syntax tree representing a given Scala expression.
*
- * For example
+ * For example:
*
* {{{
* val five = reify{ 5 } // Literal(Constant(5))
@@ -105,49 +84,7 @@ abstract class Universe extends Symbols
*
* The produced tree is path dependent on the Universe `reify` was called from.
*
- * Use [[scala.reflect.api.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 ==
- *
- * `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
- *
- * {{{
- * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
- * }}}
- *
- * and returns a tree, which produces the tree above, when compiled and executed. So in other terms, the refiy call expands to something like
- *
- * {{{
- * val $u: u.type = u // where u is a reference to the Universe that calls the reify
- * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1))))))
- * }}}
- *
- * ------
- *
- * Reification performs expression splicing (when processing Expr.splice)
- * and type splicing (for every type T that has a TypeTag[T] implicit in scope):
- *
- * {{{
- * val two = mirror.reify(2) // Literal(Constant(2))
- * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("\$plus")), List(two.tree))
- *
- * def macroImpl[T](c: Context) = {
- * ...
- * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion
- * // however, if T were annotated with c.WeakTypeTag (which would declare an implicit parameter for macroImpl)
- * // then reification would substitute T with the TypeTree that was used in a TypeApply of this particular macro invocation
- * val factory = c.reify{ new Queryable[T] }
- * ...
- * }
- * }}}
- *
- * 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 `FreeTermSymbol` or `FreeTypeSymbol`
- * - Mutable variables that are accessed from a local function are wrapped in refs
+ * Use [[scala.reflect.api.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.
* @group Universe
*/
// implementation is hardwired to `scala.reflect.reify.Taggers`