Skip to content

Commit 13b9679

Browse files
committed
Rework reflect Constant API
Add types for specific constants as in the tasty format specification. This also aligns the API design with the rest of reflection by useing `TypeTest`s. ```diff - Constant.Int(x) + IntConstant(x) - Constant.Long(x) + LongConstant(x) ... ```
1 parent a34130f commit 13b9679

File tree

35 files changed

+519
-389
lines changed

35 files changed

+519
-389
lines changed

compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class PickleQuotes extends MacroTransform {
166166
val literalValue =
167167
if lit.const.tag == Constants.NullTag || lit.const.tag == Constants.UnitTag then Nil
168168
else List(body)
169-
val constant = reflect.select("Constant".toTermName).select(typeName.toTermName).select(nme.apply).appliedToArgs(literalValue)
169+
val constant = reflect.select(s"${typeName}Constant".toTermName).select(nme.apply).appliedToArgs(literalValue)
170170
val literal = reflect.select("Literal".toTermName).select(nme.apply).appliedTo(constant)
171171
reflect.select("TreeMethods".toTermName).select("asExpr".toTermName).appliedTo(literal).asInstance(exprType)
172172
}

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 143 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,100 +2087,160 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
20872087

20882088
type Constant = dotc.core.Constants.Constant
20892089

2090-
object Constant extends ConstantModule:
2090+
object Constant extends ConstantModule
20912091

2092-
object Boolean extends BooleanModule:
2093-
def apply(x: Boolean): Constant = dotc.core.Constants.Constant(x)
2094-
def unapply(constant: Constant): Option[Boolean] =
2095-
if constant.tag == dotc.core.Constants.BooleanTag then Some(constant.booleanValue)
2096-
else None
2097-
end Boolean
2092+
given ConstantMethods: ConstantMethods with
2093+
extension (self: Constant)
2094+
def value: Any = self.value
2095+
def show: String = Extractors.showConstant(using QuotesImpl.this)(self)
2096+
end extension
2097+
end ConstantMethods
20982098

2099-
object Byte extends ByteModule:
2100-
def apply(x: Byte): Constant = dotc.core.Constants.Constant(x)
2101-
def unapply(constant: Constant): Option[Byte] =
2102-
if constant.tag == dotc.core.Constants.ByteTag then Some(constant.byteValue)
2103-
else None
2104-
end Byte
2099+
type BooleanConstant = dotc.core.Constants.Constant
21052100

2106-
object Short extends ShortModule:
2107-
def apply(x: Short): Constant = dotc.core.Constants.Constant(x)
2108-
def unapply(constant: Constant): Option[Short] =
2109-
if constant.tag == dotc.core.Constants.ShortTag then Some(constant.shortValue)
2110-
else None
2111-
end Short
2101+
object BooleanConstantTypeTest extends TypeTest[Constant, BooleanConstant]:
2102+
def unapply(x: Constant): Option[BooleanConstant & x.type] =
2103+
if x.tag == dotc.core.Constants.BooleanTag then Some(x.asInstanceOf[BooleanConstant & x.type]) else None
2104+
end BooleanConstantTypeTest
21122105

2113-
object Int extends IntModule:
2114-
def apply(x: Int): Constant = dotc.core.Constants.Constant(x)
2115-
def unapply(constant: Constant): Option[Int] =
2116-
if constant.tag == dotc.core.Constants.IntTag then Some(constant.intValue)
2117-
else None
2118-
end Int
2106+
object BooleanConstant extends BooleanConstantModule:
2107+
def apply(x: Boolean): BooleanConstant = dotc.core.Constants.Constant(x)
2108+
def unapply(constant: BooleanConstant): Some[Boolean] = Some(constant.booleanValue)
2109+
end BooleanConstant
21192110

2120-
object Long extends LongModule:
2121-
def apply(x: Long): Constant = dotc.core.Constants.Constant(x)
2122-
def unapply(constant: Constant): Option[Long] =
2123-
if constant.tag == dotc.core.Constants.LongTag then Some(constant.longValue)
2124-
else None
2125-
end Long
2111+
type ByteConstant = dotc.core.Constants.Constant
21262112

2127-
object Float extends FloatModule:
2128-
def apply(x: Float): Constant = dotc.core.Constants.Constant(x)
2129-
def unapply(constant: Constant): Option[Float] =
2130-
if constant.tag == dotc.core.Constants.FloatTag then Some(constant.floatValue)
2131-
else None
2132-
end Float
2113+
object ByteConstantTypeTest extends TypeTest[Constant, ByteConstant]:
2114+
def unapply(x: Constant): Option[ByteConstant & x.type] =
2115+
if x.tag == dotc.core.Constants.ByteTag then Some(x.asInstanceOf[ByteConstant & x.type]) else None
2116+
end ByteConstantTypeTest
21332117

2134-
object Double extends DoubleModule:
2135-
def apply(x: Double): Constant = dotc.core.Constants.Constant(x)
2136-
def unapply(constant: Constant): Option[Double] =
2137-
if constant.tag == dotc.core.Constants.DoubleTag then Some(constant.doubleValue)
2138-
else None
2139-
end Double
2118+
object ByteConstant extends ByteConstantModule:
2119+
def apply(x: Byte): ByteConstant = dotc.core.Constants.Constant(x)
2120+
def unapply(constant: ByteConstant): Some[Byte] = Some(constant.byteValue)
2121+
end ByteConstant
21402122

2141-
object Char extends CharModule:
2142-
def apply(x: Char): Constant = dotc.core.Constants.Constant(x)
2143-
def unapply(constant: Constant): Option[Char] =
2144-
if constant.tag == dotc.core.Constants.CharTag then Some(constant.charValue)
2145-
else None
2146-
end Char
2123+
type ShortConstant = dotc.core.Constants.Constant
21472124

2148-
object String extends StringModule:
2149-
def apply(x: String): Constant = dotc.core.Constants.Constant(x)
2150-
def unapply(constant: Constant): Option[String] =
2151-
if constant.tag == dotc.core.Constants.StringTag then Some(constant.stringValue)
2152-
else None
2153-
end String
2154-
2155-
object Unit extends UnitModule:
2156-
def apply(): Constant = dotc.core.Constants.Constant(())
2157-
def unapply(constant: Constant): Boolean =
2158-
constant.tag == dotc.core.Constants.UnitTag
2159-
end Unit
2160-
2161-
object Null extends NullModule:
2162-
def apply(): Constant = dotc.core.Constants.Constant(null)
2163-
def unapply(constant: Constant): Boolean =
2164-
constant.tag == dotc.core.Constants.NullTag
2165-
end Null
2166-
2167-
object ClassOf extends ClassOfModule:
2168-
def apply(x: TypeRepr): Constant =
2169-
// TODO check that the type is a valid class when creating this constant or let Ycheck do it?
2170-
dotc.core.Constants.Constant(x)
2171-
def unapply(constant: Constant): Option[TypeRepr] =
2172-
if constant.tag == dotc.core.Constants.ClazzTag then Some(constant.typeValue)
2173-
else None
2174-
end ClassOf
2125+
object ShortConstantTypeTest extends TypeTest[Constant, ShortConstant]:
2126+
def unapply(x: Constant): Option[ShortConstant & x.type] =
2127+
if x.tag == dotc.core.Constants.ShortTag then Some(x.asInstanceOf[ShortConstant & x.type]) else None
2128+
end ShortConstantTypeTest
21752129

2176-
end Constant
2130+
object ShortConstant extends ShortConstantModule:
2131+
def apply(x: Short): ShortConstant = dotc.core.Constants.Constant(x)
2132+
def unapply(constant: ShortConstant): Some[Short] = Some(constant.shortValue)
2133+
end ShortConstant
21772134

2178-
given ConstantMethods: ConstantMethods with
2179-
extension (self: Constant)
2180-
def value: Any = self.value
2181-
def show: String = Extractors.showConstant(using QuotesImpl.this)(self)
2182-
end extension
2183-
end ConstantMethods
2135+
type IntConstant = dotc.core.Constants.Constant
2136+
2137+
object IntConstantTypeTest extends TypeTest[Constant, IntConstant]:
2138+
def unapply(x: Constant): Option[IntConstant & x.type] =
2139+
if x.tag == dotc.core.Constants.IntTag then Some(x.asInstanceOf[IntConstant & x.type]) else None
2140+
end IntConstantTypeTest
2141+
2142+
object IntConstant extends IntConstantModule:
2143+
def apply(x: Int): IntConstant = dotc.core.Constants.Constant(x)
2144+
def unapply(constant: IntConstant): Some[Int] = Some(constant.intValue)
2145+
end IntConstant
2146+
2147+
type LongConstant = dotc.core.Constants.Constant
2148+
2149+
object LongConstantTypeTest extends TypeTest[Constant, LongConstant]:
2150+
def unapply(x: Constant): Option[LongConstant & x.type] =
2151+
if x.tag == dotc.core.Constants.LongTag then Some(x.asInstanceOf[LongConstant & x.type]) else None
2152+
end LongConstantTypeTest
2153+
2154+
object LongConstant extends LongConstantModule:
2155+
def apply(x: Long): LongConstant = dotc.core.Constants.Constant(x)
2156+
def unapply(constant: LongConstant): Some[Long] = Some(constant.longValue)
2157+
end LongConstant
2158+
2159+
type FloatConstant = dotc.core.Constants.Constant
2160+
2161+
object FloatConstantTypeTest extends TypeTest[Constant, FloatConstant]:
2162+
def unapply(x: Constant): Option[FloatConstant & x.type] =
2163+
if x.tag == dotc.core.Constants.FloatTag then Some(x.asInstanceOf[FloatConstant & x.type]) else None
2164+
end FloatConstantTypeTest
2165+
2166+
object FloatConstant extends FloatConstantModule:
2167+
def apply(x: Float): FloatConstant = dotc.core.Constants.Constant(x)
2168+
def unapply(constant: FloatConstant): Some[Float] = Some(constant.floatValue)
2169+
end FloatConstant
2170+
2171+
type DoubleConstant = dotc.core.Constants.Constant
2172+
2173+
object DoubleConstantTypeTest extends TypeTest[Constant, DoubleConstant]:
2174+
def unapply(x: Constant): Option[DoubleConstant & x.type] =
2175+
if x.tag == dotc.core.Constants.DoubleTag then Some(x.asInstanceOf[DoubleConstant & x.type]) else None
2176+
end DoubleConstantTypeTest
2177+
2178+
object DoubleConstant extends DoubleConstantModule:
2179+
def apply(x: Double): DoubleConstant = dotc.core.Constants.Constant(x)
2180+
def unapply(constant: DoubleConstant): Some[Double] = Some(constant.doubleValue)
2181+
end DoubleConstant
2182+
2183+
type CharConstant = dotc.core.Constants.Constant
2184+
2185+
object CharConstantTypeTest extends TypeTest[Constant, CharConstant]:
2186+
def unapply(x: Constant): Option[CharConstant & x.type] =
2187+
if x.tag == dotc.core.Constants.CharTag then Some(x.asInstanceOf[CharConstant & x.type]) else None
2188+
end CharConstantTypeTest
2189+
2190+
object CharConstant extends CharConstantModule:
2191+
def apply(x: Char): CharConstant = dotc.core.Constants.Constant(x)
2192+
def unapply(constant: CharConstant): Some[Char] = Some(constant.charValue)
2193+
end CharConstant
2194+
2195+
type StringConstant = dotc.core.Constants.Constant
2196+
2197+
object StringConstantTypeTest extends TypeTest[Constant, StringConstant]:
2198+
def unapply(x: Constant): Option[StringConstant & x.type] =
2199+
if x.tag == dotc.core.Constants.StringTag then Some(x.asInstanceOf[StringConstant & x.type]) else None
2200+
end StringConstantTypeTest
2201+
2202+
object StringConstant extends StringConstantModule:
2203+
def apply(x: String): StringConstant = dotc.core.Constants.Constant(x)
2204+
def unapply(constant: StringConstant): Some[String] = Some(constant.stringValue)
2205+
end StringConstant
2206+
2207+
type UnitConstant = dotc.core.Constants.Constant
2208+
2209+
object UnitConstantTypeTest extends TypeTest[Constant, UnitConstant]:
2210+
def unapply(x: Constant): Option[UnitConstant & x.type] =
2211+
if x.tag == dotc.core.Constants.UnitTag then Some(x.asInstanceOf[UnitConstant & x.type]) else None
2212+
end UnitConstantTypeTest
2213+
2214+
object UnitConstant extends UnitConstantModule:
2215+
def apply(): UnitConstant = dotc.core.Constants.Constant(())
2216+
def unapply(constant: UnitConstant): true = true
2217+
end UnitConstant
2218+
2219+
type NullConstant = dotc.core.Constants.Constant
2220+
2221+
object NullConstantTypeTest extends TypeTest[Constant, NullConstant]:
2222+
def unapply(x: Constant): Option[NullConstant & x.type] =
2223+
if x.tag == dotc.core.Constants.NullTag then Some(x.asInstanceOf[NullConstant & x.type]) else None
2224+
end NullConstantTypeTest
2225+
2226+
object NullConstant extends NullConstantModule:
2227+
def apply(): NullConstant = dotc.core.Constants.Constant(null)
2228+
def unapply(constant: NullConstant): true = true
2229+
end NullConstant
2230+
2231+
type ClassOfConstant = dotc.core.Constants.Constant
2232+
2233+
object ClassOfConstantTypeTest extends TypeTest[Constant, ClassOfConstant]:
2234+
def unapply(x: Constant): Option[ClassOfConstant & x.type] =
2235+
if x.tag == dotc.core.Constants.ClazzTag then Some(x.asInstanceOf[ClassOfConstant & x.type]) else None
2236+
end ClassOfConstantTypeTest
2237+
2238+
object ClassOfConstant extends ClassOfConstantModule:
2239+
def apply(x: TypeRepr): ClassOfConstant =
2240+
// TODO check that the type is a valid class when creating this constant or let Ycheck do it?
2241+
dotc.core.Constants.Constant(x)
2242+
def unapply(constant: ClassOfConstant): Some[TypeRepr] = Some(constant.typeValue)
2243+
end ClassOfConstant
21842244

21852245
object Implicits extends ImplicitsModule:
21862246
def search(tpe: TypeRepr): ImplicitSearchResult =

compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,19 @@ object Extractors {
176176
}
177177

178178
def visitConstant(x: Constant): this.type = x match {
179-
case Constant.Unit() => this += "Constant.Unit()"
180-
case Constant.Null() => this += "Constant.Null()"
181-
case Constant.Boolean(value) => this += "Constant.Boolean(" += value += ")"
182-
case Constant.Byte(value) => this += "Constant.Byte(" += value += ")"
183-
case Constant.Short(value) => this += "Constant.Short(" += value += ")"
184-
case Constant.Int(value) => this += "Constant.Int(" += value += ")"
185-
case Constant.Long(value) => this += "Constant.Long(" += value += "L)"
186-
case Constant.Float(value) => this += "Constant.Float(" += value += "f)"
187-
case Constant.Double(value) => this += "Constant.Double(" += value += "d)"
188-
case Constant.Char(value) => this += "Constant.Char('" += value += "')"
189-
case Constant.String(value) => this += "Constant.String(\"" += value += "\")"
190-
case Constant.ClassOf(value) =>
191-
this += "Constant.ClassOf("
179+
case UnitConstant() => this += "UnitConstant()"
180+
case NullConstant() => this += "NullConstant()"
181+
case BooleanConstant(value) => this += "BooleanConstant(" += value += ")"
182+
case ByteConstant(value) => this += "ByteConstant(" += value += ")"
183+
case ShortConstant(value) => this += "ShortConstant(" += value += ")"
184+
case IntConstant(value) => this += "IntConstant(" += value += ")"
185+
case LongConstant(value) => this += "LongConstant(" += value += "L)"
186+
case FloatConstant(value) => this += "FloatConstant(" += value += "f)"
187+
case DoubleConstant(value) => this += "DoubleConstant(" += value += "d)"
188+
case CharConstant(value) => this += "CharConstant('" += value += "')"
189+
case StringConstant(value) => this += "StringConstant(\"" += value += "\")"
190+
case ClassOfConstant(value) =>
191+
this += "ClassOfConstant("
192192
visitType(value) += ")"
193193
}
194194

compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ object SourceCode {
291291

292292
case While(cond, body) =>
293293
(cond, body) match {
294-
case (Block(Block(Nil, body1) :: Nil, Block(Nil, cond1)), Literal(Constant.Unit())) =>
294+
case (Block(Block(Nil, body1) :: Nil, Block(Nil, cond1)), Literal(UnitConstant())) =>
295295
this += highlightKeyword("do ")
296296
printTree(body1) += highlightKeyword(" while ")
297297
inParens(printTree(cond1))
@@ -562,7 +562,7 @@ object SourceCode {
562562
while (it.hasNext)
563563
extractFlatStats(it.next())
564564
extractFlatStats(expansion)
565-
case Literal(Constant.Unit()) => // ignore
565+
case Literal(UnitConstant()) => // ignore
566566
case stat => flatStats += stat
567567
}
568568
def extractFlatExpr(term: Term): Term = term match {
@@ -945,18 +945,18 @@ object SourceCode {
945945
inline private val qSc = '"'
946946

947947
def printConstant(const: Constant): this.type = const match {
948-
case Constant.Unit() => this += highlightLiteral("()")
949-
case Constant.Null() => this += highlightLiteral("null")
950-
case Constant.Boolean(v) => this += highlightLiteral(v.toString)
951-
case Constant.Byte(v) => this += highlightLiteral(v.toString)
952-
case Constant.Short(v) => this += highlightLiteral(v.toString)
953-
case Constant.Int(v) => this += highlightLiteral(v.toString)
954-
case Constant.Long(v) => this += highlightLiteral(v.toString + "L")
955-
case Constant.Float(v) => this += highlightLiteral(v.toString + "f")
956-
case Constant.Double(v) => this += highlightLiteral(v.toString)
957-
case Constant.Char(v) => this += highlightString(s"${qc}${escapedChar(v)}${qc}")
958-
case Constant.String(v) => this += highlightString(s"${qSc}${escapedString(v)}${qSc}")
959-
case Constant.ClassOf(v) =>
948+
case UnitConstant() => this += highlightLiteral("()")
949+
case NullConstant() => this += highlightLiteral("null")
950+
case BooleanConstant(v) => this += highlightLiteral(v.toString)
951+
case ByteConstant(v) => this += highlightLiteral(v.toString)
952+
case ShortConstant(v) => this += highlightLiteral(v.toString)
953+
case IntConstant(v) => this += highlightLiteral(v.toString)
954+
case LongConstant(v) => this += highlightLiteral(v.toString + "L")
955+
case FloatConstant(v) => this += highlightLiteral(v.toString + "f")
956+
case DoubleConstant(v) => this += highlightLiteral(v.toString)
957+
case CharConstant(v) => this += highlightString(s"${qc}${escapedChar(v)}${qc}")
958+
case StringConstant(v) => this += highlightString(s"${qSc}${escapedString(v)}${qSc}")
959+
case ClassOfConstant(v) =>
960960
this += "classOf"
961961
inSquare(printType(v))
962962
}

0 commit comments

Comments
 (0)