summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/macros
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-01-30 10:01:31 +0300
committerEugene Burmako <xeno.by@gmail.com>2014-02-14 23:51:22 +0100
commit114c99691674873393223a11a9aa9168c3f41d77 (patch)
treed855c67a565faf4dbe414cc8f1a1aaff68a8df79 /src/reflect/scala/reflect/macros
parent27805570cbf130260eab04fe1491e58fa95e8108 (diff)
downloadscala-114c99691674873393223a11a9aa9168c3f41d77.tar.gz
scala-114c99691674873393223a11a9aa9168c3f41d77.tar.bz2
scala-114c99691674873393223a11a9aa9168c3f41d77.zip
establishes scala.reflect.api#internal
Reflection API exhibits a tension inherent to experimental things: on the one hand we want it to grow into a beautiful and robust API, but on the other hand we have to deal with immaturity of underlying mechanisms by providing not very pretty solutions to enable important use cases. In Scala 2.10, which was our first stab at reflection API, we didn't have a systematic approach to dealing with this tension, sometimes exposing too much of internals (e.g. Symbol.deSkolemize) and sometimes exposing too little (e.g. there's still no facility to change owners, to do typing transformations, etc). This resulted in certain confusion with some internal APIs living among public ones, scaring the newcomers, and some internal APIs only available via casting, which requires intimate knowledge of the compiler and breaks compatibility guarantees. This led to creation of the `internal` API module for the reflection API, which provides advanced APIs necessary for macros that push boundaries of the state of the art, clearly demarcating them from the more or less straightforward rest and providing compatibility guarantees on par with the rest of the reflection API. This commit does break source compatibility with reflection API in 2.10, but the next commit is going to introduce a strategy of dealing with that.
Diffstat (limited to 'src/reflect/scala/reflect/macros')
-rw-r--r--src/reflect/scala/reflect/macros/Reifiers.scala2
-rw-r--r--src/reflect/scala/reflect/macros/TreeBuilder.scala97
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala235
3 files changed, 113 insertions, 221 deletions
diff --git a/src/reflect/scala/reflect/macros/Reifiers.scala b/src/reflect/scala/reflect/macros/Reifiers.scala
index ff1f7a3b28..e35a5c8622 100644
--- a/src/reflect/scala/reflect/macros/Reifiers.scala
+++ b/src/reflect/scala/reflect/macros/Reifiers.scala
@@ -15,7 +15,7 @@ trait Reifiers {
* For more information and examples see the documentation for `Universe.reify`.
*
* The produced tree will be bound to the specified `universe` and `mirror`.
- * Possible values for `universe` include `universe.treeBuild.mkRuntimeUniverseRef`.
+ * Possible values for `universe` include `universe.internal.gen.mkRuntimeUniverseRef`.
* Possible values for `mirror` include `EmptyTree` (in that case the reifier will automatically pick an appropriate mirror).
*
* This function is deeply connected to `Universe.reify`, a macro that reifies arbitrary expressions into runtime trees.
diff --git a/src/reflect/scala/reflect/macros/TreeBuilder.scala b/src/reflect/scala/reflect/macros/TreeBuilder.scala
deleted file mode 100644
index 7f57274347..0000000000
--- a/src/reflect/scala/reflect/macros/TreeBuilder.scala
+++ /dev/null
@@ -1,97 +0,0 @@
-package scala
-package reflect
-package macros
-
-/**
- * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
- *
- * A helper available in [[scala.reflect.macros.Universe]] that defines shorthands for the
- * most common tree-creating functions.
- */
-@deprecated("Use quasiquotes instead", "2.11.0")
-abstract class TreeBuilder {
- val global: Universe
-
- import global._
-
- /** Builds a reference to value whose type is given stable prefix.
- * The type must be suitable for this. For example, it
- * must not be a TypeRef pointing to an abstract type variable.
- */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkAttributedQualifier(tpe: Type): Tree
-
- /** Builds a reference to value whose type is given stable prefix.
- * If the type is unsuitable, e.g. it is a TypeRef for an
- * abstract type variable, then an Ident will be made using
- * termSym as the Ident's symbol. In that case, termSym must
- * not be NoSymbol.
- */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree
-
- /** Builds a typed reference to given symbol with given stable prefix. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkAttributedRef(pre: Type, sym: Symbol): RefTree
-
- /** Builds a typed reference to given symbol. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkAttributedRef(sym: Symbol): RefTree
-
- /** Builds an untyped reference to given symbol. Requires the symbol to be static. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkUnattributedRef(sym: Symbol): RefTree
-
- /** Builds an untyped reference to symbol with given name. Requires the symbol to be static. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkUnattributedRef(fullName: Name): RefTree
-
- /** Builds a typed This reference to given symbol. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkAttributedThis(sym: Symbol): This
-
- /** Builds a typed Ident with an underlying symbol. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkAttributedIdent(sym: Symbol): RefTree
-
- /** Builds a typed Select with an underlying symbol. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkAttributedSelect(qual: Tree, sym: Symbol): RefTree
-
- /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...)
- * There are a number of variations.
- *
- * @param receiver symbol of the method receiver
- * @param methodName name of the method to call
- * @param targs type arguments (if Nil, no TypeApply node will be generated)
- * @param args value arguments
- * @return the newly created trees.
- */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree
-
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree
-
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkMethodCall(method: Symbol, args: List[Tree]): Tree
-
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkMethodCall(target: Tree, args: List[Tree]): Tree
-
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree
-
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree
-
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree
-
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkNullaryCall(method: Symbol, targs: List[Type]): Tree
-
- /** A tree that refers to the runtime reflexive universe, `scala.reflect.runtime.universe`. */
- @deprecated("Use quasiquotes instead", "2.11.0")
- def mkRuntimeUniverseRef: Tree
-}
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index bc5c8b2840..17eb17cee3 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -2,6 +2,8 @@ package scala
package reflect
package macros
+import scala.language.implicitConversions
+
/**
* <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
*
@@ -17,109 +19,63 @@ package macros
*/
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 }
+ /** @inheritdoc */
+ override type Internal <: MacroInternalApi
- /** 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 }
+ /** @inheritdoc */
+ trait MacroInternalApi extends InternalApi {
+
+ /** Advanced tree factories */
+ val gen: TreeGen
+
+ /** The attachment of the symbol. */
+ def attachments(symbol: Symbol): 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.
+ * Returns the symbol itself.
*/
- def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type
+ def updateAttachment[T: ClassTag](symbol: Symbol, attachment: T): symbol.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`.
+ * Returns the symbol itself.
*/
- def deSkolemize: Symbol
+ def removeAttachment[T: ClassTag](symbol: Symbol): symbol.type
/** The position of this symbol. */
- def pos: Position
+ def pos(symbol: Symbol): Position
/** Sets the `typeSignature` of the symbol. */
- def setTypeSignature(tpe: Type): Symbol
+ def setTypeSignature(symbol: Symbol, tpe: Type): symbol.type
/** Sets the `annotations` of the symbol. */
- def setAnnotations(annots: Annotation*): Symbol
+ def setAnnotations(symbol: Symbol, annots: Annotation*): symbol.type
/** Sets the `name` of the symbol. */
- def setName(name: Name): Symbol
+ def setName(symbol: Symbol, name: Name): symbol.type
/** Sets the `privateWithin` of the symbol. */
- def setPrivateWithin(sym: Symbol): Symbol
- }
+ def setPrivateWithin(symbol: Symbol, sym: Symbol): symbol.type
- // Tree extensions ---------------------------------------------------------------
+ /** The attachment of the tree. */
+ def attachments(tree: Tree): Attachments { type Pos = Position }
- /** 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 =>
+ /** 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 tree itself.
+ */
+ def updateAttachment[T: ClassTag](tree: Tree, attachment: T): tree.type
- /** Sets the `pos` of the tree. Returns `Unit`. */
- def pos_=(pos: Position): Unit
+ /** Update the attachment with the payload of the given class type `T` removed.
+ * Returns the tree itself.
+ */
+ def removeAttachment[T: ClassTag](tree: Tree): tree.type
/** 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
+ def setPos(tree: Tree, newpos: Position): tree.type
/** Sets the `tpe` of the tree. Returns the tree itself. */
- def setType(tp: Type): Tree
+ def setType(tree: Tree, tp: Type): tree.type
/** Like `setType`, but if this is a previously empty TypeTree that
* fact is remembered so that `untypecheck` will snap back.
@@ -139,63 +95,96 @@ abstract class Universe extends scala.reflect.api.Universe {
* 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
+ def defineType(tree: Tree, tp: Type): tree.type
/** Sets the `symbol` of the tree. Returns the tree itself. */
- def setSymbol(sym: Symbol): Tree
- }
+ def setSymbol(tree: Tree, sym: Symbol): tree.type
- /** @inheritdoc */
- override type SymTree >: Null <: Tree with SymTreeContextApi
+ /** Sets the `original` field of the type tree. */
+ def setOriginal(tt: TypeTree, original: Tree): TypeTree
- /** 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
- }
+ /** Mark a variable as captured; i.e. force boxing in a *Ref type.
+ * @group Macros
+ */
+ def captureVariable(vble: Symbol): Unit
- /** @inheritdoc */
- override type TypeTree >: Null <: TypTree with TypeTreeContextApi
+ /** Mark given identifier as a reference to a captured variable itself
+ * suppressing dereferencing with the `elem` field.
+ * @group Macros
+ */
+ def referenceCapturedVariable(vble: Symbol): Tree
- /** 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
+ /** Convert type of a captured variable to *Ref type.
+ * @group Macros
+ */
+ def capturedVariableType(vble: Symbol): Type
}
- /** @inheritdoc */
- override type Ident >: Null <: RefTree with IdentContextApi
+ /** @group Internal */
+ trait TreeGen {
+ /** Builds a reference to value whose type is given stable prefix.
+ * The type must be suitable for this. For example, it
+ * must not be a TypeRef pointing to an abstract type variable.
+ */
+ def mkAttributedQualifier(tpe: Type): Tree
- /** 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
- }
+ /** Builds a reference to value whose type is given stable prefix.
+ * If the type is unsuitable, e.g. it is a TypeRef for an
+ * abstract type variable, then an Ident will be made using
+ * termSym as the Ident's symbol. In that case, termSym must
+ * not be NoSymbol.
+ */
+ def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree
- /** Mark a variable as captured; i.e. force boxing in a *Ref type.
- * @group Macros
- */
- def captureVariable(vble: Symbol): Unit
+ /** Builds a typed reference to given symbol with given stable prefix. */
+ def mkAttributedRef(pre: Type, sym: Symbol): RefTree
- /** Mark given identifier as a reference to a captured variable itself
- * suppressing dereferencing with the `elem` field.
- * @group Macros
- */
- def referenceCapturedVariable(vble: Symbol): Tree
+ /** Builds a typed reference to given symbol. */
+ def mkAttributedRef(sym: Symbol): RefTree
- /** Convert type of a captured variable to *Ref type.
- * @group Macros
- */
- def capturedVariableType(vble: Symbol): Type
+ /** Builds an untyped reference to given symbol. Requires the symbol to be static. */
+ def mkUnattributedRef(sym: Symbol): RefTree
+
+ /** Builds an untyped reference to symbol with given name. Requires the symbol to be static. */
+ def mkUnattributedRef(fullName: Name): RefTree
+
+ /** Builds a typed This reference to given symbol. */
+ def mkAttributedThis(sym: Symbol): This
+
+ /** Builds a typed Ident with an underlying symbol. */
+ def mkAttributedIdent(sym: Symbol): RefTree
+
+ /** Builds a typed Select with an underlying symbol. */
+ def mkAttributedSelect(qual: Tree, sym: Symbol): RefTree
+
+ /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...)
+ * There are a number of variations.
+ *
+ * @param receiver symbol of the method receiver
+ * @param methodName name of the method to call
+ * @param targs type arguments (if Nil, no TypeApply node will be generated)
+ * @param args value arguments
+ * @return the newly created trees.
+ */
+ def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree
+
+ def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree
+
+ def mkMethodCall(method: Symbol, args: List[Tree]): Tree
+
+ def mkMethodCall(target: Tree, args: List[Tree]): Tree
+
+ def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree
+
+ def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree
+
+ def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree
+
+ def mkNullaryCall(method: Symbol, targs: List[Type]): Tree
+
+ /** A tree that refers to the runtime reflexive universe, `scala.reflect.runtime.universe`. */
+ def mkRuntimeUniverseRef: Tree
+ }
/** The type of compilation runs.
* @see [[scala.reflect.macros.Enclosures]]