diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-05-22 22:21:10 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-05-22 22:21:10 +0200 |
commit | a907887158a469b6a21d027fd37bc360e9009b2f (patch) | |
tree | cbe260a6e1625cbaa33670289dfe78197d1fa5e5 | |
parent | d079e769b9372daae8d7770c4156f85ea1af6621 (diff) | |
download | scala-a907887158a469b6a21d027fd37bc360e9009b2f.tar.gz scala-a907887158a469b6a21d027fd37bc360e9009b2f.tar.bz2 scala-a907887158a469b6a21d027fd37bc360e9009b2f.zip |
adds MacroPlugin.pluginsIsBlackbox
This is an important omission in the current macro plugin API, which was
designed before the blackbox vs whitebox separation was implemented.
Even if one overrides pluginsTypedMacroBody and pluginsMacroExpand,
that would still be not enough to write a custom macro expander, because
typedImplicit1 uses isBlackbox, which is tightly coupled with the standard
way of reading/writing macro signatures.
7 files changed, 64 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala index fa6e5399eb..5a70d4c524 100644 --- a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala +++ b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala @@ -190,6 +190,16 @@ trait AnalyzerPlugins { self: Analyzer => def pluginsTypedMacroBody(typer: Typer, ddef: DefDef): Option[Tree] = None /** + * Figures out whether the given macro definition is blackbox or whitebox. + * + * Default implementation provided in `self.standardIsBlackbox` loads the macro impl binding + * and fetches boxity from the "isBlackbox" field of the macro signature. + * + * $nonCumulativeReturnValueDoc. + */ + def pluginsIsBlackbox(macroDef: Symbol): Option[Boolean] = None + + /** * Expands an application of a def macro (i.e. of a symbol that has the MACRO flag set), * possibly using the current typer mode and the provided prototype. * @@ -375,6 +385,14 @@ trait AnalyzerPlugins { self: Analyzer => def custom(plugin: MacroPlugin) = plugin.pluginsTypedMacroBody(typer, ddef) }) + /** @see MacroPlugin.pluginsIsBlackbox */ + def pluginsIsBlackbox(macroDef: Symbol): Boolean = invoke(new NonCumulativeOp[Boolean] { + def position = macroDef.pos + def description = "compute boxity for this macro definition" + def default = standardIsBlackbox(macroDef) + def custom(plugin: MacroPlugin) = plugin.pluginsIsBlackbox(macroDef) + }) + /** @see MacroPlugin.pluginsMacroExpand */ def pluginsMacroExpand(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = invoke(new NonCumulativeOp[Tree] { def position = expandee.pos diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index f4456998c0..aa7a570937 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -263,7 +263,12 @@ trait Macros extends MacroRuntimes with Traces with Helpers { } def isBlackbox(expandee: Tree): Boolean = isBlackbox(dissectApplied(expandee).core.symbol) - def isBlackbox(macroDef: Symbol): Boolean = { + def isBlackbox(macroDef: Symbol): Boolean = pluginsIsBlackbox(macroDef) + + /** Default implementation of `isBlackbox`. + * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsIsBlackbox for more details) + */ + def standardIsBlackbox(macroDef: Symbol): Boolean = { val fastTrackBoxity = fastTrack.get(macroDef).map(_.isBlackbox) val bindingBoxity = loadMacroImplBinding(macroDef).map(_.isBlackbox) fastTrackBoxity orElse bindingBoxity getOrElse false diff --git a/test/files/run/macroPlugins-isBlackbox/Macros_2.scala b/test/files/run/macroPlugins-isBlackbox/Macros_2.scala new file mode 100644 index 0000000000..a90dd702df --- /dev/null +++ b/test/files/run/macroPlugins-isBlackbox/Macros_2.scala @@ -0,0 +1,11 @@ +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context + +object Macros { + def impl(c: Context) = { + import c.universe._ + q"42" + } + + def foo: Any = macro impl +}
\ No newline at end of file diff --git a/test/files/run/macroPlugins-isBlackbox/Plugin_1.scala b/test/files/run/macroPlugins-isBlackbox/Plugin_1.scala new file mode 100644 index 0000000000..b78a18ea6a --- /dev/null +++ b/test/files/run/macroPlugins-isBlackbox/Plugin_1.scala @@ -0,0 +1,21 @@ +package isblackbox + +import scala.tools.nsc.Global +import scala.tools.nsc.plugins.{Plugin => NscPlugin} + +class Plugin(val global: Global) extends NscPlugin { + import global._ + import analyzer._ + import scala.reflect.internal.Mode + + val name = "isBlackbox" + val description = "A sample analyzer plugin that overrides isBlackbox." + val components = Nil + addMacroPlugin(MacroPlugin) + + object MacroPlugin extends MacroPlugin { + override def pluginsIsBlackbox(macroDef: Symbol): Option[Boolean] = { + Some(false) + } + } +}
\ No newline at end of file diff --git a/test/files/run/macroPlugins-isBlackbox/Test_3.flags b/test/files/run/macroPlugins-isBlackbox/Test_3.flags new file mode 100644 index 0000000000..966df731d0 --- /dev/null +++ b/test/files/run/macroPlugins-isBlackbox/Test_3.flags @@ -0,0 +1 @@ +-Xplugin:.
\ No newline at end of file diff --git a/test/files/run/macroPlugins-isBlackbox/Test_3.scala b/test/files/run/macroPlugins-isBlackbox/Test_3.scala new file mode 100644 index 0000000000..552e888143 --- /dev/null +++ b/test/files/run/macroPlugins-isBlackbox/Test_3.scala @@ -0,0 +1,3 @@ +object Test extends App { + val x: Int = Macros.foo +}
\ No newline at end of file diff --git a/test/files/run/macroPlugins-isBlackbox/scalac-plugin.xml b/test/files/run/macroPlugins-isBlackbox/scalac-plugin.xml new file mode 100644 index 0000000000..09b9c14648 --- /dev/null +++ b/test/files/run/macroPlugins-isBlackbox/scalac-plugin.xml @@ -0,0 +1,4 @@ +<plugin> + <name>is-blackbox</name> + <classname>isblackbox.Plugin</classname> +</plugin>
\ No newline at end of file |