@@ -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 ._
@@ -25,6 +25,7 @@ import dotty.tools.dotc.util.{SimpleIdentityMap, SimpleIdentitySet, SourceFile,
2525import collection .mutable
2626import reporting .trace
2727import util .Spans .Span
28+ import dotty .tools .dotc .transform .{Splicer , TreeMapWithStages }
2829
2930object Inliner {
3031 import tpd ._
@@ -104,7 +105,7 @@ object Inliner {
104105 else if (enclosingInlineds.length < ctx.settings.XmaxInlines .value) {
105106 val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
106107 if (ctx.reporter.hasErrors) tree
107- else new Inliner (tree, body).inlined(pt)
108+ else new Inliner (tree, body).inlined(pt, tree.sourcePos )
108109 }
109110 else
110111 errorTree(
@@ -381,7 +382,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
381382 }
382383
383384 /** The Inlined node representing the inlined call */
384- def inlined (pt : Type ): Tree = {
385+ def inlined (pt : Type , sourcePos : SourcePosition ): Tree = {
385386
386387 if (callTypeArgs.length == 1 )
387388 if (inlinedMethod == defn.Compiletime_constValue ) {
@@ -487,10 +488,21 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
487488 trace(i " inlining $call" , inlining, show = true ) {
488489
489490 // The normalized bindings collected in `bindingsBuf`
490- bindingsBuf.transform(reducer.normalizeBinding(_)(inlineCtx))
491+ bindingsBuf.transform { binding =>
492+ val transformedBinding = reducer.normalizeBinding(binding)(inlineCtx)
493+ // Set trees to symbols allow macros to see the definition tree.
494+ // This is used by `underlyingArgument`.
495+ transformedBinding.symbol.defTree = transformedBinding
496+ transformedBinding
497+ }
498+
499+ // Evaluate the top level ~ if it is a macro
500+ val expansion0 =
501+ if (call.symbol.is(Macro ) && TreeMapWithStages .level == 0 ) expandMacro(expansion, sourcePos)
502+ else expansion
491503
492504 // Run a typing pass over the inlined tree. See InlineTyper for details.
493- val expansion1 = inlineTyper.typed(expansion , pt)(inlineCtx)
505+ val expansion1 = inlineTyper.typed(expansion0 , pt)(inlineCtx)
494506
495507 if (ctx.settings.verbose.value) {
496508 inlining.println(i " to inline = $rhsToInline" )
@@ -509,6 +521,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
509521 }
510522 }
511523
524+ private def expandMacro (expansion : Tree , pos : SourcePosition ) = {
525+ // TODO cache macro classloader
526+ val urls = ctx.settings.classpath.value.split(java.io.File .pathSeparatorChar).map(cp => java.nio.file.Paths .get(cp).toUri.toURL)
527+ val macroClassLoader = new java.net.URLClassLoader (urls, getClass.getClassLoader)
528+
529+ new TreeMap () {
530+ override def transform (tree1 : tpd.Tree )(implicit ctx : Context ): tpd.Tree = tree1 match {
531+ case Spliced (splicedBody) =>
532+ val evaluatedSplice = Splicer .splice(splicedBody, pos, macroClassLoader).withSpan(tree1.span)
533+ if (ctx.reporter.hasErrors) EmptyTree
534+ else evaluatedSplice
535+ case _ =>
536+ super .transform(tree1)
537+ }
538+ }.transform(expansion)
539+ }
540+
512541 /** A utility object offering methods for rewriting inlined code */
513542 object reducer {
514543
0 commit comments