@@ -2,7 +2,7 @@ package dotty.tools
2
2
package dotc
3
3
package typer
4
4
5
- import ast ._
5
+ import ast .{ TreeInfo , tpd , _ }
6
6
import Trees ._
7
7
import core ._
8
8
import Flags ._
@@ -26,7 +26,8 @@ import collection.mutable
26
26
import reporting .trace
27
27
import util .Spans .Span
28
28
import util .SourcePosition
29
- import ast .TreeInfo
29
+ import dotty .tools .dotc .core .quoted .Spliced
30
+ import dotty .tools .dotc .transform .{Splicer , TreeMapWithStages }
30
31
31
32
object Inliner {
32
33
import tpd ._
@@ -106,7 +107,7 @@ object Inliner {
106
107
else if (enclosingInlineds.length < ctx.settings.XmaxInlines .value) {
107
108
val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
108
109
if (ctx.reporter.hasErrors) tree
109
- else new Inliner (tree, body).inlined(pt)
110
+ else new Inliner (tree, body).inlined(pt, tree.sourcePos )
110
111
}
111
112
else
112
113
errorTree(
@@ -359,7 +360,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
359
360
}
360
361
361
362
/** The Inlined node representing the inlined call */
362
- def inlined (pt : Type ): Tree = {
363
+ def inlined (pt : Type , sourcePos : SourcePosition ): Tree = {
363
364
364
365
if (callTypeArgs.length == 1 )
365
366
if (inlinedMethod == defn.Compiletime_constValue ) {
@@ -465,10 +466,21 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
465
466
trace(i " inlining $call" , inlining, show = true ) {
466
467
467
468
// 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
469
481
470
482
// 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)
472
484
473
485
if (ctx.settings.verbose.value) {
474
486
inlining.println(i " to inline = $rhsToInline" )
@@ -487,6 +499,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
487
499
}
488
500
}
489
501
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
+
490
519
/** A utility object offering methods for rewriting inlined code */
491
520
object reducer {
492
521
0 commit comments