From 5cc8f83c681ded7367dc5112f6f9042e9526facf Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 11 Jan 2014 23:41:31 +0100 Subject: *boxContext => *box.Context , *boxMacro => *box.Macro Performs the following renamings: * scala.reflect.macros.BlackboxContext to scala.reflect.macros.blackbox.Context * scala.reflect.macros.BlackboxMacro to scala.reflect.macros.blackbox.Macro * scala.reflect.macros.WhiteboxContext to scala.reflect.macros.whitebox.Context * scala.reflect.macros.WhiteboxMacro to scala.reflect.macros.whitebox.Macro https://groups.google.com/forum/#!topic/scala-internals/MX40-dM28rk --- .../scala/reflect/macros/compiler/Errors.scala | 2 +- .../scala/reflect/macros/compiler/Resolvers.scala | 4 +- .../scala/reflect/macros/compiler/Validators.scala | 12 +-- .../scala/reflect/macros/contexts/Context.scala | 4 +- .../scala/tools/nsc/typechecker/Implicits.scala | 2 +- .../scala/tools/nsc/typechecker/Macros.scala | 16 ++-- src/partest-extras/scala/tools/partest/Util.scala | 4 +- src/reflect/scala/reflect/api/Exprs.scala | 2 +- src/reflect/scala/reflect/api/Importers.scala | 2 +- src/reflect/scala/reflect/api/Mirrors.scala | 6 +- src/reflect/scala/reflect/api/Universe.scala | 6 +- .../scala/reflect/internal/Definitions.scala | 8 +- src/reflect/scala/reflect/macros/Aliases.scala | 4 +- .../scala/reflect/macros/BlackboxContext.scala | 95 --------------------- .../scala/reflect/macros/BlackboxMacro.scala | 36 -------- src/reflect/scala/reflect/macros/Enclosures.scala | 6 +- src/reflect/scala/reflect/macros/Evals.scala | 8 +- src/reflect/scala/reflect/macros/ExprUtils.scala | 4 +- src/reflect/scala/reflect/macros/FrontEnds.scala | 4 +- .../scala/reflect/macros/Infrastructure.scala | 4 +- src/reflect/scala/reflect/macros/Names.scala | 4 +- src/reflect/scala/reflect/macros/Parsers.scala | 4 +- src/reflect/scala/reflect/macros/Reifiers.scala | 4 +- src/reflect/scala/reflect/macros/Typers.scala | 6 +- .../scala/reflect/macros/WhiteboxContext.scala | 76 ----------------- .../scala/reflect/macros/WhiteboxMacro.scala | 36 -------- .../scala/reflect/macros/blackbox/Context.scala | 96 ++++++++++++++++++++++ .../scala/reflect/macros/blackbox/Macro.scala | 40 +++++++++ src/reflect/scala/reflect/macros/package.scala | 8 +- .../scala/reflect/macros/whitebox/Context.scala | 77 +++++++++++++++++ .../scala/reflect/macros/whitebox/Macro.scala | 40 +++++++++ src/reflect/scala/reflect/runtime/package.scala | 2 +- 32 files changed, 316 insertions(+), 306 deletions(-) delete mode 100644 src/reflect/scala/reflect/macros/BlackboxContext.scala delete mode 100644 src/reflect/scala/reflect/macros/BlackboxMacro.scala delete mode 100644 src/reflect/scala/reflect/macros/WhiteboxContext.scala delete mode 100644 src/reflect/scala/reflect/macros/WhiteboxMacro.scala create mode 100644 src/reflect/scala/reflect/macros/blackbox/Context.scala create mode 100644 src/reflect/scala/reflect/macros/blackbox/Macro.scala create mode 100644 src/reflect/scala/reflect/macros/whitebox/Context.scala create mode 100644 src/reflect/scala/reflect/macros/whitebox/Macro.scala (limited to 'src') diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala index 4c30a9a85c..a408a6ec62 100644 --- a/src/compiler/scala/reflect/macros/compiler/Errors.scala +++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala @@ -51,7 +51,7 @@ trait Errors extends Traces { def MacroBundleNonStaticError() = bundleRefError("macro bundles must be static") - def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be monomorphic traits extending either BlackboxMacro or WhiteboxMacro and not implementing their `val c: BlackboxContext/WhiteboxContext` member") + def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be monomorphic traits extending either blackbox.Macro or whitebox.Macro and not implementing their `val c: Context` member") // compatibility errors diff --git a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala index e4851632a5..05daf852ef 100644 --- a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala +++ b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala @@ -46,8 +46,8 @@ trait Resolvers { if (!isMacroBundleProtoType(bundleProto.tpe)) MacroBundleWrongShapeError() if (!bundleProto.owner.isStaticOwner) MacroBundleNonStaticError() - // synthesize the bundle, i.e. given a static `trait Foo extends Macro { def expand = ... } ` - // create a top-level definition `class Foo$Bundle(val c: BlackboxContext/WhiteboxContext) extends Foo` in a package next to `Foo` + // synthesize the bundle, i.e. given a static `trait Foo extends *box.Macro { def expand = ... } ` + // create a top-level definition `class Foo$Bundle(val c: *box.Context) extends Foo` in a package next to `Foo` val bundlePid = gen.mkUnattributedRef(bundlePkg) val bundlePrefix = if (bundlePkg == EmptyPackageClass) bundleProto.fullName('$') diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala index 5936b52890..95cb0f7466 100644 --- a/src/compiler/scala/reflect/macros/compiler/Validators.scala +++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala @@ -93,20 +93,20 @@ trait Validators { * * For the following macro impl: * def fooBar[T: c.WeakTypeTag] - * (c: scala.reflect.macros.BlackboxContext) + * (c: scala.reflect.macros.blackbox.Context) * (xs: c.Expr[List[T]]) * : c.Expr[T] = ... * * This function will return: - * (c: scala.reflect.macros.BlackboxContext)(xs: c.Expr[List[T]])c.Expr[T] + * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T] * * Note that type tag evidence parameters are not included into the result. * Type tag context bounds for macro impl tparams are optional. * Therefore compatibility checks ignore such parameters, and we don't need to bother about them here. * * This method cannot be reduced to just macroImpl.info, because macro implementations might - * come in different shapes. If the implementation is an apply method of a BlackboxMacro/WhiteboxMacro-compatible object, - * then it won't have (c: BlackboxContext/WhiteboxContext) in its parameters, but will rather refer to BlackboxMacro/WhiteboxMacro.c. + * come in different shapes. If the implementation is an apply method of a *box.Macro-compatible object, + * then it won't have (c: *box.Context) in its parameters, but will rather refer to *boxMacro.c. * * @param macroImpl The macro implementation symbol */ @@ -123,8 +123,8 @@ trait Validators { * def foo[T](xs: List[T]): T = macro fooBar * * This function will return: - * (c: scala.reflect.macros.BlackboxContext)(xs: c.Expr[List[T]])c.Expr[T] or - * (c: scala.reflect.macros.WhiteboxContext)(xs: c.Expr[List[T]])c.Expr[T] + * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T] or + * (c: scala.reflect.macros.whitebox.Context)(xs: c.Expr[List[T]])c.Expr[T] * * Note that type tag evidence parameters are not included into the result. * Type tag context bounds for macro impl tparams are optional. diff --git a/src/compiler/scala/reflect/macros/contexts/Context.scala b/src/compiler/scala/reflect/macros/contexts/Context.scala index 7b79b52a18..87dac18849 100644 --- a/src/compiler/scala/reflect/macros/contexts/Context.scala +++ b/src/compiler/scala/reflect/macros/contexts/Context.scala @@ -3,8 +3,8 @@ package contexts import scala.tools.nsc.Global -abstract class Context extends scala.reflect.macros.BlackboxContext - with scala.reflect.macros.WhiteboxContext +abstract class Context extends scala.reflect.macros.blackbox.Context + with scala.reflect.macros.whitebox.Context with Aliases with Enclosures with Names diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index fdec1edcc0..19fba639e3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1145,7 +1145,7 @@ trait Implicits { gen.mkAttributedThis(thisSym) case _ => // if `pre` is not a PDT, e.g. if someone wrote - // implicitly[scala.reflect.macros.BlackboxContext#TypeTag[Int]] + // implicitly[scala.reflect.macros.blackbox.Context#TypeTag[Int]] // then we need to fail, because we don't know the prefix to use during type reification // upd. we also need to fail silently, because this is a very common situation // e.g. quite often we're searching for BaseUniverse#TypeTag, e.g. for a type tag in any universe diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index a1e77515a8..cf82d6baac 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -29,7 +29,7 @@ import Fingerprint._ * Then fooBar needs to point to a static method of the following form: * * def fooBar[T: c.WeakTypeTag] // type tag annotation is optional - * (c: scala.reflect.macros.BlackboxContext) + * (c: scala.reflect.macros.blackbox.Context) * (xs: c.Expr[List[T]]) * : c.Expr[T] = { * ... @@ -67,7 +67,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * * This solution is very simple, but unfortunately it's also lacking. If we use it, then * signatures of macro defs become transitively dependent on scala-reflect.jar - * (because they refer to macro impls, and macro impls refer to scala.reflect.macros.BlackboxContext/WhiteboxContext defined in scala-reflect.jar). + * (because they refer to macro impls, and macro impls refer to *box.Context defined in scala-reflect.jar). * More details can be found in comments to https://issues.scala-lang.org/browse/SI-5940. * * Therefore we have to avoid putting macro impls into binding pickles and come up with our own serialization format. @@ -81,9 +81,9 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * and various accounting information necessary when composing an argument list for the reflective invocation. */ case class MacroImplBinding( - // Is this macro impl a bundle (a trait extending BlackboxMacro or WhiteboxMacro) or a vanilla def? + // Is this macro impl a bundle (a trait extending *box.Macro) or a vanilla def? val isBundle: Boolean, - // Is this macro impl blackbox (i.e. having BlackboxContext in its signature)? + // Is this macro impl blackbox (i.e. having blackbox.Context in its signature)? val isBlackbox: Boolean, // Java class name of the class that contains the macro implementation // is used to load the corresponding object with Java reflection @@ -97,8 +97,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { // * c.Expr[T] => LiftedTyped // * c.Tree => LiftedUntyped // * c.WeakTypeTag[T] => Tagged(index of the type parameter corresponding to that type tag) - // * everything else (e.g. scala.reflect.macros.BlackboxContext/WhiteboxContext) => Other - // f.ex. for: def impl[T: WeakTypeTag, U, V: WeakTypeTag](c: BlackboxContext)(x: c.Expr[T], y: c.Tree): (U, V) = ??? + // * everything else (e.g. *box.Context) => Other + // f.ex. for: def impl[T: WeakTypeTag, U, V: WeakTypeTag](c: blackbox.Context)(x: c.Expr[T], y: c.Tree): (U, V) = ??? // `signature` will be equal to List(List(Other), List(LiftedTyped, LiftedUntyped), List(Tagged(0), Tagged(2))) signature: List[List[Fingerprint]], // type arguments part of a macro impl ref (the right-hand side of a macro definition) @@ -116,7 +116,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * with synthetic content that carries the payload described in `MacroImplBinding`. * * For example, for a pair of macro definition and macro implementation: - * def impl(c: scala.reflect.macros.BlackboxContext): c.Expr[Unit] = ??? + * def impl(c: scala.reflect.macros.blackbox.Context): c.Expr[Unit] = ??? * def foo: Unit = macro impl * * We will have the following annotation added on the macro definition `foo`: @@ -478,7 +478,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { } /** Keeps track of macros in-flight. - * See more informations in comments to `openMacros` in `scala.reflect.macros.WhiteboxContext`. + * See more informations in comments to `openMacros` in `scala.reflect.macros.whitebox.Context`. */ var _openMacros = List[MacroContext]() def openMacros = _openMacros diff --git a/src/partest-extras/scala/tools/partest/Util.scala b/src/partest-extras/scala/tools/partest/Util.scala index 8214396291..60e9dbb0f9 100644 --- a/src/partest-extras/scala/tools/partest/Util.scala +++ b/src/partest-extras/scala/tools/partest/Util.scala @@ -16,8 +16,8 @@ object Util { */ def trace[A](a: A) = macro traceImpl[A] - import scala.reflect.macros.BlackboxContext - def traceImpl[A: c.WeakTypeTag](c: BlackboxContext)(a: c.Expr[A]): c.Expr[A] = { + import scala.reflect.macros.blackbox.Context + def traceImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]): c.Expr[A] = { import c.universe._ import definitions._ diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala index 50c8aa8779..5b6ff2325c 100644 --- a/src/reflect/scala/reflect/api/Exprs.scala +++ b/src/reflect/scala/reflect/api/Exprs.scala @@ -106,7 +106,7 @@ trait Exprs { self: Universe => * * The corresponding macro implementation should have the following signature (note how the return type denotes path-dependency on x): * {{{ - * object Impls { def foo_impl(c: BlackboxContext)(x: c.Expr[X]): c.Expr[x.value.T] = ... } + * object Impls { def foo_impl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ... } * }}} */ @compileTimeOnly("cannot use value except for signatures of macro implementations") diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala index e239b86452..5667d93e29 100644 --- a/src/reflect/scala/reflect/api/Importers.scala +++ b/src/reflect/scala/reflect/api/Importers.scala @@ -34,7 +34,7 @@ package api * {{{ * def staticEval[T](x: T) = macro staticEval[T] * - * def staticEval[T](c: scala.reflect.macros.BlackboxContext)(x: c.Expr[T]) = { + * def staticEval[T](c: scala.reflect.macros.blackbox.Context)(x: c.Expr[T]) = { * // creates a runtime reflection universe to host runtime compilation * import scala.reflect.runtime.{universe => ru} * val mirror = ru.runtimeMirror(c.libraryClassLoader) diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index a4cd531053..0f0e2b81c9 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -29,19 +29,19 @@ package api * Compile-time `Mirror`s make use of only classloader `Mirror`s to load `Symbol`s * by name. * - * The entry point to classloader `Mirror`s is via [[scala.reflect.macros.BlackboxContext#mirror]] or [[scala.reflect.macros.WhiteboxContext#mirror]]. + * The entry point to classloader `Mirror`s is via [[scala.reflect.macros.blackbox.Context#mirror]] or [[scala.reflect.macros.whitebox.Context#mirror]]. * Typical methods which use classloader `Mirror`s include [[scala.reflect.api.Mirror#staticClass]], * [[scala.reflect.api.Mirror#staticModule]], and [[scala.reflect.api.Mirror#staticPackage]]. For * example: * {{{ - * import scala.reflect.macros.BlackboxContext + * import scala.reflect.macros.blackbox.Context * * case class Location(filename: String, line: Int, column: Int) * * object Macros { * def currentLocation: Location = macro impl * - * def impl(c: BlackboxContext): c.Expr[Location] = { + * def impl(c: Context): c.Expr[Location] = { * import c.universe._ * val pos = c.macroApplication.pos * val clsLocation = c.mirror.staticModule("Location") // get symbol of "Location" object diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index 1da2c24306..1c9b77581a 100644 --- a/src/reflect/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -41,11 +41,11 @@ package api * res1: reflect.runtime.universe.Type = scala.Either[String,Int] * }}} * - * To obtain a `Universe` for use within a Scala macro, use [[scala.reflect.macros.BlackboxContext#universe]]. - * or [[scala.reflect.macros.WhiteboxContext#universe]]. For example: + * To obtain a `Universe` for use within a Scala macro, use [[scala.reflect.macros.blackbox.Context#universe]]. + * or [[scala.reflect.macros.whitebox.Context#universe]]. For example: * {{{ * def printf(format: String, params: Any*): Unit = macro impl - * def impl(c: BlackboxContext)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = { + * def impl(c: Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = { * import c.universe._ * ... * } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 38be6fcf56..133442bdb5 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -482,12 +482,12 @@ trait Definitions extends api.StandardDefinitions { lazy val TypeCreatorClass = getClassIfDefined("scala.reflect.api.TypeCreator") // defined in scala-reflect.jar, so we need to be careful lazy val TreeCreatorClass = getClassIfDefined("scala.reflect.api.TreeCreator") // defined in scala-reflect.jar, so we need to be careful - lazy val BlackboxMacroClass = getClassIfDefined("scala.reflect.macros.BlackboxMacro") // defined in scala-reflect.jar, so we need to be careful + lazy val BlackboxMacroClass = getClassIfDefined("scala.reflect.macros.blackbox.Macro") // defined in scala-reflect.jar, so we need to be careful def BlackboxMacroContextValue = BlackboxMacroClass.map(sym => getMemberValue(sym, nme.c)) - lazy val WhiteboxMacroClass = getClassIfDefined("scala.reflect.macros.WhiteboxMacro") // defined in scala-reflect.jar, so we need to be careful + lazy val WhiteboxMacroClass = getClassIfDefined("scala.reflect.macros.whitebox.Macro") // defined in scala-reflect.jar, so we need to be careful def WhiteboxMacroContextValue = WhiteboxMacroClass.map(sym => getMemberValue(sym, nme.c)) - lazy val BlackboxContextClass = getClassIfDefined("scala.reflect.macros.BlackboxContext") // defined in scala-reflect.jar, so we need to be careful - lazy val WhiteboxContextClass = getClassIfDefined("scala.reflect.macros.WhiteboxContext") // defined in scala-reflect.jar, so we need to be careful + lazy val BlackboxContextClass = getClassIfDefined("scala.reflect.macros.blackbox.Context") // defined in scala-reflect.jar, so we need to be careful + lazy val WhiteboxContextClass = getClassIfDefined("scala.reflect.macros.whitebox.Context") // defined in scala-reflect.jar, so we need to be careful def MacroContextPrefix = BlackboxContextClass.map(sym => getMemberMethod(sym, nme.prefix)) def MacroContextPrefixType = BlackboxContextClass.map(sym => getTypeMember(sym, tpnme.PrefixType)) def MacroContextUniverse = BlackboxContextClass.map(sym => getMemberMethod(sym, nme.universe)) diff --git a/src/reflect/scala/reflect/macros/Aliases.scala b/src/reflect/scala/reflect/macros/Aliases.scala index ca599dbd49..cc92cd10c7 100644 --- a/src/reflect/scala/reflect/macros/Aliases.scala +++ b/src/reflect/scala/reflect/macros/Aliases.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that defines shorthands for the + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that defines shorthands for the * most frequently used types and functions of the underlying compiler universe. */ trait Aliases { - self: BlackboxContext => + self: blackbox.Context => /** The type of symbols representing declarations. */ type Symbol = universe.Symbol diff --git a/src/reflect/scala/reflect/macros/BlackboxContext.scala b/src/reflect/scala/reflect/macros/BlackboxContext.scala deleted file mode 100644 index 2c77289866..0000000000 --- a/src/reflect/scala/reflect/macros/BlackboxContext.scala +++ /dev/null @@ -1,95 +0,0 @@ -package scala -package reflect -package macros - -/** - * EXPERIMENTAL - * - * The blackbox 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. - * - * If a macro def refers to a macro impl that uses `BlackboxContext`, then this macro def becomes a blackbox macro, - * which means that its expansion will be upcast to its return type, enforcing faithfullness of that macro to its - * type signature. Whitebox macros, i.e. the ones defined with `WhiteboxContext`, aren't bound by this restriction, - * which enables a number of important use cases, but they are also going to enjoy less support than blackbox macros, - * so choose wisely. See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] for more information. - * - * @see `scala.reflect.macros.WhiteboxContext` - */ -trait BlackboxContext 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 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: BlackboxContext { 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] -} diff --git a/src/reflect/scala/reflect/macros/BlackboxMacro.scala b/src/reflect/scala/reflect/macros/BlackboxMacro.scala deleted file mode 100644 index df142e9238..0000000000 --- a/src/reflect/scala/reflect/macros/BlackboxMacro.scala +++ /dev/null @@ -1,36 +0,0 @@ -package scala.reflect -package macros - -/** - * EXPERIMENTAL - * - * Traditionally macro implementations are defined as methods, - * but this trait provides an alternative way of encoding macro impls as - * bundles, traits which extend `scala.reflect.macros.BlackboxMacro` or`scala.reflect.macros.WhiteboxMacro` . - * - * Instead of: - * - * def impl[T: c.WeakTypeTag](c: BlackboxContext)(x: c.Expr[Int]) = ... - * - * One can write: - * - * trait Impl extends BlackboxMacro { - * def apply[T: c.WeakTypeTag](x: c.Expr[Int]) = ... - * } - * - * Without changing anything else at all. - * - * This language feature is useful in itself in cases when macro implementations - * are complex and need to be modularized. State of the art technique of addressing this need is quite heavyweight: - * http://docs.scala-lang.org/overviews/macros/overview.html#writing_bigger_macros. - * - * @see `scala.reflect.macros.WhiteboxMacro` - */ -trait BlackboxMacro { - /** The context to be used by the macro implementation. - * - * Vanilla macro implementations have to carry it in their signatures, however when a macro is a full-fledged module, - * it can define the context next to the implementation, makes implementation signature more lightweight. - */ - val c: BlackboxContext -} diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala index f3e934d12b..5f248d25d3 100644 --- a/src/reflect/scala/reflect/macros/Enclosures.scala +++ b/src/reflect/scala/reflect/macros/Enclosures.scala @@ -7,13 +7,13 @@ import scala.language.existentials // SI-6541 /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that exposes + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that exposes * enclosing trees (method, class, compilation unit and currently compiled application), * the enclosing position of the macro expansion, as well as macros and implicits * that are currently in-flight. */ trait Enclosures { - self: BlackboxContext => + self: blackbox.Context => /** The tree that undergoes macro expansion. * Can be useful to get an offset or a range position of the entire tree being processed. @@ -30,7 +30,7 @@ trait Enclosures { * Unlike `openMacros`, this is a val, which means that it gets initialized when the context is created * and always stays the same regardless of whatever happens during macro expansion. */ - def enclosingMacros: List[BlackboxContext] + def enclosingMacros: List[blackbox.Context] /** Tries to guess a position for the enclosing application. * But that is simple, right? Just dereference `pos` of `macroApplication`? Not really. diff --git a/src/reflect/scala/reflect/macros/Evals.scala b/src/reflect/scala/reflect/macros/Evals.scala index eb37e83cad..222ae43d79 100644 --- a/src/reflect/scala/reflect/macros/Evals.scala +++ b/src/reflect/scala/reflect/macros/Evals.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that provides + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that provides * a facility to evaluate trees. */ trait Evals { - self: BlackboxContext => + self: blackbox.Context => /** Takes a typed wrapper for a tree of type `T` and evaluates it to a value of type `T`. * @@ -21,12 +21,12 @@ trait Evals { * mutates the tree in place, therefore the conventional approach is to `duplicate` the tree first. * * {{{ - * scala> def impl(c: BlackboxContext)(x: c.Expr[String]) = { + * scala> def impl(c: Context)(x: c.Expr[String]) = { * | val x1 = c.Expr[String](c.resetAllAttrs(x.tree.duplicate)) * | println(s"compile-time value is: \${c.eval(x1)}") * | x * | } - * impl: (c: BlackboxContext)(x: c.Expr[String])c.Expr[String] + * impl: (c: Context)(x: c.Expr[String])c.Expr[String] * * scala> def test(x: String) = macro impl * test: (x: String)String diff --git a/src/reflect/scala/reflect/macros/ExprUtils.scala b/src/reflect/scala/reflect/macros/ExprUtils.scala index 58b61e446a..c438653c92 100644 --- a/src/reflect/scala/reflect/macros/ExprUtils.scala +++ b/src/reflect/scala/reflect/macros/ExprUtils.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that defines shorthands for the + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that defines shorthands for the * most common `Expr`-creating functions. */ trait ExprUtils { - self: BlackboxContext => + self: blackbox.Context => /** Shorthand for `Literal(Constant(null))` in the underlying `universe`. */ @deprecated("Use quasiquotes instead", "2.11.0") diff --git a/src/reflect/scala/reflect/macros/FrontEnds.scala b/src/reflect/scala/reflect/macros/FrontEnds.scala index 3a910d89ad..a770f325b2 100644 --- a/src/reflect/scala/reflect/macros/FrontEnds.scala +++ b/src/reflect/scala/reflect/macros/FrontEnds.scala @@ -5,12 +5,12 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that * provides facilities to communicate with the compiler's front end * (emit warnings, errors and other sorts of messages). */ trait FrontEnds { - self: BlackboxContext => + self: blackbox.Context => /** For sending a message which should not be labeled as a warning/error, * but also shouldn't require -verbose to be visible. diff --git a/src/reflect/scala/reflect/macros/Infrastructure.scala b/src/reflect/scala/reflect/macros/Infrastructure.scala index b6585f94d2..0f2d9ce4cf 100644 --- a/src/reflect/scala/reflect/macros/Infrastructure.scala +++ b/src/reflect/scala/reflect/macros/Infrastructure.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that * provides facilities to communicate with the compiler's infrastructure. */ trait Infrastructure { - self: BlackboxContext => + self: blackbox.Context => /** Exposes macro-specific settings as a list of strings. * These settings are passed to the compiler via the "-Xmacro-settings:setting1,setting2...,settingN" command-line option. diff --git a/src/reflect/scala/reflect/macros/Names.scala b/src/reflect/scala/reflect/macros/Names.scala index 6bd3e1a199..af60dffbfc 100644 --- a/src/reflect/scala/reflect/macros/Names.scala +++ b/src/reflect/scala/reflect/macros/Names.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that * provides functions that generate unique names. */ trait Names { - self: BlackboxContext => + self: blackbox.Context => /** Creates a unique string. */ @deprecated("Use freshName instead", "2.11.0") diff --git a/src/reflect/scala/reflect/macros/Parsers.scala b/src/reflect/scala/reflect/macros/Parsers.scala index 9d4a7e2953..720b754649 100644 --- a/src/reflect/scala/reflect/macros/Parsers.scala +++ b/src/reflect/scala/reflect/macros/Parsers.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that * exposes functions to parse strings with Scala code into trees. */ trait Parsers { - self: BlackboxContext => + self: blackbox.Context => /** Parses a string with a Scala expression into an abstract syntax tree. * Only works for expressions, i.e. parsing a package declaration will fail. diff --git a/src/reflect/scala/reflect/macros/Reifiers.scala b/src/reflect/scala/reflect/macros/Reifiers.scala index 67d10dc10a..ff1f7a3b28 100644 --- a/src/reflect/scala/reflect/macros/Reifiers.scala +++ b/src/reflect/scala/reflect/macros/Reifiers.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that * exposes functions to save reflection artifacts for runtime. */ trait Reifiers { - self: BlackboxContext => + self: blackbox.Context => /** Given a tree, generate a tree that when compiled and executed produces the original tree. * For more information and examples see the documentation for `Universe.reify`. diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index 5a25801335..54336900f8 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -5,11 +5,11 @@ package macros /** * EXPERIMENTAL * - * A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that + * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that * partially exposes the type checker to macro writers. */ trait Typers { - self: BlackboxContext => + self: blackbox.Context => /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only. * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion. @@ -21,7 +21,7 @@ trait Typers { * Unlike `enclosingMacros`, this is a def, which means that it gets recalculated on every invocation, * so it might change depending on what is going on during macro expansion. */ - def openMacros: List[BlackboxContext] + def openMacros: List[blackbox.Context] /** @see `Typers.typecheck` */ diff --git a/src/reflect/scala/reflect/macros/WhiteboxContext.scala b/src/reflect/scala/reflect/macros/WhiteboxContext.scala deleted file mode 100644 index 9d65a5c16e..0000000000 --- a/src/reflect/scala/reflect/macros/WhiteboxContext.scala +++ /dev/null @@ -1,76 +0,0 @@ -package scala -package reflect -package macros - -/** - * EXPERIMENTAL - * - * The whitebox 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. - * - * If a macro def refers to a macro impl that uses `WhiteboxContext`, then this macro def becomes a whitebox macro, - * gaining the ability to refine the type of its expansion beyond its official return type, which enables a number of important use cases. - * Blackbox macros, i.e. the ones defined with `BlackboxContext`, can't do that, so they are less powerful. - * However blackbox macros are also going to enjoy better support than whitebox macros, so choose wisely. - * See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] for more information. - * - * @see `scala.reflect.macros.BlackboxContext` - */ -trait WhiteboxContext extends BlackboxContext { - /** @inheritdoc - */ - def openMacros: List[WhiteboxContext] - - /** @inheritdoc - */ - def enclosingMacros: List[WhiteboxContext] - - /** Information about one of the currently considered implicit candidates. - * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, - * hence implicit searches can recursively trigger other implicit searches. - * - * `pre` and `sym` provide information about the candidate itself. - * `pt` and `tree` store the parameters of the implicit search the candidate is participating in. - */ - case class ImplicitCandidate(pre: Type, sym: Symbol, pt: Type, tree: Tree) - - /** Information about one of the currently considered implicit candidates. - * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, - * hence implicit searches can recursively trigger other implicit searches. - * - * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. - * If we're in an implicit macro being expanded, it's included in this list. - * - * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation, - * so it might change depending on what is going on during macro expansion. - */ - def openImplicits: List[ImplicitCandidate] - - /** Information about one of the currently considered implicit candidates. - * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, - * hence implicit searches can recursively trigger other implicit searches. - * - * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. - * If we're in an implicit macro being expanded, it's included in this list. - * - * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created - * and always stays the same regardless of whatever happens during macro expansion. - */ - def enclosingImplicits: List[ImplicitCandidate] -} \ No newline at end of file diff --git a/src/reflect/scala/reflect/macros/WhiteboxMacro.scala b/src/reflect/scala/reflect/macros/WhiteboxMacro.scala deleted file mode 100644 index 1c581313eb..0000000000 --- a/src/reflect/scala/reflect/macros/WhiteboxMacro.scala +++ /dev/null @@ -1,36 +0,0 @@ -package scala.reflect -package macros - -/** - * EXPERIMENTAL - * - * Traditionally macro implementations are defined as methods, - * but this trait provides an alternative way of encoding macro impls as - * bundles, traits which extend `scala.reflect.macros.BlackboxMacro` or`scala.reflect.macros.WhiteboxMacro` . - * - * Instead of: - * - * def impl[T: c.WeakTypeTag](c: WhiteboxContext)(x: c.Expr[Int]) = ... - * - * One can write: - * - * trait Impl extends WhiteboxMacro { - * def apply[T: c.WeakTypeTag](x: c.Expr[Int]) = ... - * } - * - * Without changing anything else at all. - * - * This language feature is useful in itself in cases when macro implementations - * are complex and need to be modularized. State of the art technique of addressing this need is quite heavyweight: - * http://docs.scala-lang.org/overviews/macros/overview.html#writing_bigger_macros. - * - * @see `scala.reflect.macros.BlackboxMacro` - */ -trait WhiteboxMacro { - /** The context to be used by the macro implementation. - * - * Vanilla macro implementations have to carry it in their signatures, however when a macro is a full-fledged module, - * it can define the context next to the implementation, makes implementation signature more lightweight. - */ - val c: WhiteboxContext -} diff --git a/src/reflect/scala/reflect/macros/blackbox/Context.scala b/src/reflect/scala/reflect/macros/blackbox/Context.scala new file mode 100644 index 0000000000..05d9595c3a --- /dev/null +++ b/src/reflect/scala/reflect/macros/blackbox/Context.scala @@ -0,0 +1,96 @@ +package scala +package reflect +package macros +package blackbox + +/** + * EXPERIMENTAL + * + * The blackbox 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. + * + * If a macro def refers to a macro impl that uses `blackbox.Context`, then this macro def becomes a blackbox macro, + * which means that its expansion will be upcast to its return type, enforcing faithfullness of that macro to its + * type signature. Whitebox macros, i.e. the ones defined with `whitebox.Context`, aren't bound by this restriction, + * which enables a number of important use cases, but they are also going to enjoy less support than blackbox macros, + * so choose wisely. See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] for more information. + * + * @see `scala.reflect.macros.whitebox.Context` + */ +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 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] +} diff --git a/src/reflect/scala/reflect/macros/blackbox/Macro.scala b/src/reflect/scala/reflect/macros/blackbox/Macro.scala new file mode 100644 index 0000000000..e51aca6896 --- /dev/null +++ b/src/reflect/scala/reflect/macros/blackbox/Macro.scala @@ -0,0 +1,40 @@ +package scala +package reflect +package macros +package blackbox + +/** + * EXPERIMENTAL + * + * Traditionally macro implementations are defined as methods, + * but this trait provides an alternative way of encoding macro impls as + * bundles, traits which extend `scala.reflect.macros.blackbox.Macro` or`scala.reflect.macros.whitebox.Macro` . + * + * Instead of: + * + * import scala.reflect.macros.blackbox._ + * def impl[T: c.WeakTypeTag](c: Context)(x: c.Expr[Int]) = ... + * + * One can write: + * + * import scala.reflect.macros.blackbox._ + * trait Impl extends Macro { + * def apply[T: c.WeakTypeTag](x: c.Expr[Int]) = ... + * } + * + * Without changing anything else at all. + * + * This language feature is useful in itself in cases when macro implementations + * are complex and need to be modularized. State of the art technique of addressing this need is quite heavyweight: + * http://docs.scala-lang.org/overviews/macros/overview.html#writing_bigger_macros. + * + * @see `scala.reflect.macros.whitebox.Macro` + */ +trait Macro { + /** The context to be used by the macro implementation. + * + * Vanilla macro implementations have to carry it in their signatures, however when a macro is a full-fledged module, + * it can define the context next to the implementation, makes implementation signature more lightweight. + */ + val c: Context +} diff --git a/src/reflect/scala/reflect/macros/package.scala b/src/reflect/scala/reflect/macros/package.scala index 6a8434a163..cc7111d794 100644 --- a/src/reflect/scala/reflect/macros/package.scala +++ b/src/reflect/scala/reflect/macros/package.scala @@ -19,10 +19,10 @@ package object macros { * with the former being better supported and the latter being more powerful. You can read about * the details of the split and the associated trade-offs in the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]]. * - * `scala.reflect.macros.Context` follows this tendency and turns into `scala.reflect.macros.BlackboxContext` - * and `scala.reflect.macros.WhiteboxContext`. The original `Context` is left in place for compatibility reasons, + * `scala.reflect.macros.Context` follows this tendency and turns into `scala.reflect.macros.blackbox.Context` + * and `scala.reflect.macros.whitebox.Context`. The original `Context` is left in place for compatibility reasons, * but it is now deprecated, nudging the users to choose between blackbox and whitebox macros. */ - @deprecated("Use BlackboxContext or WhiteboxContext instead", "2.11.0") - type Context = WhiteboxContext + @deprecated("Use blackbox.Context or whitebox.Context instead", "2.11.0") + type Context = whitebox.Context } \ No newline at end of file diff --git a/src/reflect/scala/reflect/macros/whitebox/Context.scala b/src/reflect/scala/reflect/macros/whitebox/Context.scala new file mode 100644 index 0000000000..bd48df46cc --- /dev/null +++ b/src/reflect/scala/reflect/macros/whitebox/Context.scala @@ -0,0 +1,77 @@ +package scala +package reflect +package macros +package whitebox + +/** + * EXPERIMENTAL + * + * The whitebox 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. + * + * If a macro def refers to a macro impl that uses `whitebox.Context`, then this macro def becomes a whitebox macro, + * gaining the ability to refine the type of its expansion beyond its official return type, which enables a number of important use cases. + * Blackbox macros, i.e. the ones defined with `blackbox.Context`, can't do that, so they are less powerful. + * However blackbox macros are also going to enjoy better support than whitebox macros, so choose wisely. + * See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] for more information. + * + * @see `scala.reflect.macros.blackbox.Context` + */ +trait Context extends blackbox.Context { + /** @inheritdoc + */ + def openMacros: List[Context] + + /** @inheritdoc + */ + def enclosingMacros: List[Context] + + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * + * `pre` and `sym` provide information about the candidate itself. + * `pt` and `tree` store the parameters of the implicit search the candidate is participating in. + */ + case class ImplicitCandidate(pre: Type, sym: Symbol, pt: Type, tree: Tree) + + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * + * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. + * If we're in an implicit macro being expanded, it's included in this list. + * + * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation, + * so it might change depending on what is going on during macro expansion. + */ + def openImplicits: List[ImplicitCandidate] + + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * + * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. + * If we're in an implicit macro being expanded, it's included in this list. + * + * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created + * and always stays the same regardless of whatever happens during macro expansion. + */ + def enclosingImplicits: List[ImplicitCandidate] +} \ No newline at end of file diff --git a/src/reflect/scala/reflect/macros/whitebox/Macro.scala b/src/reflect/scala/reflect/macros/whitebox/Macro.scala new file mode 100644 index 0000000000..af8539268e --- /dev/null +++ b/src/reflect/scala/reflect/macros/whitebox/Macro.scala @@ -0,0 +1,40 @@ +package scala +package reflect +package macros +package whitebox + +/** + * EXPERIMENTAL + * + * Traditionally macro implementations are defined as methods, + * but this trait provides an alternative way of encoding macro impls as + * bundles, traits which extend `scala.reflect.macros.blackbox.Macro` or`scala.reflect.macros.whitebox.Macro` . + * + * Instead of: + * + * import scala.reflect.macros.whitebox._ + * def impl[T: c.WeakTypeTag](c: Context)(x: c.Expr[Int]) = ... + * + * One can write: + * + * import scala.reflect.macros.whitebox._ + * trait Impl extends Macro { + * def apply[T: c.WeakTypeTag](x: c.Expr[Int]) = ... + * } + * + * Without changing anything else at all. + * + * This language feature is useful in itself in cases when macro implementations + * are complex and need to be modularized. State of the art technique of addressing this need is quite heavyweight: + * http://docs.scala-lang.org/overviews/macros/overview.html#writing_bigger_macros. + * + * @see `scala.reflect.macros.blackbox.Macro` + */ +trait Macro { + /** The context to be used by the macro implementation. + * + * Vanilla macro implementations have to carry it in their signatures, however when a macro is a full-fledged module, + * it can define the context next to the implementation, makes implementation signature more lightweight. + */ + val c: Context +} diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index 3a7688aa2c..3c9bbccba3 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -26,7 +26,7 @@ package object runtime { package runtime { private[scala] object Macros { - def currentMirror(c: scala.reflect.macros.BlackboxContext): c.Expr[universe.Mirror] = { + def currentMirror(c: scala.reflect.macros.blackbox.Context): c.Expr[universe.Mirror] = { import c.universe._ val runtimeClass = c.reifyEnclosingRuntimeClass if (runtimeClass.isEmpty) c.abort(c.enclosingPosition, "call site does not have an enclosing class") -- cgit v1.2.3