package scala.reflect package macros /** * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span> * * The refinement of [[scala.reflect.api.Universe]] for the use by macro writers. * * This 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`. * @groupname Macros Macro Specific Additions * @groupprio Macros -1 * * @contentDiagram hideNodes "*Api" */ abstract class Universe extends scala.reflect.api.Universe { /** A factory that encapsulates common tree-building functions. * @group Macros */ val treeBuild: TreeBuilder { val global: Universe.this.type } /** The API of reflection artifacts that support [[scala.reflect.macros.Attachments]]. * These artifacts are trees and symbols. * @group Macros */ trait AttachableApi { /** The attachment of the reflection artifact. */ def attachments: Attachments { type Pos = Position } /** Updates the attachment with the payload slot of T added/updated with the provided value. * Replaces an existing payload of the same type, if exists. * Returns the reflection artifact itself. */ def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type /** Update the attachment with the payload of the given class type `T` removed. * Returns the reflection artifact itself. */ def removeAttachment[T: ClassTag]: AttachableApi.this.type } // Symbol extensions --------------------------------------------------------------- /** The `Symbol` API is extended for macros: See [[SymbolContextApi]] for details. * * @group Macros */ override type Symbol >: Null <: SymbolContextApi /** The extended API of symbols that's supported in macro context universes * @group API */ trait SymbolContextApi extends SymbolApi with AttachableApi { self: Symbol => /** If this symbol is a skolem, its corresponding type parameter, otherwise the symbol itself. * * [[https://groups.google.com/forum/#!msg/scala-internals/0j8laVNTQsI/kRXMF_c8bGsJ To quote Martin Odersky]], * skolems are synthetic type "constants" that are copies of existentially bound or universally * bound type variables. E.g. if one is inside the right-hand side of a method: * * {{{ * def foo[T](x: T) = ... foo[List[T]].... * }}} * * the skolem named `T` refers to the unknown type instance of `T` when `foo` is called. It needs to be different * from the type parameter because in a recursive call as in the `foo[List[T]]` above the type parameter gets * substituted with `List[T]`, but the ''type skolem'' stays what it is. * * The other form of skolem is an ''existential skolem''. Say one has a function * * {{{ * def bar(xs: List[T] forSome { type T }) = xs.head * }}} * * then each occurrence of `xs` on the right will have type `List[T']` where `T'` is a fresh copy of `T`. */ def deSkolemize: Symbol /** The position of this symbol. */ def pos: Position /** Sets the `typeSignature` of the symbol. */ def setTypeSignature(tpe: Type): Symbol /** Sets the `annotations` of the symbol. */ def setAnnotations(annots: Annotation*): Symbol /** Sets the `name` of the symbol. */ def setName(name: Name): Symbol /** Sets the `privateWithin` of the symbol. */ def setPrivateWithin(sym: Symbol): Symbol } // Tree extensions --------------------------------------------------------------- /** The `Tree` API is extended for macros: See [[TreeContextApi]] for details. * * @group Macros */ override type Tree >: Null <: TreeContextApi /** The extended API of trees that's supported in macro context universes * @group API */ trait TreeContextApi extends TreeApi with AttachableApi { self: Tree => /** Sets the `pos` of the tree. Returns `Unit`. */ def pos_=(pos: Position): Unit /** Sets the `pos` of the tree. Returns the tree itself. */ def setPos(newpos: Position): Tree /** Sets the `tpe` of the tree. Returns `Unit`. */ def tpe_=(t: Type): Unit /** Sets the `tpe` of the tree. Returns the tree itself. */ def setType(tp: Type): Tree /** Like `setType`, but if this is a previously empty TypeTree that * fact is remembered so that resetAllAttrs will snap back. * * \@PP: Attempting to elaborate on the above, I find: If defineType * is called on a TypeTree whose type field is null or NoType, * this is recorded as "wasEmpty = true". That value is used in * ResetAttrsTraverser, which nulls out the type field of TypeTrees * for which wasEmpty is true, leaving the others alone. * * resetAllAttrs is used in situations where some speculative * typing of a tree takes place, fails, and the tree needs to be * returned to its former state to try again. So according to me: * using `defineType` instead of `setType` is how you communicate * that the type being set does not depend on any previous state, * and therefore should be abandoned if the current line of type * inquiry doesn't work out. */ def defineType(tp: Type): Tree /** Sets the `symbol` of the tree. Returns `Unit`. */ def symbol_=(sym: Symbol): Unit /** Sets the `symbol` of the tree. Returns the tree itself. */ def setSymbol(sym: Symbol): Tree } /** @inheritdoc */ override type SymTree >: Null <: Tree with SymTreeContextApi /** The extended API of sym trees that's supported in macro context universes * @group API */ trait SymTreeContextApi extends SymTreeApi { this: SymTree => /** Sets the `symbol` field of the sym tree. */ var symbol: Symbol } /** @inheritdoc */ override type TypeTree >: Null <: TypTree with TypeTreeContextApi /** The extended API of sym trees that's supported in macro context universes * @group API */ trait TypeTreeContextApi extends TypeTreeApi { this: TypeTree => /** Sets the `original` field of the type tree. */ def setOriginal(tree: Tree): this.type } /** @inheritdoc */ override type Ident >: Null <: RefTree with IdentContextApi /** The extended API of idents that's supported in macro context universes * @group API */ trait IdentContextApi extends IdentApi { this: Ident => /** Was this ident created from a backquoted identifier? */ def isBackquoted: Boolean } /** Mark a variable as captured; i.e. force boxing in a *Ref type. * @group Macros */ def captureVariable(vble: Symbol): Unit /** Mark given identifier as a reference to a captured variable itself * suppressing dereferencing with the `elem` field. * @group Macros */ def referenceCapturedVariable(vble: Symbol): Tree /** Convert type of a captured variable to *Ref type. * @group Macros */ def capturedVariableType(vble: Symbol): Type /** The type of compilation runs. * @template * @group Macros */ type Run <: RunContextApi /** Compilation run uniquely identifies current invocation of the compiler * (e.g. can be used to implement per-run caches for macros) and provides access to units of work * of the invocation (currently processed unit of work and the list of all units). * @group API */ trait RunContextApi { /** Currently processed unit of work (a real or a virtual file). */ def currentUnit: CompilationUnit /** All units of work comprising this compilation run. */ def units: Iterator[CompilationUnit] } /** The type of compilation units. * @template * @group Macros */ type CompilationUnit <: CompilationUnitContextApi /** Compilation unit describes a unit of work of the compilation run. * It provides such information as file name, textual representation of the unit and the underlying AST. * @group API */ trait CompilationUnitContextApi { /** Source file corresponding to this compilation unit. * * Exposes information about the file as a part of a real or virtual file system * along with the contents of that file. * * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection. * It should not be used unless you know what you are doing. In subsequent releases, this API will be refined * and exposed as a part of scala.reflect.api. */ def source: scala.reflect.internal.util.SourceFile /** The AST that corresponds to this compilation unit. */ def body: Tree } }