diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 7162b67e6691..064d4ae97ede 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -630,12 +630,23 @@ class Definitions { @tu lazy val QuotedExprClass: ClassSymbol = ctx.requiredClass("scala.quoted.Expr") @tu lazy val QuotedExprModule: Symbol = QuotedExprClass.companionModule + @tu lazy val QuotedExprModule_nullExpr: Symbol = QuotedExprModule.requiredMethod(nme.nullExpr) + @tu lazy val QuotedExprModule_unitExpr: Symbol = QuotedExprModule.requiredMethod(nme.unitExpr) @tu lazy val QuoteContextClass: ClassSymbol = ctx.requiredClass("scala.quoted.QuoteContext") @tu lazy val QuoteContextModule: Symbol = QuoteContextClass.companionModule @tu lazy val QuoteContext_macroContext: Symbol = QuoteContextModule.requiredMethod("macroContext") @tu lazy val LiftableModule: Symbol = ctx.requiredModule("scala.quoted.Liftable") + @tu lazy val LiftableModule_BooleanIsLiftable: Symbol = LiftableModule.requiredMethod("BooleanIsLiftable") + @tu lazy val LiftableModule_ByteIsLiftable: Symbol = LiftableModule.requiredMethod("ByteIsLiftable") + @tu lazy val LiftableModule_ShortIsLiftable: Symbol = LiftableModule.requiredMethod("ShortIsLiftable") + @tu lazy val LiftableModule_IntIsLiftable: Symbol = LiftableModule.requiredMethod("IntIsLiftable") + @tu lazy val LiftableModule_LongIsLiftable: Symbol = LiftableModule.requiredMethod("LongIsLiftable") + @tu lazy val LiftableModule_FloatIsLiftable: Symbol = LiftableModule.requiredMethod("FloatIsLiftable") + @tu lazy val LiftableModule_DoubleIsLiftable: Symbol = LiftableModule.requiredMethod("DoubleIsLiftable") + @tu lazy val LiftableModule_CharIsLiftable: Symbol = LiftableModule.requiredMethod("CharIsLiftable") + @tu lazy val LiftableModule_StringIsLiftable: Symbol = LiftableModule.requiredMethod("StringIsLiftable") @tu lazy val InternalQuotedModule: Symbol = ctx.requiredModule("scala.internal.Quoted") @tu lazy val InternalQuoted_exprQuote : Symbol = InternalQuotedModule.requiredMethod("exprQuote") diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index a7b6d9154a25..fe2746e50987 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -503,6 +503,7 @@ object StdNames { val notifyAll_ : N = "notifyAll" val notify_ : N = "notify" val null_ : N = "null" + val nullExpr: N = "nullExpr" val ofDim: N = "ofDim" val opaque: N = "opaque" val ordinal: N = "ordinal" @@ -556,6 +557,7 @@ object StdNames { val thisPrefix : N = "thisPrefix" val throw_ : N = "throw" val toArray: N = "toArray" + val toExpr: N = "toExpr" val toList: N = "toList" val toObjectArray : N = "toObjectArray" val toSeq: N = "toSeq" @@ -569,6 +571,7 @@ object StdNames { val unapply: N = "unapply" val unapplySeq: N = "unapplySeq" val unbox: N = "unbox" + val unitExpr: N = "unitExpr" val universe: N = "universe" val update: N = "update" val updateDynamic: N = "updateDynamic" diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 8aa8fd7f0542..b17efa5c5e22 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -206,25 +206,23 @@ class ReifyQuotes extends MacroTransform { qctx } - def liftedValue[T](value: T, name: TermName) = - ref(defn.LiftableModule) - .select(name).appliedToType(originalTp) - .select("toExpr".toTermName).appliedTo(Literal(Constant(value))) - - def pickleAsValue[T](value: T) = - value match { - case null => ref(defn.QuotedExprModule).select("nullExpr".toTermName) - case _: Unit => ref(defn.QuotedExprModule).select("unitExpr".toTermName) - case _: Boolean => liftedValue(value, "Liftable_Boolean_delegate".toTermName) - case _: Byte => liftedValue(value, "Liftable_Byte_delegate".toTermName) - case _: Short => liftedValue(value, "Liftable_Short_delegate".toTermName) - case _: Int => liftedValue(value, "Liftable_Int_delegate".toTermName) - case _: Long => liftedValue(value, "Liftable_Long_delegate".toTermName) - case _: Float => liftedValue(value, "Liftable_Float_delegate".toTermName) - case _: Double => liftedValue(value, "Liftable_Double_delegate".toTermName) - case _: Char => liftedValue(value, "Liftable_Char_delegate".toTermName) - case _: String => liftedValue(value, "Liftable_String_delegate".toTermName) + def pickleAsLiteral(lit: Literal) = { + def liftedValue(lifter: Symbol) = + ref(lifter).appliedToType(originalTp).select(nme.toExpr).appliedTo(lit) + lit.const.tag match { + case Constants.NullTag => ref(defn.QuotedExprModule_nullExpr) + case Constants.UnitTag => ref(defn.QuotedExprModule_unitExpr) + case Constants.BooleanTag => liftedValue(defn.LiftableModule_BooleanIsLiftable) + case Constants.ByteTag => liftedValue(defn.LiftableModule_ByteIsLiftable) + case Constants.ShortTag => liftedValue(defn.LiftableModule_ShortIsLiftable) + case Constants.IntTag => liftedValue(defn.LiftableModule_IntIsLiftable) + case Constants.LongTag => liftedValue(defn.LiftableModule_LongIsLiftable) + case Constants.FloatTag => liftedValue(defn.LiftableModule_FloatIsLiftable) + case Constants.DoubleTag => liftedValue(defn.LiftableModule_DoubleIsLiftable) + case Constants.CharTag => liftedValue(defn.LiftableModule_CharIsLiftable) + case Constants.StringTag => liftedValue(defn.LiftableModule_StringIsLiftable) } + } def pickleAsTasty() = { val meth = @@ -243,8 +241,8 @@ class ReifyQuotes extends MacroTransform { if (splices.isEmpty && body.symbol.isPrimitiveValueClass) tag(s"${body.symbol.name}Tag") else pickleAsTasty().select(nme.apply).appliedTo(qctx) } - else toValue(body) match { - case Some(value) => pickleAsValue(value) + else getLiteral(body) match { + case Some(lit) => pickleAsLiteral(lit) case _ => pickleAsTasty() } } @@ -429,10 +427,10 @@ object ReifyQuotes { val name: String = "reifyQuotes" - def toValue(tree: tpd.Tree): Option[Any] = tree match { - case Literal(Constant(c)) => Some(c) - case Block(Nil, e) => toValue(e) - case Inlined(_, Nil, e) => toValue(e) + def getLiteral(tree: tpd.Tree): Option[Literal] = tree match { + case tree: Literal => Some(tree) + case Block(Nil, e) => getLiteral(e) + case Inlined(_, Nil, e) => getLiteral(e) case _ => None } diff --git a/library/src-bootstrapped/scala/quoted/Liftable.scala b/library/src-bootstrapped/scala/quoted/Liftable.scala index 3a06170c1431..7d9efd98b0f9 100644 --- a/library/src-bootstrapped/scala/quoted/Liftable.scala +++ b/library/src-bootstrapped/scala/quoted/Liftable.scala @@ -19,15 +19,15 @@ trait Liftable[T] { */ object Liftable { - given Liftable_Boolean_delegate[T <: Boolean] : Liftable[T] = new PrimitiveLiftable - given Liftable_Byte_delegate[T <: Byte] : Liftable[T] = new PrimitiveLiftable - given Liftable_Short_delegate[T <: Short] : Liftable[T] = new PrimitiveLiftable - given Liftable_Int_delegate[T <: Int] : Liftable[T] = new PrimitiveLiftable - given Liftable_Long_delegate[T <: Long] : Liftable[T] = new PrimitiveLiftable - given Liftable_Float_delegate[T <: Float] : Liftable[T] = new PrimitiveLiftable - given Liftable_Double_delegate[T <: Double] : Liftable[T] = new PrimitiveLiftable - given Liftable_Char_delegate[T <: Char] : Liftable[T] = new PrimitiveLiftable - given Liftable_String_delegate[T <: String] : Liftable[T] = new PrimitiveLiftable + given BooleanIsLiftable[T <: Boolean] : Liftable[T] = new PrimitiveLiftable + given ByteIsLiftable[T <: Byte] : Liftable[T] = new PrimitiveLiftable + given ShortIsLiftable[T <: Short] : Liftable[T] = new PrimitiveLiftable + given IntIsLiftable[T <: Int] : Liftable[T] = new PrimitiveLiftable + given LongIsLiftable[T <: Long] : Liftable[T] = new PrimitiveLiftable + given FloatIsLiftable[T <: Float] : Liftable[T] = new PrimitiveLiftable + given DoubleIsLiftable[T <: Double] : Liftable[T] = new PrimitiveLiftable + given CharIsLiftable[T <: Char] : Liftable[T] = new PrimitiveLiftable + given StringIsLiftable[T <: String] : Liftable[T] = new PrimitiveLiftable private class PrimitiveLiftable[T <: Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String] extends Liftable[T] { /** Lift a primitive value `n` into `'{ n }` */