Skip to content

Commit 83ffe66

Browse files
Merge pull request #9914 from dotty-staging/rework-reflect-constant
Rework Reflect Constant
2 parents be6bcaf + edff735 commit 83ffe66

File tree

31 files changed

+419
-197
lines changed

31 files changed

+419
-197
lines changed

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

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,16 +2061,91 @@ 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+
20742149
end Constant
20752150

20762151
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: 129 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,25 +2317,144 @@ trait Reflection { reflection =>
23172317
/** Constant value represented as the constant itself */
23182318
type Constant <: AnyRef
23192319

2320-
/** Module of Constant literals */
2320+
/** Constant value represented as the constant itself */
23212321
val Constant: ConstantModule
23222322

2323+
/** Constant value represented as the constant itself */
23232324
trait ConstantModule { this: Constant.type =>
23242325

2325-
def apply(x: Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String | Type): Constant
2326+
/** Constant Boolean value */
2327+
val Boolean: ConstantBooleanModule
2328+
2329+
/** Constant Boolean value */
2330+
trait ConstantBooleanModule { this: Boolean.type =>
2331+
/** Create a constant Boolean value */
2332+
def apply(x: Boolean): Constant
2333+
/** Match Boolean value constant and extract its value */
2334+
def unapply(constant: Constant): Option[Boolean]
2335+
}
2336+
2337+
/** Constant Byte value */
2338+
val Byte: ConstantByteModule
2339+
2340+
/** Constant Byte value */
2341+
trait ConstantByteModule { this: Byte.type =>
2342+
/** Create a constant Byte value */
2343+
def apply(x: Byte): Constant
2344+
/** Match Byte value constant and extract its value */
2345+
def unapply(constant: Constant): Option[Byte]
2346+
}
2347+
2348+
/** Constant Short value */
2349+
val Short: ConstantShortModule
2350+
2351+
/** Constant Short value */
2352+
trait ConstantShortModule { this: Short.type =>
2353+
/** Create a constant Short value */
2354+
def apply(x: Short): Constant
2355+
/** Match Short value constant and extract its value */
2356+
def unapply(constant: Constant): Option[Short]
2357+
}
2358+
2359+
/** Constant Int value */
2360+
val Int: ConstantIntModule
2361+
2362+
/** Constant Int value */
2363+
trait ConstantIntModule { this: Int.type =>
2364+
/** Create a constant Int value */
2365+
def apply(x: Int): Constant
2366+
/** Match Int value constant and extract its value */
2367+
def unapply(constant: Constant): Option[Int]
2368+
}
2369+
2370+
/** Constant Long value */
2371+
val Long: ConstantLongModule
2372+
2373+
/** Constant Long value */
2374+
trait ConstantLongModule { this: Long.type =>
2375+
/** Create a constant Long value */
2376+
def apply(x: Long): Constant
2377+
/** Match Long value constant and extract its value */
2378+
def unapply(constant: Constant): Option[Long]
2379+
}
2380+
2381+
/** Constant Float value */
2382+
val Float: ConstantFloatModule
23262383

2327-
def unapply(constant: Constant): Option[Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String | Type]
2384+
/** Constant Float value */
2385+
trait ConstantFloatModule { this: Float.type =>
2386+
/** Create a constant Float value */
2387+
def apply(x: Float): Constant
2388+
/** Match Float value constant and extract its value */
2389+
def unapply(constant: Constant): Option[Float]
2390+
}
2391+
2392+
/** Constant Double value */
2393+
val Double: ConstantDoubleModule
2394+
2395+
/** Constant Double value */
2396+
trait ConstantDoubleModule { this: Double.type =>
2397+
/** Create a constant Double value */
2398+
def apply(x: Double): Constant
2399+
/** Match Double value constant and extract its value */
2400+
def unapply(constant: Constant): Option[Double]
2401+
}
2402+
2403+
/** Constant Char value */
2404+
val Char: ConstantCharModule
23282405

2329-
/** Module of ClassTag literals */
2330-
val ClassTag: ClassTagModule
2406+
/** Constant Char value */
2407+
trait ConstantCharModule { this: Char.type =>
2408+
/** Create a constant Char value */
2409+
def apply(x: Char): Constant
2410+
/** Match Char value constant and extract its value */
2411+
def unapply(constant: Constant): Option[Char]
2412+
}
2413+
2414+
/** Constant String value */
2415+
val String: ConstantStringModule
2416+
2417+
/** Constant String value */
2418+
trait ConstantStringModule { this: String.type =>
2419+
/** Create a constant String value */
2420+
def apply(x: String): Constant
2421+
/** Match String value constant and extract its value */
2422+
def unapply(constant: Constant): Option[String]
2423+
}
23312424

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 */
2425+
/** Constant Unit value */
2426+
val Unit: ConstantUnitModule
2427+
2428+
/** Constant Unit value */
2429+
trait ConstantUnitModule { this: Unit.type =>
2430+
/** Create a constant Unit value */
2431+
def apply(): Constant
2432+
/** Match Unit value constant */
2433+
def unapply(constant: Constant): Boolean
2434+
}
2435+
2436+
/** Constant null value */
2437+
val Null: ConstantNullModule
2438+
2439+
/** Constant null value */
2440+
trait ConstantNullModule { this: Null.type =>
2441+
/** Create a constant null value */
2442+
def apply(): Constant
2443+
/** Match null value constant */
2444+
def unapply(constant: Constant): Boolean
2445+
}
2446+
2447+
/** Constant class value representing a `classOf[T]` */
2448+
val ClassOf: ConstantClassOfModule
2449+
2450+
/** Constant class value representing a `classOf[T]` */
2451+
trait ConstantClassOfModule { this: ClassOf.type =>
2452+
/** Create a constant class value representing `classOf[<tpe>]` */
2453+
def apply(tpe: Type): Constant
2454+
/** Match a class value constant representing `classOf[<tpe>]` and extract its type */
23372455
def unapply(constant: Constant): Option[Type]
23382456
}
2457+
23392458
}
23402459

23412460
given ConstantMethods as ConstantMethods = ConstantMethodsImpl

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,19 +165,19 @@ 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) += ")"
182182
}
183183

0 commit comments

Comments
 (0)