@@ -2,7 +2,7 @@ package dotty.tools
22package dotc
33package typer
44
5- import ast ._
5+ import ast .{ TreeInfo , tpd , _ }
66import Trees ._
77import core ._
88import Flags ._
@@ -26,7 +26,8 @@ import collection.mutable
2626import reporting .trace
2727import util .Spans .Span
2828import util .SourcePosition
29- import ast .TreeInfo
29+ import dotty .tools .dotc .core .quoted .Spliced
30+ import dotty .tools .dotc .transform .{Splicer , TreeMapWithStages }
3031
3132object Inliner {
3233 import tpd ._
@@ -106,7 +107,7 @@ object Inliner {
106107 else if (enclosingInlineds.length < ctx.settings.XmaxInlines .value) {
107108 val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
108109 if (ctx.reporter.hasErrors) tree
109- else new Inliner (tree, body).inlined(pt)
110+ else new Inliner (tree, body).inlined(pt, tree.sourcePos )
110111 }
111112 else
112113 errorTree(
@@ -359,7 +360,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
359360 }
360361
361362 /** The Inlined node representing the inlined call */
362- def inlined (pt : Type ): Tree = {
363+ def inlined (pt : Type , sourcePos : SourcePosition ): Tree = {
363364
364365 if (callTypeArgs.length == 1 )
365366 if (inlinedMethod == defn.Compiletime_constValue ) {
@@ -465,10 +466,21 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
465466 trace(i " inlining $call" , inlining, show = true ) {
466467
467468 // The normalized bindings collected in `bindingsBuf`
468- bindingsBuf.transform(reducer.normalizeBinding(_)(inlineCtx))
469+ bindingsBuf.transform { binding =>
470+ val transformedBinding = reducer.normalizeBinding(binding)(inlineCtx)
471+ // Set trees to symbols allow macros to see the definition tree.
472+ // This is used by `underlyingArgument`.
473+ transformedBinding.symbol.defTree = transformedBinding
474+ transformedBinding
475+ }
476+
477+ // Evaluate the top level ~ if it is a macro
478+ val expansion0 =
479+ if (call.symbol.is(Macro ) && TreeMapWithStages .level == 0 ) expandMacro(expansion, sourcePos)
480+ else expansion
469481
470482 // Run a typing pass over the inlined tree. See InlineTyper for details.
471- val expansion1 = inlineTyper.typed(expansion , pt)(inlineCtx)
483+ val expansion1 = inlineTyper.typed(expansion0 , pt)(inlineCtx)
472484
473485 if (ctx.settings.verbose.value) {
474486 inlining.println(i " to inline = $rhsToInline" )
@@ -487,6 +499,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
487499 }
488500 }
489501
502+ private def expandMacro (expansion : Tree , pos : SourcePosition ) = {
503+ // TODO cache macro classloader
504+ val urls = ctx.settings.classpath.value.split(java.io.File .pathSeparatorChar).map(cp => java.nio.file.Paths .get(cp).toUri.toURL)
505+ val macroClassLoader = new java.net.URLClassLoader (urls, getClass.getClassLoader)
506+
507+ new TreeMap () {
508+ override def transform (tree1 : tpd.Tree )(implicit ctx : Context ): tpd.Tree = tree1 match {
509+ case Spliced (splicedBody) =>
510+ val evaluatedSplice = Splicer .splice(splicedBody, pos, macroClassLoader).withSpan(tree1.span)
511+ if (ctx.reporter.hasErrors) EmptyTree
512+ else evaluatedSplice
513+ case _ =>
514+ super .transform(tree1)
515+ }
516+ }.transform(expansion)
517+ }
518+
490519 /** A utility object offering methods for rewriting inlined code */
491520 object reducer {
492521
0 commit comments