diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-02-01 00:13:53 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-02-14 23:51:24 +0100 |
commit | 8c29132055845181a34ed9077d30fac87c284574 (patch) | |
tree | 29c5bb2ca8be67e324ee3e0f9d78bc62bf00d8b3 /src/compiler/scala/reflect/macros | |
parent | 73adf2d9de441e151a117a5b33ae707ad79a9f36 (diff) | |
download | scala-8c29132055845181a34ed9077d30fac87c284574.tar.gz scala-8c29132055845181a34ed9077d30fac87c284574.tar.bz2 scala-8c29132055845181a34ed9077d30fac87c284574.zip |
adds internal.typingTransform
As per Jason’s request, this commit introduces a facility to perform
tree transformations that know how to track current lexical context
and how to typecheck trees in that lexical context.
Interestingly enough, we can’t get away with the traditional “subclass the
Transformer” approach, because the required base transformer class is
declared in scala-compiler.jar, and our API is defined in scala-reflect.jar.
This forced me to play with an idea that we’ve discussed with Denys today
(actually, it’s already yesterday) - lightweight transformers that take
contextful HOFs. This commit is a sketch in that direction. Turning
`transform` and `typingTransform` into macros would make the API more
elegant (see the comments), but I didn’t have time to experiment.
I’m running short on time, so I haven’t had a chance to actually test this API,
but I’m still submitting the pull request to ignite a discussion.
Diffstat (limited to 'src/compiler/scala/reflect/macros')
-rw-r--r-- | src/compiler/scala/reflect/macros/contexts/Internals.scala | 32 |
1 files changed, 31 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 |