@@ -9,7 +9,7 @@ import util.Positions._
9
9
import tasty .TreePickler .Hole
10
10
import SymUtils ._
11
11
import NameKinds ._
12
- import dotty .tools .dotc .ast .tpd . Tree
12
+ import dotty .tools .dotc .ast .tpd
13
13
import typer .Implicits .SearchFailureType
14
14
15
15
import scala .collection .mutable
@@ -61,6 +61,7 @@ import dotty.tools.dotc.util.SourcePosition
61
61
*/
62
62
class ReifyQuotes extends MacroTransformWithImplicits {
63
63
import ast .tpd ._
64
+ import ReifyQuotes ._
64
65
65
66
/** Classloader used for loading macros */
66
67
private [this ] var myMacroClassLoader : java.lang.ClassLoader = _
@@ -90,7 +91,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
90
91
if (ctx.compilationUnit.containsQuotesOrSplices) super .run
91
92
92
93
protected def newTransformer (implicit ctx : Context ): Transformer =
93
- new Reifier (inQuote = false , null , 0 , new LevelInfo , new mutable. ListBuffer , ctx)
94
+ new Reifier (inQuote = false , null , 0 , new LevelInfo , new Embedded , ctx)
94
95
95
96
private class LevelInfo {
96
97
/** A map from locally defined symbols to the staging levels of their definitions */
@@ -123,13 +124,13 @@ class ReifyQuotes extends MacroTransformWithImplicits {
123
124
* @param rctx the contex in the destination lifted lambda
124
125
*/
125
126
private class Reifier (inQuote : Boolean , val outer : Reifier , val level : Int , levels : LevelInfo ,
126
- val embedded : mutable. ListBuffer [ Tree ] , val rctx : Context ) extends ImplicitsTransformer {
127
+ val embedded : Embedded , val rctx : Context ) extends ImplicitsTransformer {
127
128
import levels ._
128
129
assert(level >= - 1 )
129
130
130
131
/** A nested reifier for a quote (if `isQuote = true`) or a splice (if not) */
131
132
def nested (isQuote : Boolean )(implicit ctx : Context ): Reifier = {
132
- val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new mutable. ListBuffer [ Tree ]
133
+ val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new Embedded
133
134
new Reifier (isQuote, this , if (isQuote) level + 1 else level - 1 , levels, nestedEmbedded, ctx)
134
135
}
135
136
@@ -423,7 +424,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
423
424
}
424
425
else if (level == 1 ) {
425
426
val (body1, quotes) = nested(isQuote = false ).split(splice.qualifier)
426
- makeHole(body1, quotes, splice.tpe).withPos(splice.pos)
427
+ val tpe = outer.embedded.getHoleType(splice)
428
+ makeHole(body1, quotes, tpe).withPos(splice.pos)
427
429
}
428
430
else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call
429
431
val spliceCtx = ctx.outer // drop the last `inlineContext`
@@ -478,14 +480,18 @@ class ReifyQuotes extends MacroTransformWithImplicits {
478
480
(captured : mutable.Map [Symbol , Tree ]) => {
479
481
(tree : Tree ) => {
480
482
def newCapture = {
481
- val tpw = tree.tpe.widen
483
+ val tpw = tree.tpe.widen match {
484
+ case tpw : MethodicType => tpw.toFunctionType()
485
+ case tpw => tpw
486
+ }
487
+ assert(tpw.isInstanceOf [ValueType ])
482
488
val argTpe =
483
489
if (tree.isType) defn.QuotedTypeType .appliedTo(tpw)
484
490
else defn.QuotedExprType .appliedTo(tpw)
485
491
val selectArg = arg.select(nme.apply).appliedTo(Literal (Constant (i))).asInstance(argTpe)
486
492
val capturedArg = SyntheticValDef (UniqueName .fresh(tree.symbol.name.toTermName).toTermName, selectArg)
487
493
i += 1
488
- embedded += tree
494
+ embedded.addTree( tree, capturedArg.symbol)
489
495
captured.put(tree.symbol, capturedArg)
490
496
capturedArg
491
497
}
@@ -526,15 +532,14 @@ class ReifyQuotes extends MacroTransformWithImplicits {
526
532
*/
527
533
private def split (tree : Tree )(implicit ctx : Context ): (Tree , List [Tree ]) = {
528
534
val tree1 = if (inQuote) addTags(transform(tree)) else makeLambda(tree)
529
- (tree1, embedded.toList )
535
+ (tree1, embedded.getTrees )
530
536
}
531
537
532
538
/** Register `body` as an `embedded` quote or splice
533
539
* and return a hole with `splices` as arguments and the given type `tpe`.
534
540
*/
535
541
private def makeHole (body : Tree , splices : List [Tree ], tpe : Type )(implicit ctx : Context ): Hole = {
536
- val idx = embedded.length
537
- embedded += body
542
+ val idx = embedded.addTree(body, NoSymbol )
538
543
Hole (idx, splices).withType(tpe).asInstanceOf [Hole ]
539
544
}
540
545
@@ -624,10 +629,31 @@ class ReifyQuotes extends MacroTransformWithImplicits {
624
629
object ReifyQuotes {
625
630
val name = " reifyQuotes"
626
631
627
- def toValue (tree : Tree ): Option [Any ] = tree match {
632
+ def toValue (tree : tpd. Tree ): Option [Any ] = tree match {
628
633
case Literal (Constant (c)) => Some (c)
629
634
case Block (Nil , e) => toValue(e)
630
635
case Inlined (_, Nil , e) => toValue(e)
631
636
case _ => None
632
637
}
638
+
639
+ class Embedded (trees : mutable.ListBuffer [tpd.Tree ] = mutable.ListBuffer .empty, map : mutable.Map [Symbol , tpd.Tree ] = mutable.Map .empty) {
640
+ /** Adds the tree and returns it's index */
641
+ def addTree (tree : tpd.Tree , liftedSym : Symbol ): Int = {
642
+ trees += tree
643
+ if (liftedSym ne NoSymbol )
644
+ map.put(liftedSym, tree)
645
+ trees.length - 1
646
+ }
647
+
648
+ /** Type used for the hole that will replace this splice */
649
+ def getHoleType (splice : tpd.Select )(implicit ctx : Context ): Type = {
650
+ // For most expressions the splice.tpe but there are some types that are lost by lifting
651
+ // that can be recoverd from the original tree. Currently the cases are:
652
+ // * Method types: the splice represents a method reference
653
+ map.get(splice.qualifier.symbol).map(_.tpe.widen).getOrElse(splice.tpe)
654
+ }
655
+
656
+ /** Get the list of embedded trees */
657
+ def getTrees : List [tpd.Tree ] = trees.toList
658
+ }
633
659
}
0 commit comments