@@ -9,59 +9,60 @@ import MegaPhase.MiniPhase
9
9
import scala .collection .mutable
10
10
11
11
/** Translates quoted terms and types to reify method calls.
12
+ * The mini phase needs to run in the same group as FirstTransform. So far we lack
13
+ * the machinery to express this constraint in code.
12
14
*/
13
15
class ReifyQuotes extends MiniPhase {
14
16
import ast .tpd ._
15
17
16
18
override def phaseName : String = " reifyQuotes"
17
19
18
- def reifyTree (tree : Tree )(implicit ctx : Context ): String = i " ( $tree) " // TODO: replace with TASTY
19
- def reifyType (tpe : Type )(implicit ctx : Context ): String = i " [ $tpe] " // TODO: replace with TASTY
20
+ /** Serialize `tree`. Embedded splices are represented as nodes of the form
21
+ *
22
+ * Select(qual, sym)
23
+ *
24
+ * where `sym` is either `defn.MetaExpr_~` or `defn.MetaType_~`. For any splice,
25
+ * the `qual` part will be of the form `Typed(EmptyTree, TypeTree(<underlying type>))`,
26
+ * but that knowledge is not needed to uniquely identify a splice node.
27
+ */
28
+ def reifyTree (tree : Tree )(implicit ctx : Context ): String = tree.show // TODO: replace with TASTY
20
29
21
- private def reifyCall (meth : Symbol , typeArg : Type , reified : String , splices : List [Tree ])(implicit ctx : Context ) =
22
- ref(meth)
23
- .appliedToType(typeArg)
24
- .appliedTo(
25
- Literal (Constant (reified)),
26
- SeqLiteral (splices, TypeTree (defn.MetaExprType .appliedTo(TypeBounds .empty))))
30
+ private def reifyCall (body : Tree , isType : Boolean )(implicit ctx : Context ) = {
27
31
28
- override def transformApply (tree : Apply )(implicit ctx : Context ): Tree = {
29
32
object liftSplices extends TreeMap {
30
33
val splices = new mutable.ListBuffer [Tree ]
31
34
override def transform (tree : Tree )(implicit ctx : Context ) = tree match {
32
- case tree @ Select (qual, name) if tree.symbol == defn.MetaExpr_~ =>
35
+ case tree @ Select (qual, name)
36
+ if tree.symbol == defn.MetaExpr_~ || tree.symbol == defn.MetaType_~ =>
33
37
splices += qual
34
38
val placeHolder = Typed (EmptyTree , TypeTree (qual.tpe.widen))
35
39
cpy.Select (tree)(placeHolder, name)
36
40
case _ =>
37
41
super .transform(tree)
38
42
}
39
43
}
40
- if (tree.fun.symbol == defn.quoteMethod) {
41
- val body = tree.args.head
42
- val reified = reifyTree(liftSplices.transform(body))
43
- reifyCall(defn.Reifier_reifyExpr , body.tpe.widen, reified, liftSplices.splices.toList)
44
- }
45
- else tree
44
+
45
+ val reified = reifyTree(liftSplices.transform(body))
46
+ var splices = liftSplices.splices.toList
47
+ if (isType) // transform splices again because embedded type trees were not rewritten before
48
+ splices = splices.map(transformAllDeep(_)(ctx.retractMode(Mode .InQuotedType )))
49
+ val spliceType = if (isType) defn.MetaTypeType else defn.MetaExprType
50
+
51
+ ref(if (isType) defn.Reifier_reifyType else defn.Reifier_reifyExpr )
52
+ .appliedToType(if (isType) body.tpe else body.tpe.widen)
53
+ .appliedTo(
54
+ Literal (Constant (reified)),
55
+ SeqLiteral (splices, TypeTree (spliceType.appliedTo(TypeBounds .empty))))
46
56
}
47
57
48
- override def transformTypeApply (tree : TypeApply )(implicit ctx : Context ): Tree = {
49
- object liftSplices extends TypeMap {
50
- val splices = new mutable.ListBuffer [Tree ]
51
- override def apply (t : Type ) = t match {
52
- case t @ TypeRef (pre : TermRef , _) if t.symbol == defn.MetaType_~ =>
53
- splices += ref(pre).withPos(tree.args.head.pos)
54
- val placeHolder = SkolemType (pre.widen)
55
- t.withPrefix(placeHolder)
56
- case _ =>
57
- mapOver(t)
58
- }
59
- }
60
- if (tree.fun.symbol == defn.typeQuoteMethod) {
61
- val body = tree.args.head.tpe
62
- val reified = reifyType(liftSplices(body))
63
- reifyCall(defn.Reifier_reifyType , body, reified, liftSplices.splices.toList)
64
- }
58
+ override def transformApply (tree : Apply )(implicit ctx : Context ): Tree =
59
+ if (tree.fun.symbol == defn.quoteMethod) reifyCall(tree.args.head, isType = false )
65
60
else tree
66
- }
67
- }
61
+
62
+ override def prepareForTypeApply (tree : TypeApply )(implicit ctx : Context ): Context =
63
+ if (tree.symbol == defn.typeQuoteMethod) ctx.addMode(Mode .InQuotedType ) else ctx
64
+
65
+ override def transformTypeApply (tree : TypeApply )(implicit ctx : Context ): Tree =
66
+ if (tree.fun.symbol == defn.typeQuoteMethod) reifyCall(tree.args.head, isType = true )
67
+ else tree
68
+ }
0 commit comments