Skip to content

Rework reflect Constant API #10753

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion community-build/community-projects/utest
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ class PickleQuotes extends MacroTransform {
val literalValue =
if lit.const.tag == Constants.NullTag || lit.const.tag == Constants.UnitTag then Nil
else List(body)
val constant = reflect.select("Constant".toTermName).select(typeName.toTermName).select(nme.apply).appliedToArgs(literalValue)
val constant = reflect.select(s"${typeName}Constant".toTermName).select(nme.apply).appliedToArgs(literalValue)
val literal = reflect.select("Literal".toTermName).select(nme.apply).appliedTo(constant)
reflect.select("TreeMethods".toTermName).select("asExpr".toTermName).appliedTo(literal).asInstance(exprType)
}
Expand Down
226 changes: 143 additions & 83 deletions compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2087,100 +2087,160 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler

type Constant = dotc.core.Constants.Constant

object Constant extends ConstantModule:
object Constant extends ConstantModule

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

object Byte extends ByteModule:
def apply(x: Byte): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[Byte] =
if constant.tag == dotc.core.Constants.ByteTag then Some(constant.byteValue)
else None
end Byte
type BooleanConstant = dotc.core.Constants.Constant

object Short extends ShortModule:
def apply(x: Short): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[Short] =
if constant.tag == dotc.core.Constants.ShortTag then Some(constant.shortValue)
else None
end Short
object BooleanConstantTypeTest extends TypeTest[Constant, BooleanConstant]:
def unapply(x: Constant): Option[BooleanConstant & x.type] =
if x.tag == dotc.core.Constants.BooleanTag then Some(x.asInstanceOf[BooleanConstant & x.type]) else None
end BooleanConstantTypeTest

object Int extends IntModule:
def apply(x: Int): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[Int] =
if constant.tag == dotc.core.Constants.IntTag then Some(constant.intValue)
else None
end Int
object BooleanConstant extends BooleanConstantModule:
def apply(x: Boolean): BooleanConstant = dotc.core.Constants.Constant(x)
def unapply(constant: BooleanConstant): Some[Boolean] = Some(constant.booleanValue)
end BooleanConstant

object Long extends LongModule:
def apply(x: Long): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[Long] =
if constant.tag == dotc.core.Constants.LongTag then Some(constant.longValue)
else None
end Long
type ByteConstant = dotc.core.Constants.Constant

object Float extends FloatModule:
def apply(x: Float): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[Float] =
if constant.tag == dotc.core.Constants.FloatTag then Some(constant.floatValue)
else None
end Float
object ByteConstantTypeTest extends TypeTest[Constant, ByteConstant]:
def unapply(x: Constant): Option[ByteConstant & x.type] =
if x.tag == dotc.core.Constants.ByteTag then Some(x.asInstanceOf[ByteConstant & x.type]) else None
end ByteConstantTypeTest

object Double extends DoubleModule:
def apply(x: Double): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[Double] =
if constant.tag == dotc.core.Constants.DoubleTag then Some(constant.doubleValue)
else None
end Double
object ByteConstant extends ByteConstantModule:
def apply(x: Byte): ByteConstant = dotc.core.Constants.Constant(x)
def unapply(constant: ByteConstant): Some[Byte] = Some(constant.byteValue)
end ByteConstant

object Char extends CharModule:
def apply(x: Char): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[Char] =
if constant.tag == dotc.core.Constants.CharTag then Some(constant.charValue)
else None
end Char
type ShortConstant = dotc.core.Constants.Constant

object String extends StringModule:
def apply(x: String): Constant = dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[String] =
if constant.tag == dotc.core.Constants.StringTag then Some(constant.stringValue)
else None
end String

object Unit extends UnitModule:
def apply(): Constant = dotc.core.Constants.Constant(())
def unapply(constant: Constant): Boolean =
constant.tag == dotc.core.Constants.UnitTag
end Unit

object Null extends NullModule:
def apply(): Constant = dotc.core.Constants.Constant(null)
def unapply(constant: Constant): Boolean =
constant.tag == dotc.core.Constants.NullTag
end Null

object ClassOf extends ClassOfModule:
def apply(x: TypeRepr): Constant =
// TODO check that the type is a valid class when creating this constant or let Ycheck do it?
dotc.core.Constants.Constant(x)
def unapply(constant: Constant): Option[TypeRepr] =
if constant.tag == dotc.core.Constants.ClazzTag then Some(constant.typeValue)
else None
end ClassOf
object ShortConstantTypeTest extends TypeTest[Constant, ShortConstant]:
def unapply(x: Constant): Option[ShortConstant & x.type] =
if x.tag == dotc.core.Constants.ShortTag then Some(x.asInstanceOf[ShortConstant & x.type]) else None
end ShortConstantTypeTest

end Constant
object ShortConstant extends ShortConstantModule:
def apply(x: Short): ShortConstant = dotc.core.Constants.Constant(x)
def unapply(constant: ShortConstant): Some[Short] = Some(constant.shortValue)
end ShortConstant

given ConstantMethods: ConstantMethods with
extension (self: Constant)
def value: Any = self.value
def show: String = Extractors.showConstant(using QuotesImpl.this)(self)
end extension
end ConstantMethods
type IntConstant = dotc.core.Constants.Constant

object IntConstantTypeTest extends TypeTest[Constant, IntConstant]:
def unapply(x: Constant): Option[IntConstant & x.type] =
if x.tag == dotc.core.Constants.IntTag then Some(x.asInstanceOf[IntConstant & x.type]) else None
end IntConstantTypeTest

object IntConstant extends IntConstantModule:
def apply(x: Int): IntConstant = dotc.core.Constants.Constant(x)
def unapply(constant: IntConstant): Some[Int] = Some(constant.intValue)
end IntConstant

type LongConstant = dotc.core.Constants.Constant

object LongConstantTypeTest extends TypeTest[Constant, LongConstant]:
def unapply(x: Constant): Option[LongConstant & x.type] =
if x.tag == dotc.core.Constants.LongTag then Some(x.asInstanceOf[LongConstant & x.type]) else None
end LongConstantTypeTest

object LongConstant extends LongConstantModule:
def apply(x: Long): LongConstant = dotc.core.Constants.Constant(x)
def unapply(constant: LongConstant): Some[Long] = Some(constant.longValue)
end LongConstant

type FloatConstant = dotc.core.Constants.Constant

object FloatConstantTypeTest extends TypeTest[Constant, FloatConstant]:
def unapply(x: Constant): Option[FloatConstant & x.type] =
if x.tag == dotc.core.Constants.FloatTag then Some(x.asInstanceOf[FloatConstant & x.type]) else None
end FloatConstantTypeTest

object FloatConstant extends FloatConstantModule:
def apply(x: Float): FloatConstant = dotc.core.Constants.Constant(x)
def unapply(constant: FloatConstant): Some[Float] = Some(constant.floatValue)
end FloatConstant

type DoubleConstant = dotc.core.Constants.Constant

object DoubleConstantTypeTest extends TypeTest[Constant, DoubleConstant]:
def unapply(x: Constant): Option[DoubleConstant & x.type] =
if x.tag == dotc.core.Constants.DoubleTag then Some(x.asInstanceOf[DoubleConstant & x.type]) else None
end DoubleConstantTypeTest

object DoubleConstant extends DoubleConstantModule:
def apply(x: Double): DoubleConstant = dotc.core.Constants.Constant(x)
def unapply(constant: DoubleConstant): Some[Double] = Some(constant.doubleValue)
end DoubleConstant

type CharConstant = dotc.core.Constants.Constant

object CharConstantTypeTest extends TypeTest[Constant, CharConstant]:
def unapply(x: Constant): Option[CharConstant & x.type] =
if x.tag == dotc.core.Constants.CharTag then Some(x.asInstanceOf[CharConstant & x.type]) else None
end CharConstantTypeTest

object CharConstant extends CharConstantModule:
def apply(x: Char): CharConstant = dotc.core.Constants.Constant(x)
def unapply(constant: CharConstant): Some[Char] = Some(constant.charValue)
end CharConstant

type StringConstant = dotc.core.Constants.Constant

object StringConstantTypeTest extends TypeTest[Constant, StringConstant]:
def unapply(x: Constant): Option[StringConstant & x.type] =
if x.tag == dotc.core.Constants.StringTag then Some(x.asInstanceOf[StringConstant & x.type]) else None
end StringConstantTypeTest

object StringConstant extends StringConstantModule:
def apply(x: String): StringConstant = dotc.core.Constants.Constant(x)
def unapply(constant: StringConstant): Some[String] = Some(constant.stringValue)
end StringConstant

type UnitConstant = dotc.core.Constants.Constant

object UnitConstantTypeTest extends TypeTest[Constant, UnitConstant]:
def unapply(x: Constant): Option[UnitConstant & x.type] =
if x.tag == dotc.core.Constants.UnitTag then Some(x.asInstanceOf[UnitConstant & x.type]) else None
end UnitConstantTypeTest

object UnitConstant extends UnitConstantModule:
def apply(): UnitConstant = dotc.core.Constants.Constant(())
def unapply(constant: UnitConstant): true = true
end UnitConstant

type NullConstant = dotc.core.Constants.Constant

object NullConstantTypeTest extends TypeTest[Constant, NullConstant]:
def unapply(x: Constant): Option[NullConstant & x.type] =
if x.tag == dotc.core.Constants.NullTag then Some(x.asInstanceOf[NullConstant & x.type]) else None
end NullConstantTypeTest

object NullConstant extends NullConstantModule:
def apply(): NullConstant = dotc.core.Constants.Constant(null)
def unapply(constant: NullConstant): true = true
end NullConstant

type ClassOfConstant = dotc.core.Constants.Constant

object ClassOfConstantTypeTest extends TypeTest[Constant, ClassOfConstant]:
def unapply(x: Constant): Option[ClassOfConstant & x.type] =
if x.tag == dotc.core.Constants.ClazzTag then Some(x.asInstanceOf[ClassOfConstant & x.type]) else None
end ClassOfConstantTypeTest

object ClassOfConstant extends ClassOfConstantModule:
def apply(x: TypeRepr): ClassOfConstant =
// TODO check that the type is a valid class when creating this constant or let Ycheck do it?
dotc.core.Constants.Constant(x)
def unapply(constant: ClassOfConstant): Some[TypeRepr] = Some(constant.typeValue)
end ClassOfConstant

object Implicits extends ImplicitsModule:
def search(tpe: TypeRepr): ImplicitSearchResult =
Expand Down
26 changes: 13 additions & 13 deletions compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,19 @@ object Extractors {
}

def visitConstant(x: Constant): this.type = x match {
case Constant.Unit() => this += "Constant.Unit()"
case Constant.Null() => this += "Constant.Null()"
case Constant.Boolean(value) => this += "Constant.Boolean(" += value += ")"
case Constant.Byte(value) => this += "Constant.Byte(" += value += ")"
case Constant.Short(value) => this += "Constant.Short(" += value += ")"
case Constant.Int(value) => this += "Constant.Int(" += value += ")"
case Constant.Long(value) => this += "Constant.Long(" += value += "L)"
case Constant.Float(value) => this += "Constant.Float(" += value += "f)"
case Constant.Double(value) => this += "Constant.Double(" += value += "d)"
case Constant.Char(value) => this += "Constant.Char('" += value += "')"
case Constant.String(value) => this += "Constant.String(\"" += value += "\")"
case Constant.ClassOf(value) =>
this += "Constant.ClassOf("
case UnitConstant() => this += "UnitConstant()"
case NullConstant() => this += "NullConstant()"
case BooleanConstant(value) => this += "BooleanConstant(" += value += ")"
case ByteConstant(value) => this += "ByteConstant(" += value += ")"
case ShortConstant(value) => this += "ShortConstant(" += value += ")"
case IntConstant(value) => this += "IntConstant(" += value += ")"
case LongConstant(value) => this += "LongConstant(" += value += "L)"
case FloatConstant(value) => this += "FloatConstant(" += value += "f)"
case DoubleConstant(value) => this += "DoubleConstant(" += value += "d)"
case CharConstant(value) => this += "CharConstant('" += value += "')"
case StringConstant(value) => this += "StringConstant(\"" += value += "\")"
case ClassOfConstant(value) =>
this += "ClassOfConstant("
visitType(value) += ")"
}

Expand Down
28 changes: 14 additions & 14 deletions compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ object SourceCode {

case While(cond, body) =>
(cond, body) match {
case (Block(Block(Nil, body1) :: Nil, Block(Nil, cond1)), Literal(Constant.Unit())) =>
case (Block(Block(Nil, body1) :: Nil, Block(Nil, cond1)), Literal(UnitConstant())) =>
this += highlightKeyword("do ")
printTree(body1) += highlightKeyword(" while ")
inParens(printTree(cond1))
Expand Down Expand Up @@ -562,7 +562,7 @@ object SourceCode {
while (it.hasNext)
extractFlatStats(it.next())
extractFlatStats(expansion)
case Literal(Constant.Unit()) => // ignore
case Literal(UnitConstant()) => // ignore
case stat => flatStats += stat
}
def extractFlatExpr(term: Term): Term = term match {
Expand Down Expand Up @@ -945,18 +945,18 @@ object SourceCode {
inline private val qSc = '"'

def printConstant(const: Constant): this.type = const match {
case Constant.Unit() => this += highlightLiteral("()")
case Constant.Null() => this += highlightLiteral("null")
case Constant.Boolean(v) => this += highlightLiteral(v.toString)
case Constant.Byte(v) => this += highlightLiteral(v.toString)
case Constant.Short(v) => this += highlightLiteral(v.toString)
case Constant.Int(v) => this += highlightLiteral(v.toString)
case Constant.Long(v) => this += highlightLiteral(v.toString + "L")
case Constant.Float(v) => this += highlightLiteral(v.toString + "f")
case Constant.Double(v) => this += highlightLiteral(v.toString)
case Constant.Char(v) => this += highlightString(s"${qc}${escapedChar(v)}${qc}")
case Constant.String(v) => this += highlightString(s"${qSc}${escapedString(v)}${qSc}")
case Constant.ClassOf(v) =>
case UnitConstant() => this += highlightLiteral("()")
case NullConstant() => this += highlightLiteral("null")
case BooleanConstant(v) => this += highlightLiteral(v.toString)
case ByteConstant(v) => this += highlightLiteral(v.toString)
case ShortConstant(v) => this += highlightLiteral(v.toString)
case IntConstant(v) => this += highlightLiteral(v.toString)
case LongConstant(v) => this += highlightLiteral(v.toString + "L")
case FloatConstant(v) => this += highlightLiteral(v.toString + "f")
case DoubleConstant(v) => this += highlightLiteral(v.toString)
case CharConstant(v) => this += highlightString(s"${qc}${escapedChar(v)}${qc}")
case StringConstant(v) => this += highlightString(s"${qSc}${escapedString(v)}${qSc}")
case ClassOfConstant(v) =>
this += "classOf"
inSquare(printType(v))
}
Expand Down
Loading