@@ -143,12 +143,41 @@ class ReifyQuotes extends MacroTransform {
143
143
}
144
144
145
145
private def pickledQuote (body : Tree , splices : List [Tree ], originalTp : Type , isType : Boolean )(using Context ) = {
146
+ /** Encode quote using Reflection.Literal
147
+ *
148
+ * Generate the code
149
+ * ```scala
150
+ * qctx => qctx.reflect.TreeMethods.extension_asExpr(
151
+ * qctx.reflect.Literal.apply(x$1.reflect.Constant.<typeName>.apply(<literalValue>))
152
+ * ).asInstanceOf[scala.quoted.Expr[<body.type>]]
153
+ * ```
154
+ * this closure is always applied directly to the actual context and the BetaReduce phase removes it.
155
+ */
146
156
def pickleAsLiteral (lit : Literal ) = {
157
+ val exprType = defn.QuotedExprClass .typeRef.appliedTo(body.tpe)
158
+ val tpe = MethodType (defn.QuoteContextClass .typeRef :: Nil , exprType)
159
+ val meth = newSymbol(ctx.owner, UniqueName .fresh(nme.ANON_FUN ), Synthetic | Method , tpe)
160
+ def mkConst (tss : List [List [Tree ]]) = {
161
+ val reflect = tss.head.head.select(" reflect" .toTermName)
162
+ val typeName = body.tpe.typeSymbol.name
163
+ val literalValue =
164
+ if lit.const.tag == Constants .NullTag || lit.const.tag == Constants .UnitTag then Nil
165
+ else List (body)
166
+ val constant = reflect.select(" Constant" .toTermName).select(typeName.toTermName).select(nme.apply).appliedToArgs(literalValue)
167
+ val literal = reflect.select(" Literal" .toTermName).select(nme.apply).appliedTo(constant)
168
+ reflect.select(" TreeMethods" .toTermName).select(" extension_asExpr" .toTermName).appliedTo(literal).asInstance(exprType)
169
+ }
170
+ Closure (meth, mkConst).withSpan(body.span)
171
+ }
172
+
173
+ def pickleAsValue (lit : Literal ) = {
174
+ // TODO should all constants be pickled as Literals?
175
+ // Should examime the generated bytecode size to decide and performance
147
176
def liftedValue (lifter : Symbol ) =
148
177
ref(lifter).appliedToType(originalTp).select(nme.toExpr).appliedTo(lit)
149
178
lit.const.tag match {
150
- case Constants .NullTag => ref(defn. InternalQuotedExpr_null )
151
- case Constants .UnitTag => ref(defn. InternalQuotedExpr_unit )
179
+ case Constants .NullTag => pickleAsLiteral(lit )
180
+ case Constants .UnitTag => pickleAsLiteral(lit )
152
181
case Constants .BooleanTag => liftedValue(defn.LiftableModule_BooleanLiftable )
153
182
case Constants .ByteTag => liftedValue(defn.LiftableModule_ByteLiftable )
154
183
case Constants .ShortTag => liftedValue(defn.LiftableModule_ShortLiftable )
@@ -177,7 +206,7 @@ class ReifyQuotes extends MacroTransform {
177
206
else pickleAsTasty()
178
207
}
179
208
else getLiteral(body) match {
180
- case Some (lit) => pickleAsLiteral (lit)
209
+ case Some (lit) => pickleAsValue (lit)
181
210
case _ => pickleAsTasty()
182
211
}
183
212
}
0 commit comments