@@ -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 ._
@@ -25,6 +25,7 @@ import dotty.tools.dotc.util.{SimpleIdentityMap, SimpleIdentitySet, SourceFile,
25
25
import collection .mutable
26
26
import reporting .trace
27
27
import util .Spans .Span
28
+ import dotty .tools .dotc .transform .{Splicer , TreeMapWithStages }
28
29
29
30
object Inliner {
30
31
import tpd ._
@@ -104,7 +105,7 @@ object Inliner {
104
105
else if (enclosingInlineds.length < ctx.settings.XmaxInlines .value) {
105
106
val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
106
107
if (ctx.reporter.hasErrors) tree
107
- else new Inliner (tree, body).inlined(pt)
108
+ else new Inliner (tree, body).inlined(pt, tree.sourcePos )
108
109
}
109
110
else
110
111
errorTree(
@@ -381,7 +382,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
381
382
}
382
383
383
384
/** The Inlined node representing the inlined call */
384
- def inlined (pt : Type ): Tree = {
385
+ def inlined (pt : Type , sourcePos : SourcePosition ): Tree = {
385
386
386
387
if (callTypeArgs.length == 1 )
387
388
if (inlinedMethod == defn.Compiletime_constValue ) {
@@ -487,7 +488,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
487
488
trace(i " inlining $call" , inlining, show = true ) {
488
489
489
490
// 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
+ }
491
498
492
499
// Run a typing pass over the inlined tree. See InlineTyper for details.
493
500
val expansion1 = inlineTyper.typed(expansion, pt)(inlineCtx)
@@ -949,11 +956,25 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
949
956
override def typedSelect (tree : untpd.Select , pt : Type )(implicit ctx : Context ): Tree = {
950
957
assert(tree.hasType, tree)
951
958
val qual1 = typed(tree.qualifier, selectionProto(tree.name, pt, this ))
952
- val res = untpd.cpy.Select (tree)(qual1, tree.name).withType(tree.typeOpt)
959
+ val res =
960
+ if (tree.symbol == defn.QuotedExpr_splice && StagingContext .level == 0 ) expandMacro(qual1, tree.span)
961
+ else untpd.cpy.Select (tree)(qual1, tree.name).withType(tree.typeOpt)
953
962
ensureAccessible(res.tpe, tree.qualifier.isInstanceOf [untpd.Super ], tree.sourcePos)
954
963
res
955
964
}
956
965
966
+ private def expandMacro (body : Tree , span : Span )(implicit ctx : Context ) = {
967
+ assert(StagingContext .level == 0 )
968
+ // TODO cache macro classloader
969
+ val urls = ctx.settings.classpath.value.split(java.io.File .pathSeparatorChar).map(cp => java.nio.file.Paths .get(cp).toUri.toURL)
970
+ val macroClassLoader = new java.net.URLClassLoader (urls, getClass.getClassLoader)
971
+
972
+ val inlinedFrom = enclosingInlineds.last
973
+ val evaluatedSplice = Splicer .splice(body, inlinedFrom.sourcePos, macroClassLoader)(ctx.withSource(inlinedFrom.source))
974
+ if (ctx.reporter.hasErrors) EmptyTree
975
+ else evaluatedSplice.withSpan(span)
976
+ }
977
+
957
978
override def typedIf (tree : untpd.If , pt : Type )(implicit ctx : Context ): Tree =
958
979
typed(tree.cond, defn.BooleanType ) match {
959
980
case cond1 @ ConstantValue (b : Boolean ) =>
0 commit comments