summaryrefslogblamecommitdiff
path: root/src/reflect/scala/reflect/macros/Context.scala
blob: 1f6e97adbc371c753fb1f328bd38015850414672 (plain) (tree)
1
2
3
4
5
6
7
                     
              


                                                                         
                                                                                                                   
 


















                                                                                                                      
                             
                                

                              
                               
                                    
                            
                             
                           
                                 
 
                                   

                        
                                                 
                             
 


                                                                   

                 


























                                                                                               
                                                                                   








                                                                                                      
                              
 
package scala.reflect
package macros

// todo. introduce context hierarchy
// the most lightweight context should just expose the stuff from the SIP
// the full context should include all traits from scala.reflect.macros (and probably reside in scala-compiler.jar)

/** The Scala macros context.
 *
 *  See [[scala.reflect.macros.package the overview page]] for a description of how macros work. This documentation
 *  entry provides information on the API available to macro writers.
 *
 *  A macro context wraps a compiler universe exposed in `universe` and having type [[scala.reflect.macros.Universe]].
 *  This type is a refinement over the generic reflection API provided in [[scala.reflect.api.Universe]]. The
 *  extended Universe provides mutability for reflection artifacts (e.g. macros can change types of compiler trees,
 *  add annotation to symbols representing definitions, etc) and exposes some internal compiler functionality
 *  such as `Symbol.deSkolemize` or `Tree.attachments`.
 *
 *  Another fundamental part of a macro context is `macroApplication`, which provides access to the tree undergoing
 *  macro expansion. Parts of this tree can be found in arguments of the corresponding macro implementations and
 *  in `prefix`, but `macroApplication` gives the full picture.
 *
 *  Other than that, macro contexts provide facilities for typechecking, exploring the compiler's symbol table and
 *  enclosing trees and compilation units, evaluating trees, logging warnings/errors and much more.
 *  Refer to the documentation of top-level traits in this package to learn the details.
 */
trait Context extends Aliases
                 with Enclosures
                 with Names
                 with Reifiers
                 with FrontEnds
                 with Infrastructure
                 with Typers
                 with Parsers
                 with Evals
                 with ExprUtils {

  /** The compile-time universe. */
  val universe: Universe

  /** The mirror of the compile-time universe. */
  val mirror: universe.Mirror

  /** The type of the prefix tree from which the macro is selected.
   *  See the documentation entry for `prefix` for an example.
   */
  type PrefixType

  /** The prefix tree from which the macro is selected.
   *
   *  For a example, for a macro `filter` defined as an instance method on a collection `Coll`,
   *  `prefix` represents an equivalent of `this` for normal instance methods:
   *
   *  {{{
   *  scala> class Coll[T] {
   *       | def filter(p: T => Boolean): Coll[T] = macro M.filter[T]
   *       | }; object M {
   *       | def filter[T](c: Context { type PrefixType = Coll[T] })
   *       |              (p: c.Expr[T => Boolean]): c.Expr[Coll[T]] =
   *       |   {
   *       |     println(c.prefix.tree)
   *       |     c.prefix
   *       |   }
   *       | }
   *  defined class Coll
   *  defined module Macros
   *
   *  scala> new Coll[Int]().filter(_ % 2 == 0)
   *  new Coll[Int]()
   *  res0: Coll[Int] = ...
   *
   *  scala> val x = new Coll[String]()
   *  x: Coll[String] = ...
   *
   *  scala> x.filter(_ != "")
   *  \$line11.\$read.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.x
   *  res1 @ 35563b4b: x.type = ...
   *  }}}
   *
   *  Note how the value of `prefix` changes depending on the qualifier of the macro call
   *  (i.e. the expression that is at the left-hand side of the dot).
   *
   *  Another noteworthy thing about the snippet above is the `Context { type PrefixType = Coll[T] }`
   *  type that is used to stress that the macro implementation works with prefixes of type `Coll[T]`.
   */
  val prefix: Expr[PrefixType]
}