summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/macros/Universe.scala
blob: bc5c8b2840133c9c68cd6db8b9f0be2e882ff8da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
package scala
package 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
   */
  @deprecated("Use quasiquotes instead", "2.11.0")
  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`. */
    @deprecated("Use setType", "2.11.0") 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 `untypecheck` 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.
     *
     *  `untypecheck` (or `resetAttrs` in compiler parlance) 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.
   *  @see [[scala.reflect.macros.Enclosures]]
   *  @template
   *  @group Macros
   */
  @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
  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).
   *  @see [[scala.reflect.macros.Enclosures]]
   *  @group API
   */
  @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
  trait RunContextApi {
    /** Currently processed unit of work (a real or a virtual file). */
    @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
    def currentUnit: CompilationUnit

    /** All units of work comprising this compilation run. */
    @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
    def units: Iterator[CompilationUnit]
  }

  /** The type of compilation units.
   *  @see [[scala.reflect.macros.Enclosures]]
   *  @template
   *  @group Macros
   */
  @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
  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.
   *  @see [[scala.reflect.macros.Enclosures]]
   *  @group API
   */
  @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
  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.
     */
    @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
    def source: scala.reflect.internal.util.SourceFile

    /** The AST that corresponds to this compilation unit. */
    @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
    def body: Tree
  }
}