@@ -143,12 +143,41 @@ class ReifyQuotes extends MacroTransform {
143143 }
144144
145145 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.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+ */
146156 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(" 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
147176 def liftedValue (lifter : Symbol ) =
148177 ref(lifter).appliedToType(originalTp).select(nme.toExpr).appliedTo(lit)
149178 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 )
152181 case Constants .BooleanTag => liftedValue(defn.LiftableModule_BooleanLiftable )
153182 case Constants .ByteTag => liftedValue(defn.LiftableModule_ByteLiftable )
154183 case Constants .ShortTag => liftedValue(defn.LiftableModule_ShortLiftable )
@@ -177,7 +206,7 @@ class ReifyQuotes extends MacroTransform {
177206 else pickleAsTasty()
178207 }
179208 else getLiteral(body) match {
180- case Some (lit) => pickleAsLiteral (lit)
209+ case Some (lit) => pickleAsValue (lit)
181210 case _ => pickleAsTasty()
182211 }
183212 }
0 commit comments