Skip to content

Commit 933ce20

Browse files
committed
Rework Reflect Constant
1 parent be6bcaf commit 933ce20

File tree

26 files changed

+371
-192
lines changed

26 files changed

+371
-192
lines changed

compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala

Lines changed: 91 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,16 +2061,100 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext:
20612061
type Constant = dotc.core.Constants.Constant
20622062

20632063
object Constant extends ConstantModule:
2064-
def apply(x: Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String | Type): Constant =
2065-
dotc.core.Constants.Constant(x)
2066-
def unapply(constant: Constant): Option[Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String | Type] =
2067-
Some(constant.value.asInstanceOf[Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String | Type])
2068-
object ClassTag extends ClassTagModule:
2069-
def apply[T](using x: Type): Constant = dotc.core.Constants.Constant(x)
2064+
2065+
object Boolean extends ConstantBooleanModule:
2066+
def apply(x: Boolean): Constant = dotc.core.Constants.Constant(x)
2067+
def unapply(constant: Constant): Option[Boolean] =
2068+
if constant.tag == dotc.core.Constants.BooleanTag then Some(constant.booleanValue)
2069+
else None
2070+
end Boolean
2071+
2072+
object Byte extends ConstantByteModule:
2073+
def apply(x: Byte): Constant = dotc.core.Constants.Constant(x)
2074+
def unapply(constant: Constant): Option[Byte] =
2075+
if constant.tag == dotc.core.Constants.ByteTag then Some(constant.byteValue)
2076+
else None
2077+
end Byte
2078+
2079+
object Short extends ConstantShortModule:
2080+
def apply(x: Short): Constant = dotc.core.Constants.Constant(x)
2081+
def unapply(constant: Constant): Option[Short] =
2082+
if constant.tag == dotc.core.Constants.ShortTag then Some(constant.shortValue)
2083+
else None
2084+
end Short
2085+
2086+
object Int extends ConstantIntModule:
2087+
def apply(x: Int): Constant = dotc.core.Constants.Constant(x)
2088+
def unapply(constant: Constant): Option[Int] =
2089+
if constant.tag == dotc.core.Constants.IntTag then Some(constant.intValue)
2090+
else None
2091+
end Int
2092+
2093+
object Long extends ConstantLongModule:
2094+
def apply(x: Long): Constant = dotc.core.Constants.Constant(x)
2095+
def unapply(constant: Constant): Option[Long] =
2096+
if constant.tag == dotc.core.Constants.LongTag then Some(constant.longValue)
2097+
else None
2098+
end Long
2099+
2100+
object Float extends ConstantFloatModule:
2101+
def apply(x: Float): Constant = dotc.core.Constants.Constant(x)
2102+
def unapply(constant: Constant): Option[Float] =
2103+
if constant.tag == dotc.core.Constants.FloatTag then Some(constant.floatValue)
2104+
else None
2105+
end Float
2106+
2107+
object Double extends ConstantDoubleModule:
2108+
def apply(x: Double): Constant = dotc.core.Constants.Constant(x)
2109+
def unapply(constant: Constant): Option[Double] =
2110+
if constant.tag == dotc.core.Constants.DoubleTag then Some(constant.doubleValue)
2111+
else None
2112+
end Double
2113+
2114+
object Char extends ConstantCharModule:
2115+
def apply(x: Char): Constant = dotc.core.Constants.Constant(x)
2116+
def unapply(constant: Constant): Option[Char] =
2117+
if constant.tag == dotc.core.Constants.CharTag then Some(constant.charValue)
2118+
else None
2119+
end Char
2120+
2121+
object String extends ConstantStringModule:
2122+
def apply(x: String): Constant = dotc.core.Constants.Constant(x)
2123+
def unapply(constant: Constant): Option[String] =
2124+
if constant.tag == dotc.core.Constants.StringTag then Some(constant.stringValue)
2125+
else None
2126+
end String
2127+
2128+
object Unit extends ConstantUnitModule:
2129+
def apply(): Constant = dotc.core.Constants.Constant(())
2130+
def unapply(constant: Constant): Boolean =
2131+
constant.tag == dotc.core.Constants.UnitTag
2132+
end Unit
2133+
2134+
object Null extends ConstantNullModule:
2135+
def apply(): Constant = dotc.core.Constants.Constant(null)
2136+
def unapply(constant: Constant): Boolean =
2137+
constant.tag == dotc.core.Constants.NullTag
2138+
end Null
2139+
2140+
object ClassOf extends ConstantClassOfModule:
2141+
def apply(x: Type): Constant =
2142+
// TODO check that the type is a valid class when creating this constant or let Ycheck do it?
2143+
dotc.core.Constants.Constant(x)
20702144
def unapply(constant: Constant): Option[Type] =
20712145
if constant.tag == dotc.core.Constants.ClazzTag then Some(constant.typeValue)
20722146
else None
2073-
end ClassTag
2147+
end ClassOf
2148+
2149+
object Enum extends ConstantEnumModule:
2150+
def apply(x: Symbol): Constant =
2151+
// TODO check that the type is a valid enum when creating this constant or let Ycheck do it?
2152+
dotc.core.Constants.Constant(x)
2153+
def unapply(constant: Constant): Option[Symbol] =
2154+
if constant.tag == dotc.core.Constants.EnumTag then Some(constant.symbolValue)
2155+
else None
2156+
end Enum
2157+
20742158
end Constant
20752159

20762160
object ConstantMethodsImpl extends ConstantMethods:

library/src-bootstrapped/scala/internal/quoted/Expr.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ object Expr {
6060
/** Returns a null expresssion equivalent to `'{null}` */
6161
def `null`: QuoteContext ?=> quoted.Expr[Null] = qctx ?=> {
6262
import qctx.tasty._
63-
Literal(Constant(null)).seal.asInstanceOf[quoted.Expr[Null]]
63+
Literal(Constant.Null()).seal.asInstanceOf[quoted.Expr[Null]]
6464
}
6565

6666
/** Returns a unit expresssion equivalent to `'{}` or `'{()}` */
6767
def Unit: QuoteContext ?=> quoted.Expr[Unit] = qctx ?=> {
6868
import qctx.tasty._
69-
Literal(Constant(())).seal.asInstanceOf[quoted.Expr[Unit]]
69+
Literal(Constant.Unit()).seal.asInstanceOf[quoted.Expr[Unit]]
7070
}
7171

7272
}

library/src-bootstrapped/scala/quoted/Liftable.scala

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,38 +22,66 @@ object Liftable {
2222
// IMPORTANT Keep in sync with tests/run-staging/liftables.scala
2323

2424
/** Default liftable for Boolean */
25-
given BooleanLiftable[T <: Boolean] as Liftable[T] = new PrimitiveLiftable
25+
given BooleanLiftable[T <: Boolean] as Liftable[T] {
26+
def toExpr(x: T) =
27+
import qctx.tasty._
28+
Literal(Constant.Boolean(x)).seal.asInstanceOf[Expr[T]]
29+
}
2630

2731
/** Default liftable for Byte */
28-
given ByteLiftable[T <: Byte] as Liftable[T] = new PrimitiveLiftable
32+
given ByteLiftable[T <: Byte] as Liftable[T] {
33+
def toExpr(x: T) =
34+
import qctx.tasty._
35+
Literal(Constant.Byte(x)).seal.asInstanceOf[Expr[T]]
36+
}
2937

3038
/** Default liftable for Short */
31-
given ShortLiftable[T <: Short] as Liftable[T] = new PrimitiveLiftable
39+
given ShortLiftable[T <: Short] as Liftable[T] {
40+
def toExpr(x: T) =
41+
import qctx.tasty._
42+
Literal(Constant.Short(x)).seal.asInstanceOf[Expr[T]]
43+
}
3244

3345
/** Default liftable for Int */
34-
given IntLiftable[T <: Int] as Liftable[T] = new PrimitiveLiftable
46+
given IntLiftable[T <: Int] as Liftable[T] {
47+
def toExpr(x: T) =
48+
import qctx.tasty._
49+
Literal(Constant.Int(x)).seal.asInstanceOf[Expr[T]]
50+
}
3551

3652
/** Default liftable for Long */
37-
given LongLiftable[T <: Long] as Liftable[T] = new PrimitiveLiftable
53+
given LongLiftable[T <: Long] as Liftable[T] {
54+
def toExpr(x: T) =
55+
import qctx.tasty._
56+
Literal(Constant.Long(x)).seal.asInstanceOf[Expr[T]]
57+
}
3858

3959
/** Default liftable for Float */
40-
given FloatLiftable[T <: Float] as Liftable[T] = new PrimitiveLiftable
60+
given FloatLiftable[T <: Float] as Liftable[T] {
61+
def toExpr(x: T) =
62+
import qctx.tasty._
63+
Literal(Constant.Float(x)).seal.asInstanceOf[Expr[T]]
64+
}
4165

4266
/** Default liftable for Double */
43-
given DoubleLiftable[T <: Double] as Liftable[T] = new PrimitiveLiftable
67+
given DoubleLiftable[T <: Double] as Liftable[T] {
68+
def toExpr(x: T) =
69+
import qctx.tasty._
70+
Literal(Constant.Double(x)).seal.asInstanceOf[Expr[T]]
71+
}
4472

4573
/** Default liftable for Char */
46-
given CharLiftable[T <: Char] as Liftable[T] = new PrimitiveLiftable
74+
given CharLiftable[T <: Char] as Liftable[T] {
75+
def toExpr(x: T) =
76+
import qctx.tasty._
77+
Literal(Constant.Char(x)).seal.asInstanceOf[Expr[T]]
78+
}
4779

4880
/** Default liftable for String */
49-
given StringLiftable[T <: String] as Liftable[T] = new PrimitiveLiftable
50-
51-
/** Lift a literal constant value */
52-
private class PrimitiveLiftable[T <: Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String] extends Liftable[T] {
53-
def toExpr(x: T) = qctx ?=> {
81+
given StringLiftable[T <: String] as Liftable[T] {
82+
def toExpr(x: T) =
5483
import qctx.tasty._
55-
Literal(Constant(x)).seal.asInstanceOf[Expr[T]]
56-
}
84+
Literal(Constant.String(x)).seal.asInstanceOf[Expr[T]]
5785
}
5886

5987
/** Default liftable for Class[T] */

library/src/scala/tasty/Reflection.scala

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,25 +2317,87 @@ trait Reflection { reflection =>
23172317
/** Constant value represented as the constant itself */
23182318
type Constant <: AnyRef
23192319

2320-
/** Module of Constant literals */
23212320
val Constant: ConstantModule
23222321

23232322
trait ConstantModule { this: Constant.type =>
23242323

2325-
def apply(x: Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String | Type): Constant
2324+
val Boolean: ConstantBooleanModule
2325+
trait ConstantBooleanModule { this: Boolean.type =>
2326+
def apply(x: Boolean): Constant
2327+
def unapply(constant: Constant): Option[Boolean]
2328+
}
2329+
2330+
val Byte: ConstantByteModule
2331+
trait ConstantByteModule { this: Byte.type =>
2332+
def apply(x: Byte): Constant
2333+
def unapply(constant: Constant): Option[Byte]
2334+
}
23262335

2327-
def unapply(constant: Constant): Option[Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String | Type]
2336+
val Short: ConstantShortModule
2337+
trait ConstantShortModule { this: Short.type =>
2338+
def apply(x: Short): Constant
2339+
def unapply(constant: Constant): Option[Short]
2340+
}
2341+
2342+
val Int: ConstantIntModule
2343+
trait ConstantIntModule { this: Int.type =>
2344+
def apply(x: Int): Constant
2345+
def unapply(constant: Constant): Option[Int]
2346+
}
23282347

2329-
/** Module of ClassTag literals */
2330-
val ClassTag: ClassTagModule
2348+
val Long: ConstantLongModule
2349+
trait ConstantLongModule { this: Long.type =>
2350+
def apply(x: Long): Constant
2351+
def unapply(constant: Constant): Option[Long]
2352+
}
2353+
2354+
val Float: ConstantFloatModule
2355+
trait ConstantFloatModule { this: Float.type =>
2356+
def apply(x: Float): Constant
2357+
def unapply(constant: Constant): Option[Float]
2358+
}
2359+
2360+
val Double: ConstantDoubleModule
2361+
trait ConstantDoubleModule { this: Double.type =>
2362+
def apply(x: Double): Constant
2363+
def unapply(constant: Constant): Option[Double]
2364+
}
23312365

2332-
/** Module of ClassTag literals */
2333-
trait ClassTagModule { this: ClassTag.type =>
2334-
/** scala.reflect.ClassTag literal */
2335-
def apply[T](using x: Type): Constant
2336-
/** Extractor for ClassTag literals */
2366+
val Char: ConstantCharModule
2367+
trait ConstantCharModule { this: Char.type =>
2368+
def apply(x: Char): Constant
2369+
def unapply(constant: Constant): Option[Char]
2370+
}
2371+
2372+
val String: ConstantStringModule
2373+
trait ConstantStringModule { this: String.type =>
2374+
def apply(x: String): Constant
2375+
def unapply(constant: Constant): Option[String]
2376+
}
2377+
2378+
val Unit: ConstantUnitModule
2379+
trait ConstantUnitModule { this: Unit.type =>
2380+
def apply(): Constant
2381+
def unapply(constant: Constant): Boolean
2382+
}
2383+
2384+
val Null: ConstantNullModule
2385+
trait ConstantNullModule { this: Null.type =>
2386+
def apply(): Constant
2387+
def unapply(constant: Constant): Boolean
2388+
}
2389+
2390+
val ClassOf: ConstantClassOfModule
2391+
trait ConstantClassOfModule { this: ClassOf.type =>
2392+
def apply(x: Type): Constant
23372393
def unapply(constant: Constant): Option[Type]
23382394
}
2395+
2396+
val Enum: ConstantEnumModule
2397+
trait ConstantEnumModule { this: Enum.type =>
2398+
def apply(x: Symbol): Constant
2399+
def unapply(constant: Constant): Option[Symbol]
2400+
}
23392401
}
23402402

23412403
given ConstantMethods as ConstantMethods = ConstantMethodsImpl

library/src/scala/tasty/reflect/ExtractorsPrinter.scala

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,23 @@ class ExtractorsPrinter[R <: Reflection & Singleton](val tasty: R) extends Print
165165
}
166166

167167
def visitConstant(x: Constant): Buffer = x match {
168-
case Constant(()) => this += "Constant(())"
169-
case Constant(null) => this += "Constant(null)"
170-
case Constant(value: Boolean) => this += "Constant(" += value += ")"
171-
case Constant(value: Byte) => this += "Constant(" += value += ": Byte)"
172-
case Constant(value: Short) => this += "Constant(" += value += ": Short)"
173-
case Constant(value: Char) => this += "Constant('" += value += "')"
174-
case Constant(value: Int) => this += "Constant(" += value.toString += ")"
175-
case Constant(value: Long) => this += "Constant(" += value += "L)"
176-
case Constant(value: Float) => this += "Constant(" += value += "f)"
177-
case Constant(value: Double) => this += "Constant(" += value += "d)"
178-
case Constant(value: String) => this += "Constant(\"" += value += "\")"
179-
case Constant.ClassTag(value) =>
180-
this += "Constant.ClassTag("
168+
case Constant.Unit() => this += "Constant.Unit()"
169+
case Constant.Null() => this += "Constant.Null()"
170+
case Constant.Boolean(value) => this += "Constant.Boolean(" += value += ")"
171+
case Constant.Byte(value) => this += "Constant.Byte(" += value += ")"
172+
case Constant.Short(value) => this += "Constant.Short(" += value += ")"
173+
case Constant.Int(value) => this += "Constant.Int(" += value += ")"
174+
case Constant.Long(value) => this += "Constant.Long(" += value += "L)"
175+
case Constant.Float(value) => this += "Constant.Float(" += value += "f)"
176+
case Constant.Double(value) => this += "Constant.Double(" += value += "d)"
177+
case Constant.Char(value) => this += "Constant.Char('" += value += "')"
178+
case Constant.String(value) => this += "Constant.String(\"" += value += "\")"
179+
case Constant.ClassOf(value) =>
180+
this += "Constant.ClassOf("
181181
visitType(value) += ")"
182+
case Constant.Enum(value) =>
183+
this += "Constant.Enum(\""
184+
visitSymbol(value) += "\")"
182185
}
183186

184187
def visitType(x: Type): Buffer = x match {

0 commit comments

Comments
 (0)