summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/macros/contexts/Internals.scala32
-rw-r--r--src/reflect/scala/reflect/macros/Internals.scala47
2 files changed, 78 insertions, 1 deletions
diff --git a/src/compiler/scala/reflect/macros/contexts/Internals.scala b/src/compiler/scala/reflect/macros/contexts/Internals.scala
index e0f7824cf3..e35a8ae034 100644
--- a/src/compiler/scala/reflect/macros/contexts/Internals.scala
+++ b/src/compiler/scala/reflect/macros/contexts/Internals.scala
@@ -1,9 +1,39 @@
package scala.reflect.macros
package contexts
-trait Internals {
+trait Internals extends scala.tools.nsc.transform.TypingTransformers {
self: Context =>
+ import global._
+
lazy val internal: ContextInternalApi = new global.SymbolTableInternal with ContextInternalApi {
+ class HofTransformer(hof: (Tree, TransformApi) => Tree) extends Transformer {
+ val api = new TransformApi {
+ def recur(tree: Tree): Tree = hof(tree, this)
+ def default(tree: Tree): Tree = superTransform(tree)
+ }
+ def superTransform(tree: Tree) = super.transform(tree)
+ override def transform(tree: Tree): Tree = hof(tree, api)
+ }
+
+ def transform(tree: Tree)(transformer: (Tree, TransformApi) => Tree): Tree = new HofTransformer(transformer).transform(tree)
+
+ class HofTypingTransformer(hof: (Tree, TypingTransformApi) => Tree) extends TypingTransformer(callsiteTyper.context.unit) { self =>
+ currentOwner = callsiteTyper.context.owner
+ curTree = EmptyTree
+ localTyper = global.analyzer.newTyper(callsiteTyper.context.make(unit = callsiteTyper.context.unit))
+
+ val api = new TypingTransformApi {
+ def recur(tree: Tree): Tree = hof(tree, this)
+ def default(tree: Tree): Tree = superTransform(tree)
+ def atOwner[T](owner: Symbol)(op: => T): T = self.atOwner(owner)(op)
+ def currentOwner: Symbol = self.currentOwner
+ def typecheck(tree: Tree): Tree = localTyper.typed(tree)
+ }
+ def superTransform(tree: Tree) = super.transform(tree)
+ override def transform(tree: Tree): Tree = hof(tree, api)
+ }
+
+ def typingTransform(tree: Tree)(transformer: (Tree, TypingTransformApi) => Tree): Tree = new HofTypingTransformer(transformer).transform(tree)
}
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/macros/Internals.scala b/src/reflect/scala/reflect/macros/Internals.scala
index f74f120470..415e70c36e 100644
--- a/src/reflect/scala/reflect/macros/Internals.scala
+++ b/src/reflect/scala/reflect/macros/Internals.scala
@@ -14,5 +14,52 @@ trait Internals {
/** @see [[scala.reflect.api.Internals]] */
trait ContextInternalApi extends universe.MacroInternalApi {
+ /** Functions that are available during [[transform]].
+ * @see [[transform]]
+ */
+ trait TransformApi {
+ /** Calls the current transformer on the given tree.
+ * Current transformer = argument to the `transform` call.
+ */
+ def recur(tree: Tree): Tree
+
+ /** Calls the default transformer on the given tree.
+ * Default transformer = recur into tree's children and assemble the results.
+ */
+ def default(tree: Tree): Tree
+ }
+
+ /** Transforms a given tree using the provided function.
+ * @see [[TransformApi]]
+ */
+ // TODO: explore a more concise notation that Denys and I discussed today
+ // when transformer is PartialFunction[Tree, Tree]] and TransformApi is passed magically
+ // also cf. https://github.com/dsl-paradise/dsl-paradise
+ def transform(tree: Tree)(transformer: (Tree, TransformApi) => Tree): Tree
+
+ /** Functions that are available during [[typingTransform]].
+ * @see [[typingTransform]]
+ */
+ trait TypingTransformApi extends TransformApi {
+ /** Temporarily pushes the given symbol onto the owner stack, creating a new local typer,
+ * invoke the given operation and then rollback the changes to the owner stack.
+ */
+ def atOwner[T](owner: Symbol)(op: => T): T
+
+ /** Returns the symbol currently on the top of the owner stack.
+ * If we're not inside any `atOwner` call, then macro application's context owner will be used.
+ */
+ def currentOwner: Symbol
+
+ /** Typechecks the given tree using the local typer currently on the top of the owner stack.
+ * If we're not inside any `atOwner` call, then macro application's callsite typer will be used.
+ */
+ def typecheck(tree: Tree): Tree
+ }
+
+ /** Transforms a given tree using the provided function.
+ * @see [[TypingTransformApi]]
+ */
+ def typingTransform(tree: Tree)(transformer: (Tree, TypingTransformApi) => Tree): Tree
}
}