diff --git a/compiler/src/scala/quoted/compiletime/internal/ConstantImpl.scala b/compiler/src/scala/quoted/compiletime/internal/ConstantImpl.scala new file mode 100644 index 000000000000..6b285f9462f5 --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/ConstantImpl.scala @@ -0,0 +1,184 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import scala.quoted.compiletime as pub + +/////// Constant /////////////////////////////////////////////////////////////// + +type Constant = pub.Constant & ConstantImpl +sealed trait ConstantImpl { _self: pub.Constant => } +object ConstantImpl { + def apply(c: dotc.core.Constants.Constant): ConstantImpl = c.tag match { + case dotc.core.Constants.BooleanTag => BooleanConstantImpl(c.booleanValue) + case dotc.core.Constants.ByteTag => ByteConstantImpl(c.byteValue) + case dotc.core.Constants.ShortTag => ShortConstantImpl(c.shortValue) + case dotc.core.Constants.IntTag => IntConstantImpl(c.intValue) + case dotc.core.Constants.LongTag => LongConstantImpl(c.longValue) + case dotc.core.Constants.FloatTag => FloatConstantImpl(c.floatValue) + case dotc.core.Constants.DoubleTag => DoubleConstantImpl(c.doubleValue) + case dotc.core.Constants.CharTag => CharConstantImpl(c.charValue) + case dotc.core.Constants.StringTag => StringConstantImpl(c.stringValue) + case dotc.core.Constants.UnitTag => UnitConstantImpl() + case dotc.core.Constants.NullTag => NullConstantImpl() + case dotc.core.Constants.ClazzTag => ClassOfConstantImpl(TypeReprImpl(c.typeValue)) + } + + object Module extends pub.Constant.Module {} + +} + +/////// BooleanConstant /////////////////////////////////////////////////////////////// + +type BooleanConstant = BooleanConstantImpl +final case class BooleanConstantImpl(value: Boolean) extends ConstantImpl, pub.BooleanConstant +object BooleanConstantImpl { + + object Module extends pub.BooleanConstant.Module { + override def apply(x: Boolean): BooleanConstant = BooleanConstantImpl(x) + override def make(x: Boolean): BooleanConstant = BooleanConstantImpl(x) + } + +} + +/////// ByteConstant /////////////////////////////////////////////////////////////// + +type ByteConstant = ByteConstantImpl +final case class ByteConstantImpl(value: Byte) extends ConstantImpl, pub.ByteConstant +object ByteConstantImpl { + + object Module extends pub.ByteConstant.Module { + override def apply(x: Byte): ByteConstant = ByteConstantImpl(x) + override def make(x: Byte): ByteConstant = ByteConstantImpl(x) + } + +} + +/////// ShortConstant /////////////////////////////////////////////////////////////// + +type ShortConstant = ShortConstantImpl +final case class ShortConstantImpl(value: Short) extends ConstantImpl, pub.ShortConstant +object ShortConstantImpl { + + object Module extends pub.ShortConstant.Module { + override def apply(x: Short): ShortConstant = ShortConstantImpl(x) + override def make(x: Short): ShortConstant = ShortConstantImpl(x) + } + +} + +/////// IntConstant /////////////////////////////////////////////////////////////// + +type IntConstant = IntConstantImpl +final case class IntConstantImpl(value: Int) extends ConstantImpl, pub.IntConstant +object IntConstantImpl { + + object Module extends pub.IntConstant.Module { + override def apply(x: Int): IntConstant = IntConstantImpl(x) + override def make(x: Int): IntConstant = IntConstantImpl(x) + } + +} + +/////// LongConstant /////////////////////////////////////////////////////////////// + +type LongConstant = LongConstantImpl +final case class LongConstantImpl(value: Long) extends ConstantImpl, pub.LongConstant +object LongConstantImpl { + + object Module extends pub.LongConstant.Module { + override def apply(x: Long): LongConstant = LongConstantImpl(x) + override def make(x: Long): LongConstant = LongConstantImpl(x) + } + +} + +/////// FloatConstant /////////////////////////////////////////////////////////////// + +type FloatConstant = FloatConstantImpl +final case class FloatConstantImpl(value: Float) extends ConstantImpl, pub.FloatConstant +object FloatConstantImpl { + + object Module extends pub.FloatConstant.Module { + override def apply(x: Float): FloatConstant = FloatConstantImpl(x) + override def make(x: Float): FloatConstant = FloatConstantImpl(x) + } + +} + +/////// DoubleConstant /////////////////////////////////////////////////////////////// + +type DoubleConstant = DoubleConstantImpl +final case class DoubleConstantImpl(value: Double) extends ConstantImpl, pub.DoubleConstant +object DoubleConstantImpl { + + object Module extends pub.DoubleConstant.Module { + override def apply(x: Double): DoubleConstant = DoubleConstantImpl(x) + override def make(x: Double): DoubleConstant = DoubleConstantImpl(x) + } + +} + +/////// CharConstant /////////////////////////////////////////////////////////////// + +type CharConstant = CharConstantImpl +final case class CharConstantImpl(value: Char) extends ConstantImpl, pub.CharConstant +object CharConstantImpl { + + object Module extends pub.CharConstant.Module { + override def apply(x: Char): CharConstant = CharConstantImpl(x) + override def make(x: Char): CharConstant = CharConstantImpl(x) + } + +} + +/////// StringConstant /////////////////////////////////////////////////////////////// + +type StringConstant = StringConstantImpl +final case class StringConstantImpl(value: String) extends ConstantImpl, pub.StringConstant +object StringConstantImpl { + + object Module extends pub.StringConstant.Module { + override def apply(x: String): StringConstant = StringConstantImpl(x) + override def make(x: String): StringConstant = StringConstantImpl(x) + } + +} + +/////// UnitConstant /////////////////////////////////////////////////////////////// + +type UnitConstant = UnitConstantImpl +final case class UnitConstantImpl() extends ConstantImpl, pub.UnitConstant { override def value: Unit = () } +object UnitConstantImpl { + + object Module extends pub.UnitConstant.Module { + override def apply(): UnitConstant = UnitConstantImpl() + override def make(): UnitConstant = UnitConstantImpl() + } + +} + +/////// NullConstant /////////////////////////////////////////////////////////////// + +type NullConstant = NullConstantImpl +final case class NullConstantImpl() extends ConstantImpl, pub.NullConstant { override def value: Null = null } +object NullConstantImpl { + + object Module extends pub.NullConstant.Module { + override def apply(): NullConstant = NullConstantImpl() + override def make(): NullConstant = NullConstantImpl() + } + +} + +/////// ClassOfConstant /////////////////////////////////////////////////////////////// + +type ClassOfConstant = ClassOfConstantImpl +final case class ClassOfConstantImpl(value: TypeReprImpl) extends ConstantImpl, pub.ClassOfConstant +object ClassOfConstantImpl { + + object Module extends pub.ClassOfConstant.Module { + override def apply(x: pub.TypeRepr): ClassOfConstant = ClassOfConstantImpl(x.asInstanceOf[TypeReprImpl]) + override def make(x: pub.TypeRepr): ClassOfConstant = ClassOfConstantImpl(x.asInstanceOf[TypeReprImpl]) + } + +} \ No newline at end of file diff --git a/compiler/src/scala/quoted/compiletime/internal/FlagsImpl.scala b/compiler/src/scala/quoted/compiletime/internal/FlagsImpl.scala new file mode 100644 index 000000000000..479174e007ae --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/FlagsImpl.scala @@ -0,0 +1,80 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import scala.quoted.compiletime as pub + +type Flags = FlagsImpl +final class FlagsImpl(val underlying: dotc.core.Flags.FlagSet) extends pub.Flags { + + override def is(that: pub.Flags): Boolean = + val thatImpl = that.asInstanceOf[FlagsImpl] + underlying.isAllOf(thatImpl.underlying) + + override def |(that: pub.Flags): pub.Flags = + val thatImpl = that.asInstanceOf[FlagsImpl] + new FlagsImpl(underlying | thatImpl.underlying) + + override def &(that: pub.Flags): pub.Flags = + val thatImpl = that.asInstanceOf[FlagsImpl] + new FlagsImpl(underlying & thatImpl.underlying) + + override def show: String = underlying.toString + + override def toString: String = underlying.toString + override lazy val hashCode: Int = underlying.hashCode + override def equals(that: Any): Boolean = that.asInstanceOf[Matchable] match + case that: FlagsImpl => this.underlying == that.underlying + case _ => false + +} +object FlagsImpl { + object Module extends pub.Flags.Module { + def Abstract: pub.Flags = new FlagsImpl(dotc.core.Flags.Abstract) + def AbsOverride: pub.Flags = new FlagsImpl(dotc.core.Flags.AbsOverride) + def Artifact: pub.Flags = new FlagsImpl(dotc.core.Flags.Artifact) + def Case: pub.Flags = new FlagsImpl(dotc.core.Flags.Case) + def CaseAccessor: pub.Flags = new FlagsImpl(dotc.core.Flags.CaseAccessor) + def Contravariant: pub.Flags = new FlagsImpl(dotc.core.Flags.Contravariant) + def Covariant: pub.Flags = new FlagsImpl(dotc.core.Flags.Covariant) + def Deferred: pub.Flags = new FlagsImpl(dotc.core.Flags.Deferred) + def EmptyFlags: pub.Flags = new FlagsImpl(dotc.core.Flags.EmptyFlags) + def Enum: pub.Flags = new FlagsImpl(dotc.core.Flags.Enum) + def Erased: pub.Flags = new FlagsImpl(dotc.core.Flags.Erased) + def Exported: pub.Flags = new FlagsImpl(dotc.core.Flags.Exported) + def ExtensionMethod: pub.Flags = new FlagsImpl(dotc.core.Flags.ExtensionMethod) + def FieldAccessor: pub.Flags = new FlagsImpl(dotc.core.Flags.Accessor) + def Final: pub.Flags = new FlagsImpl(dotc.core.Flags.Final) + def Given: pub.Flags = new FlagsImpl(dotc.core.Flags.Given) + def HasDefault: pub.Flags = new FlagsImpl(dotc.core.Flags.HasDefault) + def Implicit: pub.Flags = new FlagsImpl(dotc.core.Flags.Implicit) + def Infix: pub.Flags = new FlagsImpl(dotc.core.Flags.Infix) + def Inline: pub.Flags = new FlagsImpl(dotc.core.Flags.Inline) + def Invisible: pub.Flags = new FlagsImpl(dotc.core.Flags.Invisible) + def JavaDefined: pub.Flags = new FlagsImpl(dotc.core.Flags.JavaDefined) + def JavaStatic: pub.Flags = new FlagsImpl(dotc.core.Flags.JavaStatic) + def JavaAnnotation: pub.Flags = new FlagsImpl(dotc.core.Flags.JavaAnnotation) + def Lazy: pub.Flags = new FlagsImpl(dotc.core.Flags.Lazy) + def Local: pub.Flags = new FlagsImpl(dotc.core.Flags.Local) + def Macro: pub.Flags = new FlagsImpl(dotc.core.Flags.Macro) + def Method: pub.Flags = new FlagsImpl(dotc.core.Flags.Method) + def Module: pub.Flags = new FlagsImpl(dotc.core.Flags.Module) + def Mutable: pub.Flags = new FlagsImpl(dotc.core.Flags.Mutable) + def NoInits: pub.Flags = new FlagsImpl(dotc.core.Flags.NoInits) + def Opaque: pub.Flags = new FlagsImpl(dotc.core.Flags.Opaque) + def Open: pub.Flags = new FlagsImpl(dotc.core.Flags.Open) + def Override: pub.Flags = new FlagsImpl(dotc.core.Flags.Override) + def Package: pub.Flags = new FlagsImpl(dotc.core.Flags.Package) + def Param: pub.Flags = new FlagsImpl(dotc.core.Flags.Param) + def ParamAccessor: pub.Flags = new FlagsImpl(dotc.core.Flags.ParamAccessor) + def Private: pub.Flags = new FlagsImpl(dotc.core.Flags.Private) + def PrivateLocal: pub.Flags = new FlagsImpl(dotc.core.Flags.Private | dotc.core.Flags.Local) + def Protected: pub.Flags = new FlagsImpl(dotc.core.Flags.Protected) + def Scala2x: pub.Flags = new FlagsImpl(dotc.core.Flags.Scala2x) + def Sealed: pub.Flags = new FlagsImpl(dotc.core.Flags.Sealed) + def StableRealizable: pub.Flags = new FlagsImpl(dotc.core.Flags.StableRealizable) + def Static: pub.Flags = new FlagsImpl(dotc.core.Flags.JavaStatic) + def Synthetic: pub.Flags = new FlagsImpl(dotc.core.Flags.Synthetic) + def Trait: pub.Flags = new FlagsImpl(dotc.core.Flags.Trait) + def Transparent: pub.Flags = new FlagsImpl(dotc.core.Flags.Transparent) + } +} diff --git a/compiler/src/scala/quoted/compiletime/internal/ParamClauseImpl.scala b/compiler/src/scala/quoted/compiletime/internal/ParamClauseImpl.scala new file mode 100644 index 000000000000..7ca1f9c4896b --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/ParamClauseImpl.scala @@ -0,0 +1,50 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc.ast.tpd +import scala.annotation.experimental +import scala.quoted.compiletime as pub + +/////// ParamClause /////////////////////////////////////////////////////////////// + +type ParamClause = pub.ParamClause & ParamClauseImpl +sealed trait ParamClauseImpl { _self: pub.ParamClause => + val underlying: tpd.ParamClause +} +object ParamClauseImpl { + def apply(x: tpd.ParamClause): ParamClauseImpl = x match { + case x: List[tpd.ValDef] @unchecked if x.isEmpty || x.head.isInstanceOf[tpd.ValDef] => new TermParamClauseImpl(x) + case x: List[tpd.TypeDef] @unchecked if x.isEmpty || x.head.isInstanceOf[tpd.TypeDef] => new TypeParamClauseImpl(x) + case _ => throw new MatchError(x) + } + object Module extends pub.ParamClause.Module {} +} + +/////// TermParamClause /////////////////////////////////////////////////////////////// + +type TermParamClause = TermParamClauseImpl +final class TermParamClauseImpl(val underlying: List[tpd.ValDef]) extends ParamClauseImpl, pub.TermParamClause { + override def params: List[pub.ValDef] = ??? + override def isImplicit: Boolean = ??? + override def isGiven: Boolean = ??? + @experimental override def erasedArgs: List[Boolean] = ??? + @experimental override def hasErasedArgs: Boolean = ??? +} +object TermParamClauseImpl { + object Module extends pub.TermParamClause.Module { + override def apply(params: List[pub.ValDef]): pub.TermParamClause = ??? + override def make(params: List[pub.ValDef]): pub.TermParamClause = ??? + } +} + +/////// TypeParamClause /////////////////////////////////////////////////////////////// + +type TypeParamClause = TypeParamClauseImpl +final class TypeParamClauseImpl(val underlying: List[tpd.TypeDef]) extends ParamClauseImpl, pub.TypeParamClause { + override def params: List[pub.TypeDef] = ??? +} +object TypeParamClauseImpl { + object Module extends pub.TypeParamClause.Module { + override def apply(params: List[pub.TypeDef]): pub.TypeParamClause = ??? + override def make(params: List[pub.TypeDef]): pub.TypeParamClause = ??? + } +} \ No newline at end of file diff --git a/compiler/src/scala/quoted/compiletime/internal/PositionImpl.scala b/compiler/src/scala/quoted/compiletime/internal/PositionImpl.scala new file mode 100644 index 000000000000..c26bff442b84 --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/PositionImpl.scala @@ -0,0 +1,52 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import dotty.tools.dotc.core.Contexts.* +import dotty.tools.dotc.quoted.MacroExpansion +import scala.quoted.compiletime as pub + +type Position = PositionImpl +final case class PositionImpl(position: dotc.util.SourcePosition) extends pub.Position { + + override lazy val start: Int = position.start + + override lazy val end: Int = position.end + + override lazy val sourceFile: SourceFile = SourceFileImpl(position.source) + + override lazy val startLine: Int = position.startLine + + override lazy val endLine: Int = position.endLine + + override lazy val startColumn: Int = position.startColumn + + override lazy val endColumn: Int = position.endColumn + + override lazy val sourceCode: Option[String] = + val contents = position.source.content() + if contents.length < position.end then None + else Some(new String(contents, position.start, position.end - position.start)) + + override def toString: String = position.toString + override lazy val hashCode: Int = position.hashCode + override def equals(that: Any): Boolean = that.asInstanceOf[Matchable] match + case that: PositionImpl => this.position == that.position + case _ => false + +} +object PositionImpl { + + final class Module(using val ctx: Context) extends pub.Position.Module { + + override def ofMacroExpansion: Position = + PositionImpl(MacroExpansion.position.getOrElse(dotc.util.SourcePosition(ctx.source, dotc.util.Spans.NoSpan))) + + override def apply(sourceFile: pub.SourceFile, start: Int, end: Int): Position = + make(sourceFile, start, end) + + override def make(sourceFile: pub.SourceFile, start: Int, end: Int): Position = + PositionImpl(dotc.util.SourcePosition(sourceFile.cast.sourceFile, dotc.util.Spans.Span(start, end))) + + } + +} diff --git a/compiler/src/scala/quoted/compiletime/internal/QuotesImpl.scala b/compiler/src/scala/quoted/compiletime/internal/QuotesImpl.scala new file mode 100644 index 000000000000..4d7859076166 --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/QuotesImpl.scala @@ -0,0 +1,26 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc.core.Contexts.* +import scala.quoted.compiletime as pub + +object QuotesImpl { + + def apply()(using Context): pub.Quotes = + new QuotesImpl + + // FIX-PRE-MERGE (KR) : + /* + def showDecompiledTree(tree: tpd.Tree)(using Context): String = + import qctx.reflect.Printer.{TreeCode, TreeAnsiCode} + val qctx: QuotesImpl = new QuotesImpl(using MacroExpansion.context(tree)) + if ctx.settings.color.value == "always" then TreeAnsiCode.show(tree) + else TreeCode.show(tree) + */ + +} + +final class QuotesImpl private (using val ctx: Context) extends pub.Quotes { + + override lazy val reflectV2: reflectImpl.Module = new reflectImpl.Module + +} diff --git a/compiler/src/scala/quoted/compiletime/internal/SelectorImpl.scala b/compiler/src/scala/quoted/compiletime/internal/SelectorImpl.scala new file mode 100644 index 000000000000..d7d51a0d2624 --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/SelectorImpl.scala @@ -0,0 +1,80 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc.ast.untpd +import dotty.tools.dotc.core.StdNames.nme +import scala.annotation.experimental +import scala.quoted.compiletime as pub + +/////// Selector /////////////////////////////////////////////////////////////// + +type Selector = pub.Selector & SelectorImpl +sealed trait SelectorImpl { _self: pub.Selector => + val underlying: untpd.ImportSelector +} +object SelectorImpl { + def apply(x: untpd.ImportSelector): SelectorImpl = + if x.isGiven then new GivenSelectorImpl(x) + else if x.renamed.isEmpty then new SimpleSelectorImpl(x) + else x.renamed match + case untpd.Ident(nme.WILDCARD) => new OmitSelectorImpl(x) + case _ => new RenameSelectorImpl(x) + + object Module extends pub.Selector.Module {} +} + +/////// SimpleSelector /////////////////////////////////////////////////////////////// + +type SimpleSelector = SimpleSelectorImpl +final class SimpleSelectorImpl(val underlying: untpd.ImportSelector) extends SelectorImpl, pub.SimpleSelector { + override def name: String = ??? + override def namePos: pub.Position = ??? +} +object SimpleSelectorImpl { + object Module extends pub.SimpleSelector.Module { + @experimental override def apply(name: String): pub.SimpleSelector = ??? + @experimental override def make(name: String): pub.SimpleSelector = ??? + } +} + +/////// RenameSelector /////////////////////////////////////////////////////////////// + +type RenameSelector = RenameSelectorImpl +final class RenameSelectorImpl(val underlying: untpd.ImportSelector) extends SelectorImpl, pub.RenameSelector { + override def fromName: String = ??? + override def fromPos: pub.Position = ??? + override def toName: String = ??? + override def toPos: pub.Position = ??? +} +object RenameSelectorImpl { + object Module extends pub.RenameSelector.Module { + @experimental override def apply(fromName: String, toName: String): pub.RenameSelector = ??? + @experimental override def make(fromName: String, toName: String): pub.RenameSelector = ??? + } +} + +/////// OmitSelector /////////////////////////////////////////////////////////////// + +type OmitSelector = OmitSelectorImpl +final class OmitSelectorImpl(val underlying: untpd.ImportSelector) extends SelectorImpl, pub.OmitSelector { + override def name: String = ??? + override def namePos: pub.Position = ??? +} +object OmitSelectorImpl { + object Module extends pub.OmitSelector.Module { + @experimental override def apply(name: String): pub.OmitSelector = ??? + @experimental override def make(name: String): pub.OmitSelector = ??? + } +} + +/////// GivenSelector /////////////////////////////////////////////////////////////// + +type GivenSelector = GivenSelectorImpl +final class GivenSelectorImpl(val underlying: untpd.ImportSelector) extends SelectorImpl, pub.GivenSelector { + override def bound: Option[pub.TypeTree] = ??? +} +object GivenSelectorImpl { + object Module extends pub.GivenSelector.Module { + @experimental override def apply(bound: Option[pub.TypeTree]): pub.GivenSelector = ??? + @experimental override def make(bound: Option[pub.TypeTree]): pub.GivenSelector = ??? + } +} \ No newline at end of file diff --git a/compiler/src/scala/quoted/compiletime/internal/SignatureImpl.scala b/compiler/src/scala/quoted/compiletime/internal/SignatureImpl.scala new file mode 100644 index 000000000000..7f1b3b407070 --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/SignatureImpl.scala @@ -0,0 +1,15 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import scala.quoted.compiletime as pub + +/////// Signature /////////////////////////////////////////////////////////////// + +type Signature = SignatureImpl +final class SignatureImpl(val underlying: dotc.core.Signature) extends pub.Signature { + override def paramSigs: List[String | Int] = ??? + override def resultSig: String = ??? +} +object SignatureImpl { + object Module extends pub.Signature.Module {} +} \ No newline at end of file diff --git a/compiler/src/scala/quoted/compiletime/internal/SourceFileImpl.scala b/compiler/src/scala/quoted/compiletime/internal/SourceFileImpl.scala new file mode 100644 index 000000000000..95461476f12a --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/SourceFileImpl.scala @@ -0,0 +1,36 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import dotty.tools.dotc.core.Contexts.* +import scala.quoted.compiletime as pub + +type SourceFile = SourceFileImpl +final class SourceFileImpl(val sourceFile: dotc.util.SourceFile) extends pub.SourceFile { + + override lazy val getJPath: Option[java.nio.file.Path] = Option(sourceFile.file.jpath) + + override lazy val name: String = sourceFile.name + + override lazy val path: String = sourceFile.path + + override lazy val content: Option[String] = + // TODO detect when we do not have a source and return None + Some(new String(sourceFile.content())) + + override def toString: String = sourceFile.toString + override lazy val hashCode: Int = sourceFile.hashCode + override def equals(that: Any): Boolean = that.asInstanceOf[Matchable] match + case that: SourceFileImpl => this.sourceFile == that.sourceFile + case _ => false + +} +object SourceFileImpl { + + final class Module(using val ctx: Context) extends pub.SourceFile.Module { + + override def current: SourceFile = + ??? // FIX-PRE-MERGE (KR) : + + } + +} diff --git a/compiler/src/scala/quoted/compiletime/internal/SymbolImpl.scala b/compiler/src/scala/quoted/compiletime/internal/SymbolImpl.scala new file mode 100644 index 000000000000..00629311d53a --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/SymbolImpl.scala @@ -0,0 +1,15 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import dotty.tools.dotc.core.Contexts.* +import scala.quoted.compiletime as pub + +type Symbol = SymbolImpl +final case class SymbolImpl(symbol: dotc.core.Symbols.Symbol)(using val ctx: Context) extends pub.Symbol { + // TODO implementations +} +object SymbolImpl { + final class Module(using val ctx: Context) extends pub.Symbol.Module { + // TODO implementations + } +} diff --git a/compiler/src/scala/quoted/compiletime/internal/TreeImpl.scala b/compiler/src/scala/quoted/compiletime/internal/TreeImpl.scala new file mode 100644 index 000000000000..d9dcba3c9eae --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/TreeImpl.scala @@ -0,0 +1,1150 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import dotty.tools.dotc.ast.{tpd, untpd} +import dotty.tools.dotc.core.NameKinds +import scala.quoted.Expr +import scala.quoted.Type +import scala.quoted.compiletime as pub + +/////// Tree /////////////////////////////////////////////////////////////// + +type Tree = pub.Tree & TreeImpl + +sealed trait TreeImpl { _self: pub.Tree => + + val underlying: tpd.Tree + + override final def toString: String = underlying.toString + override lazy val hashCode: Int = underlying.hashCode + override final def equals(that: Any): Boolean = that.asInstanceOf[Matchable] match + case that: TreeImpl => this.underlying == that.underlying + case _ => false + + override def pos: Position = PositionImpl(underlying.sourcePos) + + override def symbol: Symbol = SymbolImpl(underlying.symbol) + + override def show(using pub.Printer[pub.Tree]): String = ??? + + override def isExpr: Boolean = ??? + + override def asExpr: Expr[Any] = ??? + + override def asExprOf[T](using Type[T]): Expr[T] = ??? + + override def changeOwner(newOwner: pub.Symbol): Tree = TreeImpl(tpd.TreeOps(underlying).changeNonLocalOwners(newOwner.cast.symbol)) + +} + +object TreeImpl { + + implicit def treeToDotc(tree: pub.Tree): tpd.Tree = tree.cast.underlying + + private[internal] def optional[T <: tpd.Tree](x: T): Option[T] = + + if x.isEmpty then None else Some(x) + + private def effectivePatterns(patterns: List[tpd.Tree]): List[tpd.Tree] = + + patterns match + + case patterns0 :+ dotty.tools.dotc.ast.Trees.SeqLiteral(elems, _) => patterns0 ::: elems + + case _ => patterns + + def apply(tree: tpd.Tree): TreeImpl = tree match { + + case tree: tpd.PackageDef => new PackageClauseImpl(tree) + + case tree: tpd.Import => new ImportImpl(tree) + + case tree: tpd.Export => new ExportImpl(tree) + + case tree: tpd.TypeDef => + + if tree.isClassDef then new ClassDefImpl(tree) + else new TypeDefImpl(tree) + + case tree: tpd.DefDef => new DefDefImpl(tree) + + case tree: tpd.ValDef => new ValDefImpl(tree) + + case tree: tpd.Ident => + + if tree.isTerm then + + if tree.name == nme.WILDCARD then new WildcardImpl(tree) + else new IdentImpl(tree) + else if tree.name == nme.WILDCARD then new WildcardTypeTreeImpl(tree) + else new TypeIdentImpl(tree) + + case tree: tpd.Select => + + if tree.isTerm then + + tree.name match + + case NameKinds.OuterSelectName(_, _) => new SelectOuterImpl(tree) + + case _ => new SelectImpl(tree) + else if tree.qualifier.isTerm then new TypeSelectImpl(tree) + else new TypeProjectionImpl(tree) + + case tree: tpd.Literal => new LiteralImpl(tree) + + case tree: tpd.This => new ThisImpl(tree) + + case tree: tpd.New => new NewImpl(tree) + + case tree: tpd.NamedArg => new NamedArgImpl(tree) + + case tree: tpd.Apply => new ApplyImpl(tree) + + case tree: tpd.TypeApply => new TypeApplyImpl(tree) + + case tree: tpd.Super => new SuperImpl(tree) + + case tree: tpd.Typed => new TypedImpl(tree) + + case tree: tpd.Assign => new AssignImpl(tree) + + case tree: tpd.Block => + + if tree.isTerm then new BlockImpl(tree) + else new TypeBlockImpl(tree) + + case tree: tpd.Closure => new ClosureImpl(tree) + + case tree: tpd.If => new IfImpl(tree) + + case tree: tpd.Match => + + if !tree.selector.isEmpty then new MatchImpl(tree) + else new SummonFromImpl(tree) + + case tree: tpd.Try => new TryImpl(tree) + + case tree: tpd.Return => new ReturnImpl(tree) + + case tree: tpd.SeqLiteral => new RepeatedImpl(tree) + + case tree: tpd.Inlined => new InlinedImpl(tree) + + case tree: tpd.WhileDo => new WhileImpl(tree) + + case tree: tpd.TypeTree => + + if tree.tpe.isInstanceOf[dotc.core.Types.TypeBounds] then new TypeBoundsTreeImpl(tree) + else new InferredImpl(tree) + + case tree: tpd.SingletonTypeTree => new SingletonImpl(tree) + + case tree: tpd.RefinedTypeTree => new RefinedImpl(tree) + + case tree: tpd.AppliedTypeTree => new AppliedImpl(tree) + + case tree: tpd.Annotated => new AnnotatedImpl(tree) + + case tree: tpd.MatchTypeTree => new MatchTypeTreeImpl(tree) + + case tree: tpd.ByNameTypeTree => new ByNameImpl(tree) + + case tree: tpd.LambdaTypeTree => new LambdaTypeTreeImpl(tree) + + case tree: tpd.Bind => + + if tree.name.isTypeName then new TypeBindImpl(tree) + else new BindImpl(tree) + + case tree: tpd.TypeBoundsTree => new TypeBoundsTreeImpl(tree) + + case tree: tpd.CaseDef => + + if tree.body.isTerm then new CaseDefImpl(tree) + else new TypeCaseDefImpl(tree) + + case tree: tpd.UnApply => new UnapplyImpl(tree) + + case tree: tpd.QuotePattern => new UnapplyImpl(tree) + + case tree: tpd.Alternative => new AlternativesImpl(tree) + + case tree: tpd.Quote => new ApplyImpl(tree) + + case tree: tpd.Splice => new ApplyImpl(tree) + + case _ => throw new MatchError(tree) + + } + + object Module extends pub.Tree.Module {} + +} + +/////// PackageClause /////////////////////////////////////////////////////////////// + +type PackageClause = PackageClauseImpl + +final class PackageClauseImpl(val underlying: tpd.PackageDef) extends TreeImpl, pub.PackageClause { + + override def pid: Ref = TreeImpl(underlying.pid).asInstanceOf[Ref] + + override def stats: List[Tree] = underlying.stats.map(TreeImpl(_)) + +} + +object PackageClauseImpl { + + object Module extends pub.PackageClause.Module { + + override def apply(pid: pub.Ref, stats: List[pub.Tree]): pub.PackageClause = ??? + + override def make(pid: pub.Ref, stats: List[pub.Tree]): pub.PackageClause = ??? + + } + +} + +/////// Statement /////////////////////////////////////////////////////////////// + +type Statement = pub.Statement & StatementImpl + +sealed trait StatementImpl extends TreeImpl { _self: pub.Statement => } + +object StatementImpl { + + object Module extends pub.Statement.Module {} + +} + +/////// Import /////////////////////////////////////////////////////////////// + +type Import = ImportImpl + +final class ImportImpl(val underlying: tpd.Import) extends StatementImpl, pub.Import { + + override def expr: Term = TreeImpl(underlying.expr).asInstanceOf[Term] + + override def selectors: List[Selector] = underlying.selectors.map(SelectorImpl(_)) + +} + +object ImportImpl { + + object Module extends pub.Import.Module { + + override def apply(expr: pub.Term, selectors: List[pub.Selector]): pub.Import = ??? + + override def make(expr: pub.Term, selectors: List[pub.Selector]): pub.Import = ??? + + } + +} + +/////// Export /////////////////////////////////////////////////////////////// + +type Export = ExportImpl + +final class ExportImpl(val underlying: tpd.Export) extends StatementImpl, pub.Export { + + override def expr: Term = TreeImpl(underlying.expr).asInstanceOf[Term] + + override def selectors: List[Selector] = underlying.selectors.map(SelectorImpl(_)) + +} + +object ExportImpl { + + object Module extends pub.Export.Module {} + +} + +/////// Definition /////////////////////////////////////////////////////////////// + +type Definition = pub.Definition & DefinitionImpl + +sealed trait DefinitionImpl extends StatementImpl { _self: pub.Definition => + + override val underlying: tpd.MemberDef + + override def name: String = underlying.name.toString + +} + +object DefinitionImpl { + + object Module extends pub.Definition.Module {} + +} + +/////// ClassDef /////////////////////////////////////////////////////////////// + +type ClassDef = ClassDefImpl + +final class ClassDefImpl(override val underlying: tpd.TypeDef) extends DefinitionImpl, pub.ClassDef { + + override def constructor: DefDef = TreeImpl(underlying.rhs.asInstanceOf[tpd.Template].constr).asInstanceOf[DefDef] + + override def parents: List[Tree] = underlying.rhs.asInstanceOf[tpd.Template].parents.map(TreeImpl(_)) + + override def self: Option[ValDef] = TreeImpl.optional(underlying.rhs.asInstanceOf[tpd.Template].self).map(TreeImpl(_).asInstanceOf[ValDef]) + + override def body: List[Statement] = underlying.rhs.asInstanceOf[tpd.Template].body.map(TreeImpl(_).asInstanceOf[Statement]) + +} + +object ClassDefImpl { + + object Module extends pub.ClassDef.Module { + + override def apply(cls: pub.Symbol, parents: List[pub.Tree], body: List[pub.Statement]): pub.ClassDef = ??? + + override def make(cls: pub.Symbol, parents: List[pub.Tree], body: List[pub.Statement]): pub.ClassDef = ??? + + override def module(module: pub.Symbol, parents: List[pub.Tree], body: List[pub.Statement]): (pub.ValDef, pub.ClassDef) = ??? + + } + +} + +/////// ValOrDefDef /////////////////////////////////////////////////////////////// + +type ValOrDefDef = pub.ValOrDefDef & ValOrDefDefImpl + +sealed trait ValOrDefDefImpl extends DefinitionImpl { _self: pub.ValOrDefDef => + + override val underlying: tpd.ValOrDefDef + + override def tpt: TypeTree = TreeImpl(underlying.tpt).asInstanceOf[TypeTree] + + override def rhs: Option[Term] = TreeImpl.optional(underlying.rhs).map(TreeImpl(_).asInstanceOf[Term]) + +} + +object ValOrDefDefImpl { + + object Module extends pub.ValOrDefDef.Module {} + +} + +/////// DefDef /////////////////////////////////////////////////////////////// + +type DefDef = DefDefImpl + +final class DefDefImpl(override val underlying: tpd.DefDef) extends ValOrDefDefImpl, pub.DefDef { + + override def paramss: List[ParamClause] = underlying.paramss.map(ParamClauseImpl(_)) + + override def leadingTypeParams: List[TypeDef] = underlying.leadingTypeParams.map(TreeImpl(_).asInstanceOf[TypeDef]) + + override def trailingParamss: List[ParamClause] = underlying.trailingParamss.map(ParamClauseImpl(_)) + + override def termParamss: List[TermParamClause] = underlying.termParamss.map(TermParamClauseImpl(_)) + + override def returnTpt: TypeTree = TreeImpl(underlying.tpt).asInstanceOf[TypeTree] + +} + +object DefDefImpl { + + object Module extends pub.DefDef.Module { + + override def apply(symbol: pub.Symbol, rhsFn: List[List[pub.Tree]] => Option[pub.Term]): pub.DefDef = ??? + + override def make(symbol: pub.Symbol, rhsFn: List[List[pub.Tree]] => Option[pub.Term]): pub.DefDef = ??? + + } + +} + +/////// ValDef /////////////////////////////////////////////////////////////// + +type ValDef = ValDefImpl + +final class ValDefImpl(override val underlying: tpd.ValDef) extends ValOrDefDefImpl, pub.ValDef + +object ValDefImpl { + + object Module extends pub.ValDef.Module { + + override def apply(symbol: pub.Symbol, rhs: Option[pub.Term]): pub.ValDef = ??? + + override def make(symbol: pub.Symbol, rhs: Option[pub.Term]): pub.ValDef = ??? + + override def let(owner: pub.Symbol, name: String, rhs: pub.Term, flags: pub.Flags)(body: pub.Ref => pub.Term): pub.Term = ??? + + override def let(owner: pub.Symbol, name: String, rhs: pub.Term)(body: pub.Ref => pub.Term): pub.Term = ??? + + override def let(owner: pub.Symbol, rhs: pub.Term)(body: pub.Ref => pub.Term): pub.Term = ??? + + override def let(owner: pub.Symbol, terms: List[pub.Term])(body: List[pub.Ref] => pub.Term): pub.Term = ??? + + } + +} + +/////// TypeDef /////////////////////////////////////////////////////////////// + +type TypeDef = TypeDefImpl + +final class TypeDefImpl(override val underlying: tpd.TypeDef) extends DefinitionImpl, pub.TypeDef { + + override def rhs: Tree = TreeImpl(underlying.rhs) + +} + +object TypeDefImpl { + object Module extends pub.TypeDef.Module { + override def apply(symbol: pub.Symbol): pub.TypeDef = ??? + override def make(symbol: pub.Symbol): pub.TypeDef = ??? + } +} + +/////// Term /////////////////////////////////////////////////////////////// + +type Term = pub.Term & TermImpl +sealed trait TermImpl extends StatementImpl { _self: pub.Term => + override def tpe: TypeRepr = TypeReprImpl(underlying.tpe.widenSkolem) + override def underlyingArgument: Term = TreeImpl(new tpd.TreeOps(underlying).underlyingArgument).asInstanceOf[Term] + override def underlying: Term = TreeImpl(new tpd.TreeOps(underlying).underlying).asInstanceOf[Term] + override def etaExpand(owner: pub.Symbol): Term = + val t = underlying.tpe.widen match { + case mtpe: dotc.core.Types.MethodType if !mtpe.isParamDependent => + val closureResType = mtpe.resType match { + case t: dotc.core.Types.MethodType => t.toFunctionType(isJava = underlying.symbol.is(dotc.core.Flags.JavaDefined)) + case t => t + } + val closureTpe = dotc.core.Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType) + val closureMethod = dotc.core.Symbols.newAnonFun(owner.cast.symbol, closureTpe) + tpd.Closure(closureMethod, tss => new tpd.TreeOps(underlying).appliedToTermArgs(tss.head).etaExpand(closureMethod)) + case _ => underlying + } + TreeImpl(t).asInstanceOf[Term] + + override def appliedTo(arg: pub.Term): Term = appliedToArgs(List(arg.cast)) + override def appliedTo(arg: pub.Term, args: pub.Term*): Term = appliedToArgs(arg.cast :: args.map(_.cast).toList) + override def appliedToArgs(args: List[pub.Term]): Apply = ApplyImpl(tpd.Apply(underlying, args.map(_.cast.underlying))) + override def appliedToArgss(argss: List[List[pub.Term]]): Term = + TreeImpl(argss.foldLeft(underlying)((acc, args) => tpd.Apply(acc, args.map(_.cast.underlying)))).asInstanceOf[Term] + override def appliedToNone: Apply = appliedToArgs(Nil) + override def ensureApplied: Term = + def isParameterless(tpe: TypeRepr): Boolean = !tpe.isInstanceOf[MethodType] + if isParameterless(tpe.widen) then this.asInstanceOf[Term] else appliedToNone.asInstanceOf[Term] + override def appliedToType(targ: pub.TypeRepr): Term = appliedToTypes(List(targ.cast)) + override def appliedToTypes(targs: List[pub.TypeRepr]): Term = appliedToTypeTrees(targs.map(t => InferredImpl(tpd.TypeTree(t.cast.underlying)))) + override def appliedToTypeTrees(targs: List[pub.TypeTree]): Term = + if targs.isEmpty then this.asInstanceOf[Term] else TreeImpl(tpd.TypeApply(underlying, targs.map(_.cast.underlying))).asInstanceOf[Term] + override def select(sym: pub.Symbol): Select = SelectImpl(tpd.Select(underlying, sym.cast.symbol)) +} +object TermImpl { + object Module extends pub.Term.Module { + override def betaReduce(term: pub.Term): Option[pub.Term] = ??? + } +} + +/////// Ref /////////////////////////////////////////////////////////////// + +type Ref = pub.Ref & RefImpl +sealed trait RefImpl extends TermImpl { _self: pub.Ref => + override val underlying: tpd.RefTree +} +object RefImpl { + object Module extends pub.Ref.Module { + override def term(tp: pub.TermRef): pub.Ref = ??? + override def apply(sym: pub.Symbol): pub.Ref = ??? + override def make(sym: pub.Symbol): pub.Ref = ??? + } +} + +/////// Ident /////////////////////////////////////////////////////////////// + +type Ident = IdentImpl +final class IdentImpl(override val underlying: tpd.Ident) extends RefImpl, pub.Ident { + override def name: String = underlying.name.toString +} +object IdentImpl { + object Module extends pub.Ident.Module { + override def apply(tmref: pub.TermRef): pub.Term = ??? + override def make(tmref: pub.TermRef): pub.Term = ??? + } +} + +/////// Wildcard /////////////////////////////////////////////////////////////// + +type Wildcard = WildcardImpl +final class WildcardImpl(override val underlying: tpd.Ident) extends RefImpl, pub.Wildcard { + override def name: String = underlying.name.toString +} +object WildcardImpl { + object Module extends pub.Wildcard.Module { + override def apply(): pub.Wildcard = ??? + override def make(): pub.Wildcard = ??? + } +} + +/////// Select /////////////////////////////////////////////////////////////// + +type Select = SelectImpl +final class SelectImpl(override val underlying: tpd.Select) extends RefImpl, pub.Select { + override def qualifier: Term = TreeImpl(underlying.qualifier).asInstanceOf[Term] + override def name: String = underlying.name.toString + override def signature: Option[Signature] = + if underlying.symbol.signature == dotc.core.Signature.NotAMethod then None + else Some(SignatureImpl(underlying.symbol.signature)) +} +object SelectImpl { + object Module extends pub.Select.Module { + override def apply(qualifier: pub.Term, symbol: pub.Symbol): pub.Select = ??? + override def make(qualifier: pub.Term, symbol: pub.Symbol): pub.Select = ??? + override def unique(qualifier: pub.Term, name: String): pub.Select = ??? + override def overloaded(qualifier: pub.Term, name: String, targs: List[pub.TypeRepr], args: List[pub.Term]): pub.Term = ??? + override def overloaded(qualifier: pub.Term, name: String, targs: List[pub.TypeRepr], args: List[pub.Term], returnType: pub.TypeRepr): pub.Term = ??? + } +} + +/////// Literal /////////////////////////////////////////////////////////////// + +type Literal = LiteralImpl +final class LiteralImpl(val underlying: tpd.Literal) extends TermImpl, pub.Literal { + override def constant: Constant = ConstantImpl(underlying.const) +} +object LiteralImpl { + object Module extends pub.Literal.Module { + override def apply(constant: pub.Constant): pub.Literal = ??? + override def make(constant: pub.Constant): pub.Literal = ??? + } +} + +/////// This /////////////////////////////////////////////////////////////// + +type This = ThisImpl +final class ThisImpl(val underlying: tpd.This) extends TermImpl, pub.This { + override def id: Option[String] = TreeImpl.optional(underlying.qual).map(_.name.toString) +} +object ThisImpl { + object Module extends pub.This.Module { + override def apply(cls: pub.Symbol): pub.This = ??? + override def make(cls: pub.Symbol): pub.This = ??? + } +} + +/////// New /////////////////////////////////////////////////////////////// + +type New = NewImpl +final class NewImpl(val underlying: tpd.New) extends TermImpl, pub.New { + override def tpt: TypeTree = TreeImpl(underlying.tpt).asInstanceOf[TypeTree] +} +object NewImpl { + object Module extends pub.New.Module { + override def apply(tpt: pub.TypeTree): pub.New = ??? + override def make(tpt: pub.TypeTree): pub.New = ??? + } +} + +/////// NamedArg /////////////////////////////////////////////////////////////// + +type NamedArg = NamedArgImpl +final class NamedArgImpl(val underlying: tpd.NamedArg) extends TermImpl, pub.NamedArg { + override def name: String = underlying.name.toString + override def value: Term = TreeImpl(underlying.arg).asInstanceOf[Term] +} +object NamedArgImpl { + object Module extends pub.NamedArg.Module { + override def apply(name: String, arg: pub.Term): pub.NamedArg = ??? + override def make(name: String, arg: pub.Term): pub.NamedArg = ??? + } +} + +/////// Apply /////////////////////////////////////////////////////////////// + +type Apply = ApplyImpl +final class ApplyImpl(val underlying: tpd.Tree) extends TermImpl, pub.Apply { + override def fun: Term = + val t = underlying match + case self: tpd.Apply => self.fun + case self: tpd.Quote => + tpd + .ref(dotc.core.Symbols.defn.QuotedRuntime_exprQuote) + .appliedToType(self.bodyType) + .withSpan(self.span) + case self: tpd.Splice => + tpd + .ref(dotc.core.Symbols.defn.QuotedRuntime_exprSplice) + .appliedToType(self.tpe) + .withSpan(self.span) + TreeImpl(t).asInstanceOf[Term] + + override def args: List[Term] = + val ts = underlying match + case self: tpd.Apply => self.args + case self: tpd.Quote => List(self.body) + case self: tpd.Splice => List(self.expr) + ts.map(TreeImpl(_).asInstanceOf[Term]) +} +object ApplyImpl { + object Module extends pub.Apply.Module { + override def apply(fun: pub.Term, args: List[pub.Term]): pub.Apply = ??? + override def make(fun: pub.Term, args: List[pub.Term]): pub.Apply = ??? + } +} + +/////// TypeApply /////////////////////////////////////////////////////////////// + +type TypeApply = TypeApplyImpl +final class TypeApplyImpl(val underlying: tpd.TypeApply) extends TermImpl, pub.TypeApply { + override def fun: Term = TreeImpl(underlying.fun).asInstanceOf[Term] + override def args: List[TypeTree] = underlying.args.map(TreeImpl(_).asInstanceOf[TypeTree]) +} +object TypeApplyImpl { + object Module extends pub.TypeApply.Module { + override def apply(fun: pub.Term, args: List[pub.TypeTree]): pub.TypeApply = ??? + override def make(fun: pub.Term, args: List[pub.TypeTree]): pub.TypeApply = ??? + } +} + +/////// Super /////////////////////////////////////////////////////////////// + +type Super = SuperImpl +final class SuperImpl(val underlying: tpd.Super) extends TermImpl, pub.Super { + override def qualifier: Term = TreeImpl(underlying.qual).asInstanceOf[Term] + override def id: Option[String] = TreeImpl.optional(underlying.mix).map(_.name.toString) + override def idPos: Position = PositionImpl(underlying.mix.sourcePos) +} +object SuperImpl { + object Module extends pub.Super.Module { + override def apply(qual: pub.Term, mix: Option[String]): pub.Super = ??? + override def make(qual: pub.Term, mix: Option[String]): pub.Super = ??? + } +} + +/////// Typed /////////////////////////////////////////////////////////////// + +type Typed = TypedImpl +final class TypedImpl(val underlying: tpd.Typed) extends TermImpl, pub.Typed { + // Typed extends Term AND TypedOrTest. + // TermImpl is a trait. TypedOrTestImpl is a trait. + // I need to mix in TypedOrTestImpl as well? No, TermImpl covers TreeImpl. + // But TypedOrTest adds `tree` method which `Typed` might not have? + // `Typed` has `expr` which corresponds to `tree` in TypedOrTest. + // I need to check `Typed` definition in Tree.scala. + // `trait Typed ... extends Term with TypedOrTest { def expr: Term; def tpt: TypeTree }` + // `TypedOrTest` has `def tree: Tree; def tpt: TypeTree`. + // So `Typed` must implement `tree`. + override def expr: Term = TreeImpl(underlying.expr).asInstanceOf[Term] + override def tpt: TypeTree = TreeImpl(underlying.tpt).asInstanceOf[TypeTree] + override def tree: Tree = TreeImpl(underlying.expr) // From TypedOrTest +} +object TypedImpl { + object Module extends pub.Typed.Module { + override def apply(expr: pub.Term, tpt: pub.TypeTree): pub.Typed = ??? + override def make(expr: pub.Term, tpt: pub.TypeTree): pub.Typed = ??? + } +} + +/////// Assign /////////////////////////////////////////////////////////////// + +type Assign = AssignImpl +final class AssignImpl(val underlying: tpd.Assign) extends TermImpl, pub.Assign { + override def lhs: Term = TreeImpl(underlying.lhs).asInstanceOf[Term] + override def rhs: Term = TreeImpl(underlying.rhs).asInstanceOf[Term] +} +object AssignImpl { + object Module extends pub.Assign.Module { + override def apply(lhs: pub.Term, rhs: pub.Term): pub.Assign = ??? + override def make(lhs: pub.Term, rhs: pub.Term): pub.Assign = ??? + } +} + +/////// Block /////////////////////////////////////////////////////////////// + +type Block = BlockImpl +final class BlockImpl(val underlying: tpd.Block) extends TermImpl, pub.Block { + override def statements: List[Statement] = underlying.stats.map(TreeImpl(_).asInstanceOf[Statement]) + override def expr: Term = TreeImpl(underlying.expr).asInstanceOf[Term] +} +object BlockImpl { + object Module extends pub.Block.Module { + override def apply(stats: List[pub.Statement], expr: pub.Term): pub.Block = ??? + override def make(stats: List[pub.Statement], expr: pub.Term): pub.Block = ??? + } +} + +/////// Closure /////////////////////////////////////////////////////////////// + +type Closure = ClosureImpl +final class ClosureImpl(val underlying: tpd.Closure) extends TermImpl, pub.Closure { + override def meth: Term = TreeImpl(underlying.meth).asInstanceOf[Term] + override def tpeOpt: Option[TypeRepr] = TreeImpl.optional(underlying.tpt).map(t => TypeReprImpl(t.tpe)) +} +object ClosureImpl { + object Module extends pub.Closure.Module { + override def apply(meth: pub.Term, tpe: Option[pub.TypeRepr]): pub.Closure = ??? + override def make(meth: pub.Term, tpe: Option[pub.TypeRepr]): pub.Closure = ??? + } +} + +/////// Lambda /////////////////////////////////////////////////////////////// + +object LambdaImpl { + object Module extends pub.Lambda.Module { + override def unapply(tree: pub.Block): Option[(List[pub.ValDef], pub.Term)] = ??? + override def apply(owner: pub.Symbol, tpe: pub.MethodType, rhsFn: (pub.Symbol, List[pub.Tree]) => pub.Tree): pub.Block = ??? + override def make(owner: pub.Symbol, tpe: pub.MethodType, rhsFn: (pub.Symbol, List[pub.Tree]) => pub.Tree): pub.Block = ??? + } +} + +/////// If /////////////////////////////////////////////////////////////// + +type If = IfImpl +final class IfImpl(val underlying: tpd.If) extends TermImpl, pub.If { + override def cond: Term = TreeImpl(underlying.cond).asInstanceOf[Term] + override def thenp: Term = TreeImpl(underlying.thenp).asInstanceOf[Term] + override def elsep: Term = TreeImpl(underlying.elsep).asInstanceOf[Term] + override def isInline: Boolean = underlying.isInline +} +object IfImpl { + object Module extends pub.If.Module { + override def apply(cond: pub.Term, thenp: pub.Term, elsep: pub.Term): pub.If = ??? + override def make(cond: pub.Term, thenp: pub.Term, elsep: pub.Term): pub.If = ??? + } +} + +/////// Match /////////////////////////////////////////////////////////////// + +type Match = MatchImpl +final class MatchImpl(val underlying: tpd.Match) extends TermImpl, pub.Match { + override def scrutinee: Term = TreeImpl(underlying.selector).asInstanceOf[Term] + override def cases: List[CaseDef] = underlying.cases.map(CaseDefImpl(_)) + override def isInline: Boolean = underlying.isInline +} +object MatchImpl { + object Module extends pub.Match.Module { + override def apply(selector: pub.Term, cases: List[pub.CaseDef]): pub.Match = ??? + override def make(selector: pub.Term, cases: List[pub.CaseDef]): pub.Match = ??? + } +} + +/////// SummonFrom /////////////////////////////////////////////////////////////// + +type SummonFrom = SummonFromImpl +final class SummonFromImpl(val underlying: tpd.Match) extends TermImpl, pub.SummonFrom { + override def cases: List[CaseDef] = underlying.cases.map(CaseDefImpl(_)) +} +object SummonFromImpl { + object Module extends pub.SummonFrom.Module { + override def apply(cases: List[pub.CaseDef]): pub.SummonFrom = ??? + override def make(cases: List[pub.CaseDef]): pub.SummonFrom = ??? + } +} + +/////// Try /////////////////////////////////////////////////////////////// + +type Try = TryImpl +final class TryImpl(val underlying: tpd.Try) extends TermImpl, pub.Try { + override def body: Term = TreeImpl(underlying.expr).asInstanceOf[Term] + override def cases: List[CaseDef] = underlying.cases.map(CaseDefImpl(_)) + override def finalizer: Option[Term] = TreeImpl.optional(underlying.finalizer).map(TreeImpl(_).asInstanceOf[Term]) +} +object TryImpl { + object Module extends pub.Try.Module { + override def apply(expr: pub.Term, cases: List[pub.CaseDef], finalizer: Option[pub.Term]): pub.Try = ??? + override def make(expr: pub.Term, cases: List[pub.CaseDef], finalizer: Option[pub.Term]): pub.Try = ??? + } +} + +/////// Return /////////////////////////////////////////////////////////////// + +type Return = ReturnImpl +final class ReturnImpl(val underlying: tpd.Return) extends TermImpl, pub.Return { + override def expr: Term = TreeImpl(underlying.expr).asInstanceOf[Term] + override def from: Symbol = SymbolImpl(underlying.from.symbol) +} +object ReturnImpl { + object Module extends pub.Return.Module { + override def apply(expr: pub.Term, from: pub.Symbol): pub.Return = ??? + override def make(expr: pub.Term, from: pub.Symbol): pub.Return = ??? + } +} + +/////// Repeated /////////////////////////////////////////////////////////////// + +type Repeated = RepeatedImpl +final class RepeatedImpl(val underlying: tpd.SeqLiteral) extends TermImpl, pub.Repeated { + override def elems: List[Term] = underlying.elems.map(TreeImpl(_).asInstanceOf[Term]) + override def elemtpt: TypeTree = TreeImpl(underlying.elemtpt).asInstanceOf[TypeTree] +} +object RepeatedImpl { + object Module extends pub.Repeated.Module { + override def apply(elems: List[pub.Term], tpt: pub.TypeTree): pub.Repeated = ??? + override def make(elems: List[pub.Term], tpt: pub.TypeTree): pub.Repeated = ??? + } +} + +/////// Inlined /////////////////////////////////////////////////////////////// + +type Inlined = InlinedImpl +final class InlinedImpl(val underlying: tpd.Inlined) extends TermImpl, pub.Inlined { + override def call: Option[Tree] = TreeImpl.optional(underlying.call).map(TreeImpl(_)) + override def bindings: List[Definition] = underlying.bindings.map(TreeImpl(_).asInstanceOf[Definition]) + override def body: Term = TreeImpl(underlying.expansion).asInstanceOf[Term] +} +object InlinedImpl { + object Module extends pub.Inlined.Module { + override def apply(call: Option[pub.Tree], bindings: List[pub.Definition], expansion: pub.Term): pub.Inlined = ??? + override def make(call: Option[pub.Tree], bindings: List[pub.Definition], expansion: pub.Term): pub.Inlined = ??? + } +} + +/////// SelectOuter /////////////////////////////////////////////////////////////// + +type SelectOuter = SelectOuterImpl +final class SelectOuterImpl(val underlying: tpd.Select) extends TermImpl, pub.SelectOuter { + override def qualifier: Term = TreeImpl(underlying.qualifier).asInstanceOf[Term] + override def name: String = underlying.name.toString + override def level: Int = + val NameKinds.OuterSelectName(_, levels) = underlying.name: @unchecked + levels +} +object SelectOuterImpl { + object Module extends pub.SelectOuter.Module { + override def apply(qualifier: pub.Term, name: String, levels: Int): pub.SelectOuter = ??? + override def make(qualifier: pub.Term, name: String, levels: Int): pub.SelectOuter = ??? + } +} + +/////// While /////////////////////////////////////////////////////////////// + +type While = WhileImpl +final class WhileImpl(val underlying: tpd.WhileDo) extends TermImpl, pub.While { + override def cond: Term = TreeImpl(underlying.cond).asInstanceOf[Term] + override def body: Term = TreeImpl(underlying.body).asInstanceOf[Term] +} +object WhileImpl { + object Module extends pub.While.Module { + override def apply(cond: pub.Term, body: pub.Term): pub.While = ??? + override def make(cond: pub.Term, body: pub.Term): pub.While = ??? + } +} + +/////// TypedOrTest /////////////////////////////////////////////////////////////// + +type TypedOrTest = pub.TypedOrTest & TypedOrTestImpl +sealed trait TypedOrTestImpl extends TreeImpl { _self: pub.TypedOrTest => + override val underlying: tpd.Typed + override def tree: Tree = TreeImpl(underlying.expr) + override def tpt: TypeTree = TreeImpl(underlying.tpt).asInstanceOf[TypeTree] +} +object TypedOrTestImpl { + object Module extends pub.TypedOrTest.Module { + override def apply(expr: pub.Tree, tpt: pub.TypeTree): pub.TypedOrTest = ??? + override def make(expr: pub.Tree, tpt: pub.TypeTree): pub.TypedOrTest = ??? + } +} + +/////// TypeTree /////////////////////////////////////////////////////////////// + +type TypeTree = pub.TypeTree & TypeTreeImpl +sealed trait TypeTreeImpl extends TreeImpl { _self: pub.TypeTree => + override def tpe: TypeRepr = TypeReprImpl(underlying.tpe.stripTypeVar) +} +object TypeTreeImpl { + object Module extends pub.TypeTree.Module { + override def of[T <: AnyKind](using Type[T]): pub.TypeTree = ??? + override def ref(typeSymbol: pub.Symbol): pub.TypeTree = ??? + } +} + +/////// Inferred /////////////////////////////////////////////////////////////// + +type Inferred = InferredImpl +final class InferredImpl(val underlying: tpd.TypeTree) extends TypeTreeImpl, pub.Inferred +object InferredImpl { + object Module extends pub.Inferred.Module { + override def apply(tpe: pub.TypeRepr): pub.Inferred = ??? + override def make(tpe: pub.TypeRepr): pub.Inferred = ??? + } +} + +/////// TypeIdent /////////////////////////////////////////////////////////////// + +type TypeIdent = TypeIdentImpl +final class TypeIdentImpl(val underlying: tpd.Ident) extends TypeTreeImpl, pub.TypeIdent { + override def name: String = underlying.name.toString +} +object TypeIdentImpl { + object Module extends pub.TypeIdent.Module { + override def apply(sym: pub.Symbol): pub.TypeTree = ??? + override def make(sym: pub.Symbol): pub.TypeTree = ??? + } +} + +/////// TypeSelect /////////////////////////////////////////////////////////////// + +type TypeSelect = TypeSelectImpl +final class TypeSelectImpl(val underlying: tpd.Select) extends TypeTreeImpl, pub.TypeSelect { + override def qualifier: Term = TreeImpl(underlying.qualifier).asInstanceOf[Term] + override def name: String = underlying.name.toString +} +object TypeSelectImpl { + object Module extends pub.TypeSelect.Module { + override def apply(qualifier: pub.Term, name: String): pub.TypeSelect = ??? + override def make(qualifier: pub.Term, name: String): pub.TypeSelect = ??? + } +} + +/////// TypeProjection /////////////////////////////////////////////////////////////// + +type TypeProjection = TypeProjectionImpl +final class TypeProjectionImpl(val underlying: tpd.Select) extends TypeTreeImpl, pub.TypeProjection { + override def qualifier: TypeTree = TreeImpl(underlying.qualifier).asInstanceOf[TypeTree] + override def name: String = underlying.name.toString +} +object TypeProjectionImpl { + object Module extends pub.TypeProjection.Module { + override def apply(qualifier: pub.TypeTree, name: String): pub.TypeProjection = ??? + override def make(qualifier: pub.TypeTree, name: String): pub.TypeProjection = ??? + } +} + +/////// Singleton /////////////////////////////////////////////////////////////// + +type Singleton = SingletonImpl +final class SingletonImpl(val underlying: tpd.SingletonTypeTree) extends TypeTreeImpl, pub.Singleton { + override def ref: Term = TreeImpl(underlying.ref).asInstanceOf[Term] +} +object SingletonImpl { + object Module extends pub.Singleton.Module { + override def apply(ref: pub.Term): pub.Singleton = ??? + override def make(ref: pub.Term): pub.Singleton = ??? + } +} + +/////// Refined /////////////////////////////////////////////////////////////// + +type Refined = RefinedImpl +final class RefinedImpl(val underlying: tpd.RefinedTypeTree) extends TypeTreeImpl, pub.Refined { + override def tpt: TypeTree = TreeImpl(underlying.tpt).asInstanceOf[TypeTree] + override def refinements: List[Definition] = underlying.refinements.map(TreeImpl(_).asInstanceOf[Definition]) +} +object RefinedImpl { + object Module extends pub.Refined.Module { + override def apply(tpt: pub.TypeTree, refinements: List[pub.Definition], refineCls: pub.Symbol): pub.Refined = ??? + override def make(tpt: pub.TypeTree, refinements: List[pub.Definition], refineCls: pub.Symbol): pub.Refined = ??? + } +} + +/////// Applied /////////////////////////////////////////////////////////////// + +type Applied = AppliedImpl +final class AppliedImpl(val underlying: tpd.AppliedTypeTree) extends TypeTreeImpl, pub.Applied { + override def tpt: TypeTree = TreeImpl(underlying.tpt).asInstanceOf[TypeTree] + override def args: List[Tree] = underlying.args.map(TreeImpl(_)) +} +object AppliedImpl { + object Module extends pub.Applied.Module { + override def apply(tpt: pub.TypeTree, args: List[pub.Tree]): pub.Applied = ??? + override def make(tpt: pub.TypeTree, args: List[pub.Tree]): pub.Applied = ??? + } +} + +/////// Annotated /////////////////////////////////////////////////////////////// + +type Annotated = AnnotatedImpl +final class AnnotatedImpl(val underlying: tpd.Annotated) extends TypeTreeImpl, pub.Annotated { + override def arg: TypeTree = TreeImpl(underlying.arg).asInstanceOf[TypeTree] + override def annotation: Term = TreeImpl(underlying.annot).asInstanceOf[Term] +} +object AnnotatedImpl { + object Module extends pub.Annotated.Module { + override def apply(arg: pub.TypeTree, annotation: pub.Term): pub.Annotated = ??? + override def make(arg: pub.TypeTree, annotation: pub.Term): pub.Annotated = ??? + } +} + +/////// MatchTypeTree /////////////////////////////////////////////////////////////// + +type MatchTypeTree = MatchTypeTreeImpl +final class MatchTypeTreeImpl(val underlying: tpd.MatchTypeTree) extends TypeTreeImpl, pub.MatchTypeTree { + override def bound: Option[TypeTree] = TreeImpl.optional(underlying.bound).map(TreeImpl(_).asInstanceOf[TypeTree]) + override def selector: TypeTree = TreeImpl(underlying.selector).asInstanceOf[TypeTree] + override def cases: List[TypeCaseDef] = underlying.cases.map(TypeCaseDefImpl(_)) +} +object MatchTypeTreeImpl { + object Module extends pub.MatchTypeTree.Module { + override def apply(bound: Option[pub.TypeTree], selector: pub.TypeTree, cases: List[pub.TypeCaseDef]): pub.MatchTypeTree = ??? + override def make(bound: Option[pub.TypeTree], selector: pub.TypeTree, cases: List[pub.TypeCaseDef]): pub.MatchTypeTree = ??? + } +} + +/////// ByName /////////////////////////////////////////////////////////////// + +type ByName = ByNameImpl +final class ByNameImpl(val underlying: tpd.ByNameTypeTree) extends TypeTreeImpl, pub.ByName { + override def result: TypeTree = TreeImpl(underlying.result).asInstanceOf[TypeTree] +} +object ByNameImpl { + object Module extends pub.ByName.Module { + override def apply(result: pub.TypeTree): pub.ByName = ??? + override def make(result: pub.TypeTree): pub.ByName = ??? + } +} + +/////// LambdaTypeTree /////////////////////////////////////////////////////////////// + +type LambdaTypeTree = LambdaTypeTreeImpl +final class LambdaTypeTreeImpl(val underlying: tpd.LambdaTypeTree) extends TypeTreeImpl, pub.LambdaTypeTree { + override def tparams: List[TypeDef] = underlying.tparams.map(TypeDefImpl(_)) + override def body: Tree = TreeImpl(underlying.body) +} +object LambdaTypeTreeImpl { + object Module extends pub.LambdaTypeTree.Module { + override def apply(tparams: List[pub.TypeDef], body: pub.Tree): pub.LambdaTypeTree = ??? + override def make(tparams: List[pub.TypeDef], body: pub.Tree): pub.LambdaTypeTree = ??? + } +} + +/////// TypeBind /////////////////////////////////////////////////////////////// + +type TypeBind = TypeBindImpl +final class TypeBindImpl(val underlying: tpd.Bind) extends TypeTreeImpl, pub.TypeBind { + override def name: String = underlying.name.toString + override def body: Tree = TreeImpl(underlying.body) +} +object TypeBindImpl { + object Module extends pub.TypeBind.Module {} +} + +/////// TypeBlock /////////////////////////////////////////////////////////////// + +type TypeBlock = TypeBlockImpl +final class TypeBlockImpl(val underlying: tpd.Block) extends TypeTreeImpl, pub.TypeBlock { + override def aliases: List[TypeDef] = underlying.stats.map(TreeImpl(_).asInstanceOf[TypeDef]) + override def tpt: TypeTree = TreeImpl(underlying.expr).asInstanceOf[TypeTree] +} +object TypeBlockImpl { + object Module extends pub.TypeBlock.Module { + override def apply(aliases: List[pub.TypeDef], tpt: pub.TypeTree): pub.TypeBlock = ??? + override def make(aliases: List[pub.TypeDef], tpt: pub.TypeTree): pub.TypeBlock = ??? + } +} + +/////// TypeBoundsTree /////////////////////////////////////////////////////////////// + +type TypeBoundsTree = TypeBoundsTreeImpl +final class TypeBoundsTreeImpl(val underlying: tpd.Tree) extends TreeImpl, pub.TypeBoundsTree { + override def tpe: TypeBounds = TypeBoundsImpl(underlying.tpe.asInstanceOf[dotc.core.Types.TypeBounds]) + override def low: TypeTree = underlying match + case self: tpd.TypeBoundsTree => TreeImpl(self.lo).asInstanceOf[TypeTree] + case self: tpd.TypeTree => ??? // Cannot implement without Context to makeTypeDef + override def hi: TypeTree = underlying match + case self: tpd.TypeBoundsTree => TreeImpl(self.hi).asInstanceOf[TypeTree] + case self: tpd.TypeTree => ??? // Cannot implement without Context to makeTypeDef +} +object TypeBoundsTreeImpl { + object Module extends pub.TypeBoundsTree.Module { + override def apply(low: pub.TypeTree, hi: pub.TypeTree): pub.TypeBoundsTree = ??? + override def make(low: pub.TypeTree, hi: pub.TypeTree): pub.TypeBoundsTree = ??? + } +} + +/////// WildcardTypeTree /////////////////////////////////////////////////////////////// + +type WildcardTypeTree = WildcardTypeTreeImpl +final class WildcardTypeTreeImpl(val underlying: tpd.Ident) extends TreeImpl, pub.WildcardTypeTree { + override def tpe: TypeRepr = TypeReprImpl(underlying.tpe.stripTypeVar) +} +object WildcardTypeTreeImpl { + object Module extends pub.WildcardTypeTree.Module { + override def apply(tpe: pub.TypeRepr): pub.WildcardTypeTree = ??? + override def make(tpe: pub.TypeRepr): pub.WildcardTypeTree = ??? + } +} + +/////// CaseDef /////////////////////////////////////////////////////////////// + +type CaseDef = CaseDefImpl +final class CaseDefImpl(val underlying: tpd.CaseDef) extends TreeImpl, pub.CaseDef { + override def pattern: Tree = TreeImpl(underlying.pat) + override def guard: Option[Term] = TreeImpl.optional(underlying.guard).map(TreeImpl(_).asInstanceOf[Term]) + override def rhs: Term = TreeImpl(underlying.body).asInstanceOf[Term] +} +object CaseDefImpl { + object Module extends pub.CaseDef.Module { + override def apply(pattern: pub.Tree, guard: Option[pub.Term], rhs: pub.Term): pub.CaseDef = ??? + override def make(pattern: pub.Tree, guard: Option[pub.Term], rhs: pub.Term): pub.CaseDef = ??? + } +} + +/////// TypeCaseDef /////////////////////////////////////////////////////////////// + +type TypeCaseDef = TypeCaseDefImpl +final class TypeCaseDefImpl(val underlying: tpd.CaseDef) extends TreeImpl, pub.TypeCaseDef { + override def pattern: TypeTree = TreeImpl(underlying.pat).asInstanceOf[TypeTree] + override def rhs: TypeTree = TreeImpl(underlying.body).asInstanceOf[TypeTree] +} +object TypeCaseDefImpl { + object Module extends pub.TypeCaseDef.Module { + override def apply(pattern: pub.TypeTree, rhs: pub.TypeTree): pub.TypeCaseDef = ??? + override def make(pattern: pub.TypeTree, rhs: pub.TypeTree): pub.TypeCaseDef = ??? + } +} + +/////// Bind /////////////////////////////////////////////////////////////// + +type Bind = BindImpl +final class BindImpl(val underlying: tpd.Bind) extends TreeImpl, pub.Bind { + override def name: String = underlying.name.toString + override def pattern: Tree = TreeImpl(underlying.body) +} +object BindImpl { + object Module extends pub.Bind.Module { + override def apply(sym: pub.Symbol, pattern: pub.Tree): pub.Bind = ??? + override def make(sym: pub.Symbol, pattern: pub.Tree): pub.Bind = ??? + } +} + +/////// Unapply /////////////////////////////////////////////////////////////// + +type Unapply = UnapplyImpl +final class UnapplyImpl(val underlying: tpd.Tree) extends TreeImpl, pub.Unapply { + override def fun: Term = + val t = underlying match + case self: tpd.UnApply => self.fun + case self: tpd.QuotePattern => dotc.quoted.QuotePatterns.encode(self).fun + TreeImpl(t).asInstanceOf[Term] + + override def implicits: List[Term] = + val ts = underlying match + case self: tpd.UnApply => self.implicits + case self: tpd.QuotePattern => dotc.quoted.QuotePatterns.encode(self).implicits + ts.map(TreeImpl(_).asInstanceOf[Term]) + + override def patterns: List[Tree] = + val ps = underlying match + case self: tpd.UnApply => self.patterns + case self: tpd.QuotePattern => dotc.quoted.QuotePatterns.encode(self).patterns + val effective = ps match + case patterns0 :+ dotc.ast.Trees.SeqLiteral(elems, _) => patterns0 ::: elems + case _ => ps + effective.map(TreeImpl(_)) +} +object UnapplyImpl { + object Module extends pub.Unapply.Module { + override def apply(fun: pub.Term, implicits: List[pub.Term], patterns: List[pub.Tree]): pub.Unapply = ??? + override def make(fun: pub.Term, implicits: List[pub.Term], patterns: List[pub.Tree]): pub.Unapply = ??? + } +} + +/////// Alternatives /////////////////////////////////////////////////////////////// + +type Alternatives = AlternativesImpl +final class AlternativesImpl(val underlying: tpd.Alternative) extends TreeImpl, pub.Alternatives { + override def patterns: List[Tree] = underlying.trees.map(TreeImpl(_)) +} +object AlternativesImpl { + object Module extends pub.Alternatives.Module { + override def apply(patterns: List[pub.Tree]): pub.Alternatives = ??? + override def make(patterns: List[pub.Tree]): pub.Alternatives = ??? + } +} diff --git a/compiler/src/scala/quoted/compiletime/internal/TypeReprImpl.scala b/compiler/src/scala/quoted/compiletime/internal/TypeReprImpl.scala new file mode 100644 index 000000000000..46e18e402262 --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/TypeReprImpl.scala @@ -0,0 +1,455 @@ +package scala.quoted.compiletime.internal + +import dotty.tools.dotc +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.core.Contexts.* +import scala.quoted.compiletime.internal.casting.* +import scala.quoted.compiletime as pub + +/////// TypeRepr /////////////////////////////////////////////////////////////// + +type TypeRepr = pub.TypeRepr & TypeReprImpl +sealed trait TypeReprImpl(using val ctx: Context) { _self: pub.TypeRepr => + + val underlying: dotc.core.Types.Type + + override final def toString: String = underlying.toString + override final def equals(that: Any): Boolean = that.asInstanceOf[Matchable] match + case that: TypeReprImpl => this.underlying == that.underlying + case _ => false + + def asType: scala.quoted.Type[?] = + new scala.quoted.runtime.impl.TypeImpl(tpd.TypeTree(underlying), scala.quoted.runtime.impl.SpliceScope.getCurrent) + + def =:=(that: pub.TypeRepr): Boolean = underlying =:= that.cast.underlying + def <:<(that: pub.TypeRepr): Boolean = underlying <:< that.cast.underlying + def widen: TypeRepr = TypeReprImpl(underlying.widen) + def widenTermRefByName: TypeRepr = + val res = underlying.widenTermRefExpr match + case dotc.core.Types.ClassInfo(prefix, sym, _, _, _) => prefix.select(sym) + case other => other + TypeReprImpl(res) + def widenByName: TypeRepr = TypeReprImpl(underlying.widenExpr) + def dealias: TypeRepr = TypeReprImpl(underlying.dealias) + def dealiasKeepOpaques: TypeRepr = TypeReprImpl(underlying.dealiasKeepOpaques) + def simplified: TypeRepr = TypeReprImpl(underlying.simplified) + def classSymbol: Option[SymbolImpl] = + if underlying.classSymbol.exists then Some(SymbolImpl(underlying.classSymbol.asClass)) + else None + def typeSymbol: SymbolImpl = SymbolImpl(underlying.typeSymbol) + def termSymbol: SymbolImpl = SymbolImpl(underlying.termSymbol) + def isSingleton: Boolean = underlying.isSingleton + def memberType(member: pub.Symbol): TypeRepr = + // we replace thisTypes here to avoid resolving otherwise unstable prefixes into Nothing + val memberInfo = + if underlying.typeSymbol.isClassDef then member.cast.symbol.info.substThis(underlying.classSymbol.asClass, underlying) + else member.cast.symbol.info + TypeReprImpl(memberInfo.asSeenFrom(underlying, member.cast.symbol.owner)) + + def baseClasses: List[SymbolImpl] = underlying.baseClasses.map(SymbolImpl(_)) + def baseType(cls: pub.Symbol): TypeRepr = TypeReprImpl(underlying.baseType(cls.cast.symbol)) + def derivesFrom(cls: pub.Symbol): Boolean = underlying.derivesFrom(cls.cast.symbol) + def isFunctionType: Boolean = + dotc.core.Symbols.defn.isFunctionNType(underlying) + def isContextFunctionType: Boolean = + dotc.core.Symbols.defn.isContextFunctionType(underlying) + def isErasedFunctionType: Boolean = + underlying match + case dotc.core.Symbols.defn.PolyFunctionOf(mt) => + mt match + case mt: dotc.core.Types.MethodType => mt.hasErasedParams + case dotc.core.Types.PolyType(_, _, mt1) => mt1.hasErasedParams + case _ => false + def isDependentFunctionType: Boolean = + val tpNoRefinement = underlying.dropDependentRefinement + tpNoRefinement != underlying + && dotc.core.Symbols.defn.isNonRefinedFunction(tpNoRefinement) + def isTupleN: Boolean = + dotc.core.Symbols.defn.isTupleNType(underlying) + def select(sym: pub.Symbol): TypeRepr = TypeReprImpl(underlying.select(sym.cast.symbol)) + def appliedTo(targ: pub.TypeRepr): TypeRepr = + TypeReprImpl(dotc.core.Types.decorateTypeApplications(underlying).appliedTo(targ.cast.underlying)) + def appliedTo(targs: List[pub.TypeRepr]): TypeRepr = + TypeReprImpl(dotc.core.Types.decorateTypeApplications(underlying).appliedTo(targs.map(_.cast.underlying))) + def substituteTypes(from: List[pub.Symbol], to: List[pub.TypeRepr]): TypeRepr = + TypeReprImpl(underlying.subst(from.map(_.cast.symbol), to.map(_.cast.underlying))) + + def typeArgs: List[TypeRepr] = underlying match + case dotc.core.Types.AppliedType(_, args) => args.map(TypeReprImpl(_)) + case dotc.core.Types.AnnotatedType(parent, _) => TypeReprImpl(parent).typeArgs + case dotc.core.Types.FlexibleType(underlying) => TypeReprImpl(underlying).typeArgs + case _ => List.empty + +} +object TypeReprImpl { + + def apply(t: dotc.core.Types.Type)(using Context): TypeReprImpl = t match { + case t: dotc.core.Types.TermRef => new TermRefImpl(t) + case t: dotc.core.Types.TypeRef => new TypeRefImpl(t) + case t: dotc.core.Types.ConstantType => new ConstantTypeImpl(t) + case t: dotc.core.Types.SuperType => new SuperTypeImpl(t) + case t: dotc.core.Types.RefinedType => new RefinementImpl(t) + case t: dotc.core.Types.AppliedType if t.tycon.isRef(dotc.core.Symbols.defn.MatchCaseClass) => new MatchCaseImpl(t) + case t: dotc.core.Types.AppliedType => new AppliedTypeImpl(t) + case t: dotc.core.Types.AnnotatedType => new AnnotatedTypeImpl(t) + case t: dotc.core.Types.AndType => new AndTypeImpl(t) + case t: dotc.core.Types.OrType => new OrTypeImpl(t) + case t: dotc.core.Types.MatchType => new MatchTypeImpl(t) + case t: dotc.core.Types.ExprType => new ByNameTypeImpl(t) + case t: dotc.core.Types.ParamRef => new ParamRefImpl(t) + case t: dotc.core.Types.ThisType => new ThisTypeImpl(t) + case t: dotc.core.Types.RecThis => new RecursiveThisImpl(t) + case t: dotc.core.Types.RecType => new RecursiveTypeImpl(t) + case t: dotc.core.Types.MethodType => new MethodTypeImpl(t) + case t: dotc.core.Types.PolyType => new PolyTypeImpl(t) + case t: dotc.core.Types.HKTypeLambda => new TypeLambdaImpl(t) + case t: dotc.core.Types.TypeBounds => new TypeBoundsImpl(t) + case t: dotc.core.Types.NoPrefix.type => new NoPrefixImpl(t) + case t: dotc.core.Types.FlexibleType => new FlexibleTypeImpl(t) + case _ => throw new MatchError(t) + } + + object Module extends pub.TypeRepr.Module { + override def of[T <: AnyKind](using scala.quoted.Type[T]): pub.TypeRepr = ??? + override def typeConstructorOf(clazz: Class[?]): pub.TypeRepr = ??? + } +} + +/////// NamedType /////////////////////////////////////////////////////////////// + +type NamedType = pub.NamedType & NamedTypeImpl +sealed trait NamedTypeImpl(using Context) extends TypeReprImpl { _self: pub.NamedType => + + override val underlying: dotc.core.Types.NamedType + + def qualifier: TypeRepr = TypeReprImpl(underlying.prefix.widenSkolem) + def name: String = underlying.name.toString + +} +object NamedTypeImpl { + object Module extends pub.NamedType.Module {} +} + +/////// TermRef /////////////////////////////////////////////////////////////// + +type TermRef = TermRefImpl // TODO (KR) : QuotesImpl.scala used only `NamedType` here, was that a mistake or intentional... +final class TermRefImpl(val underlying: dotc.core.Types.TermRef)(using Context) extends NamedTypeImpl, pub.TermRef +object TermRefImpl { + object Module extends pub.TermRef.Module { + override def apply(qual: pub.TypeRepr, name: String): pub.TermRef = ??? + override def make(qual: pub.TypeRepr, name: String): pub.TermRef = ??? + } +} + +/////// TypeRef /////////////////////////////////////////////////////////////// + +type TypeRef = TypeRefImpl +final class TypeRefImpl(val underlying: dotc.core.Types.TypeRef)(using Context) extends NamedTypeImpl, pub.TypeRef { + def isOpaqueAlias: Boolean = underlying.symbol.isOpaqueAlias + def translucentSuperType: TypeRepr = TypeReprImpl(underlying.translucentSuperType) +} +object TypeRefImpl { + object Module extends pub.TypeRef.Module {} +} + +/////// ConstantType /////////////////////////////////////////////////////////////// + +type ConstantType = ConstantTypeImpl +final class ConstantTypeImpl(val underlying: dotc.core.Types.ConstantType)(using Context) extends TypeReprImpl, pub.ConstantType { + override def constant: ConstantImpl = ConstantImpl(underlying.value) +} +object ConstantTypeImpl { + object Module extends pub.ConstantType.Module { + override def apply(x: pub.Constant): pub.ConstantType = ??? + override def make(x: pub.Constant): pub.ConstantType = ??? + } +} + +/////// SuperType /////////////////////////////////////////////////////////////// + +type SuperType = SuperTypeImpl +final class SuperTypeImpl(val underlying: dotc.core.Types.SuperType)(using Context) extends TypeReprImpl, pub.SuperType { + override def thistpe: TypeRepr = TypeReprImpl(underlying.thistpe) + override def supertpe: TypeRepr = TypeReprImpl(underlying.supertpe) +} +object SuperTypeImpl { + object Module extends pub.SuperType.Module { + override def apply(thistpe: pub.TypeRepr, supertpe: pub.TypeRepr): pub.SuperType = ??? + override def make(thistpe: pub.TypeRepr, supertpe: pub.TypeRepr): pub.SuperType = ??? + } +} + +/////// Refinement /////////////////////////////////////////////////////////////// + +type Refinement = RefinementImpl +final class RefinementImpl(val underlying: dotc.core.Types.RefinedType)(using Context) extends TypeReprImpl, pub.Refinement { + override def parent: TypeRepr = TypeReprImpl(underlying.parent) + override def name: String = underlying.refinedName.toString + override def info: TypeRepr = TypeReprImpl(underlying.refinedInfo) +} +object RefinementImpl { + object Module extends pub.Refinement.Module { + override def apply(parent: pub.TypeRepr, name: String, info: pub.TypeRepr): pub.Refinement = ??? + override def make(parent: pub.TypeRepr, name: String, info: pub.TypeRepr): pub.Refinement = ??? + } +} + +/////// AppliedType /////////////////////////////////////////////////////////////// + +type AppliedType = AppliedTypeImpl +final class AppliedTypeImpl(val underlying: dotc.core.Types.AppliedType)(using Context) extends TypeReprImpl, pub.AppliedType { + override def tycon: TypeRepr = TypeReprImpl(underlying.tycon) + override def args: List[TypeRepr] = underlying.args.map(TypeReprImpl(_)) +} +object AppliedTypeImpl { + object Module extends pub.AppliedType.Module { + override def apply(tycon: pub.TypeRepr, args: List[pub.TypeRepr]): pub.AppliedType = ??? + override def make(tycon: pub.TypeRepr, args: List[pub.TypeRepr]): pub.AppliedType = ??? + } +} + +/////// AnnotatedType /////////////////////////////////////////////////////////////// + +type AnnotatedType = AnnotatedTypeImpl +final class AnnotatedTypeImpl(val underlying: dotc.core.Types.AnnotatedType)(using Context) extends TypeReprImpl, pub.AnnotatedType { + override def underlying: TypeRepr = TypeReprImpl(underlying.underlying) +} +object AnnotatedTypeImpl { + object Module extends pub.AnnotatedType.Module {} +} + +/////// AndOrType /////////////////////////////////////////////////////////////// + +type AndOrType = pub.AndOrType & AndOrTypeImpl +sealed trait AndOrTypeImpl(using Context) extends TypeReprImpl { _self: pub.AndOrType => + override val underlying: dotc.core.Types.AndOrType + def left: TypeRepr = TypeReprImpl(underlying.tp1) + def right: TypeRepr = TypeReprImpl(underlying.tp2) +} +object AndOrTypeImpl { + object Module extends pub.AndOrType.Module {} +} + +/////// AndType /////////////////////////////////////////////////////////////// + +type AndType = AndTypeImpl +final class AndTypeImpl(val underlying: dotc.core.Types.AndType)(using Context) extends AndOrTypeImpl, pub.AndType +object AndTypeImpl { + object Module extends pub.AndType.Module { + override def apply(lhs: pub.TypeRepr, rhs: pub.TypeRepr): pub.AndType = ??? + override def make(lhs: pub.TypeRepr, rhs: pub.TypeRepr): pub.AndType = ??? + } +} + +/////// OrType /////////////////////////////////////////////////////////////// + +type OrType = OrTypeImpl +final class OrTypeImpl(val underlying: dotc.core.Types.OrType)(using Context) extends AndOrTypeImpl, pub.OrType +object OrTypeImpl { + object Module extends pub.OrType.Module { + override def apply(lhs: pub.TypeRepr, rhs: pub.TypeRepr): pub.OrType = ??? + override def make(lhs: pub.TypeRepr, rhs: pub.TypeRepr): pub.OrType = ??? + } +} + +/////// MatchType /////////////////////////////////////////////////////////////// + +type MatchType = MatchTypeImpl +final class MatchTypeImpl(val underlying: dotc.core.Types.MatchType)(using Context) extends TypeReprImpl, pub.MatchType { + override def bound: TypeRepr = TypeReprImpl(underlying.bound) + override def scrutinee: TypeRepr = TypeReprImpl(underlying.scrutinee) + override def cases: List[TypeRepr] = underlying.cases.map(TypeReprImpl(_)) +} +object MatchTypeImpl { + object Module extends pub.MatchType.Module { + override def apply(bound: pub.TypeRepr, scrutinee: pub.TypeRepr, cases: List[pub.TypeRepr]): pub.MatchType = ??? + override def make(bound: pub.TypeRepr, scrutinee: pub.TypeRepr, cases: List[pub.TypeRepr]): pub.MatchType = ??? + } +} + +/////// ByNameType /////////////////////////////////////////////////////////////// + +type ByNameType = ByNameTypeImpl +final class ByNameTypeImpl(val underlying: dotc.core.Types.ExprType)(using Context) extends TypeReprImpl, pub.ByNameType { + override def underlying: TypeRepr = TypeReprImpl(underlying.resType) +} +object ByNameTypeImpl { + object Module extends pub.ByNameType.Module { + override def apply(underlying: pub.TypeRepr): pub.TypeRepr = ??? + override def make(underlying: pub.TypeRepr): pub.TypeRepr = ??? + } +} + +/////// ParamRef /////////////////////////////////////////////////////////////// + +type ParamRef = ParamRefImpl +final class ParamRefImpl(val underlying: dotc.core.Types.ParamRef)(using Context) extends TypeReprImpl, pub.ParamRef { + override def binder: TypeRepr = TypeReprImpl(underlying.binder) + override def paramNum: Int = underlying.paramNum +} +object ParamRefImpl { + object Module extends pub.ParamRef.Module {} +} + +/////// ThisType /////////////////////////////////////////////////////////////// + +type ThisType = ThisTypeImpl +final class ThisTypeImpl(val underlying: dotc.core.Types.ThisType)(using Context) extends TypeReprImpl, pub.ThisType { + override def tref: TypeRepr = TypeReprImpl(underlying.tref) +} +object ThisTypeImpl { + object Module extends pub.ThisType.Module {} +} + +/////// RecursiveThis /////////////////////////////////////////////////////////////// + +type RecursiveThis = RecursiveThisImpl +final class RecursiveThisImpl(val underlying: dotc.core.Types.RecThis)(using Context) extends TypeReprImpl, pub.RecursiveThis { + override def binder: RecursiveType = RecursiveTypeImpl(underlying.binder) +} +object RecursiveThisImpl { + object Module extends pub.RecursiveThis.Module {} +} + +/////// RecursiveType /////////////////////////////////////////////////////////////// + +type RecursiveType = RecursiveTypeImpl +final class RecursiveTypeImpl(val underlying: dotc.core.Types.RecType)(using Context) extends TypeReprImpl, pub.RecursiveType { + override def underlying: TypeRepr = TypeReprImpl(underlying.underlying) + override def recThis: RecursiveThis = RecursiveThisImpl(underlying.recThis) +} +object RecursiveTypeImpl { + object Module extends pub.RecursiveType.Module { + override def apply(parentExp: pub.RecursiveType => pub.TypeRepr): pub.RecursiveType = ??? + override def make(parentExp: pub.RecursiveType => pub.TypeRepr): pub.RecursiveType = ??? + } +} + +/////// LambdaType /////////////////////////////////////////////////////////////// + +type LambdaType = pub.LambdaType & LambdaTypeImpl +sealed trait LambdaTypeImpl(using Context) extends TypeReprImpl { _self: pub.LambdaType => + override val underlying: dotc.core.Types.LambdaType + def paramNames: List[String] = underlying.paramNames.map(_.toString) + def paramTypes: List[TypeRepr] = underlying.paramInfos.map(TypeReprImpl(_)) + def resType: TypeRepr = TypeReprImpl(underlying.resType) +} +object LambdaTypeImpl { + object Module extends pub.LambdaType.Module {} +} + +/////// MethodOrPoly /////////////////////////////////////////////////////////////// + +type MethodOrPoly = pub.MethodOrPoly & MethodOrPolyImpl +sealed trait MethodOrPolyImpl(using Context) extends LambdaTypeImpl { _self: pub.MethodOrPoly => } +object MethodOrPolyImpl { + object Module extends pub.MethodOrPoly.Module {} +} + +/////// MethodType /////////////////////////////////////////////////////////////// + +type MethodType = MethodTypeImpl +final class MethodTypeImpl(val underlying: dotc.core.Types.MethodType)(using Context) extends MethodOrPolyImpl, pub.MethodType { + override def isImplicit: Boolean = underlying.isImplicitMethod + override def isContextual: Boolean = underlying.isContextualMethod + override def methodTypeKind: pub.MethodTypeKind = + underlying.companion match + case dotc.core.Types.ContextualMethodType => pub.MethodTypeKind.Contextual + case dotc.core.Types.ImplicitMethodType => pub.MethodTypeKind.Implicit + case _ => pub.MethodTypeKind.Plain + + override def erasedParams: List[Boolean] = underlying.paramErasureStatuses + override def hasErasedParams: Boolean = underlying.hasErasedParams + override def param(idx: Int): TypeRepr = TypeReprImpl(underlying.newParamRef(idx)) +} +object MethodTypeImpl { + object Module extends pub.MethodType.Module { + override def apply(paramNames: List[String])(paramInfosExp: pub.MethodType => List[pub.TypeRepr], resultTypeExp: pub.MethodType => pub.TypeRepr): pub.MethodType = ??? + override def make(paramNames: List[String])(paramInfosExp: pub.MethodType => List[pub.TypeRepr], resultTypeExp: pub.MethodType => pub.TypeRepr): pub.MethodType = ??? + override def apply(kind: pub.MethodTypeKind)(paramNames: List[String])(paramInfosExp: pub.MethodType => List[pub.TypeRepr], resultTypeExp: pub.MethodType => pub.TypeRepr): pub.MethodType = ??? + override def make(kind: pub.MethodTypeKind)(paramNames: List[String])(paramInfosExp: pub.MethodType => List[pub.TypeRepr], resultTypeExp: pub.MethodType => pub.TypeRepr): pub.MethodType = ??? + } +} + +/////// PolyType /////////////////////////////////////////////////////////////// + +type PolyType = PolyTypeImpl +final class PolyTypeImpl(val underlying: dotc.core.Types.PolyType)(using Context) extends MethodOrPolyImpl, pub.PolyType { + override def param(idx: Int): TypeRepr = TypeReprImpl(underlying.newParamRef(idx)) + override def paramBounds: List[TypeBounds] = underlying.paramInfos.map(TypeBoundsImpl(_)) +} +object PolyTypeImpl { + object Module extends pub.PolyType.Module { + override def apply(paramNames: List[String])(paramBoundsExp: pub.PolyType => List[pub.TypeBounds], resultTypeExp: pub.PolyType => pub.TypeRepr): pub.PolyType = ??? + override def make(paramNames: List[String])(paramBoundsExp: pub.PolyType => List[pub.TypeBounds], resultTypeExp: pub.PolyType => pub.TypeRepr): pub.PolyType = ??? + } +} + +/////// TypeLambda /////////////////////////////////////////////////////////////// + +type TypeLambda = TypeLambdaImpl +final class TypeLambdaImpl(val underlying: dotc.core.Types.HKTypeLambda)(using Context) extends LambdaTypeImpl, pub.TypeLambda { + override def param(idx: Int): TypeRepr = TypeReprImpl(underlying.newParamRef(idx)) + override def paramBounds: List[TypeBounds] = underlying.paramInfos.map(TypeBoundsImpl(_)) + override def paramVariances: List[pub.Flags] = underlying.typeParams.map(tp => new FlagsImpl(tp.paramVariance)) +} +object TypeLambdaImpl { + object Module extends pub.TypeLambda.Module { + override def apply(paramNames: List[String], boundsFn: pub.TypeLambda => List[pub.TypeBounds], bodyFn: pub.TypeLambda => pub.TypeRepr): pub.TypeLambda = ??? + override def make(paramNames: List[String], boundsFn: pub.TypeLambda => List[pub.TypeBounds], bodyFn: pub.TypeLambda => pub.TypeRepr): pub.TypeLambda = ??? + } +} + +/////// MatchCase /////////////////////////////////////////////////////////////// + +type MatchCase = MatchCaseImpl +final class MatchCaseImpl(val underlying: dotc.core.Types.AppliedType)(using Context) extends TypeReprImpl, pub.MatchCase { + override def pattern: TypeRepr = TypeReprImpl(underlying.args(0)) + override def rhs: TypeRepr = TypeReprImpl(underlying.args(1)) +} +object MatchCaseImpl { + object Module extends pub.MatchCase.Module { + override def apply(pattern: pub.TypeRepr, rhs: pub.TypeRepr): pub.MatchCase = ??? + override def make(pattern: pub.TypeRepr, rhs: pub.TypeRepr): pub.MatchCase = ??? + } +} + +/////// TypeBounds /////////////////////////////////////////////////////////////// + +type TypeBounds = TypeBoundsImpl +final class TypeBoundsImpl(val underlying: dotc.core.Types.TypeBounds)(using Context) extends TypeReprImpl, pub.TypeBounds { + override def low: TypeRepr = TypeReprImpl(underlying.lo) + override def hi: TypeRepr = TypeReprImpl(underlying.hi) +} +object TypeBoundsImpl { + object Module extends pub.TypeBounds.Module { + override def apply(low: pub.TypeRepr, hi: pub.TypeRepr): pub.TypeBounds = ??? + override def make(low: pub.TypeRepr, hi: pub.TypeRepr): pub.TypeBounds = ??? + override def empty: pub.TypeBounds = ??? + override def upper(hi: pub.TypeRepr): pub.TypeBounds = ??? + override def lower(lo: pub.TypeRepr): pub.TypeBounds = ??? + } +} + +/////// NoPrefix /////////////////////////////////////////////////////////////// + +type NoPrefix = NoPrefixImpl +final class NoPrefixImpl(val underlying: dotc.core.Types.NoPrefix.type)(using Context) extends TypeReprImpl, pub.NoPrefix +object NoPrefixImpl { + object Module extends pub.NoPrefix.Module {} +} + +/////// FlexibleType /////////////////////////////////////////////////////////////// + +type FlexibleType = FlexibleTypeImpl +final class FlexibleTypeImpl(val underlying: dotc.core.Types.FlexibleType)(using Context) extends TypeReprImpl, pub.FlexibleType { + override def underlying: TypeRepr = TypeReprImpl(underlying.hi) + override def lo: TypeRepr = TypeReprImpl(underlying.lo) + override def hi: TypeRepr = TypeReprImpl(underlying.hi) +} +object FlexibleTypeImpl { + object Module extends pub.FlexibleType.Module { + override def apply(tp: pub.TypeRepr): pub.FlexibleType = ??? + override def make(tp: pub.TypeRepr): pub.FlexibleType = ??? + } +} \ No newline at end of file diff --git a/compiler/src/scala/quoted/compiletime/internal/casting.scala b/compiler/src/scala/quoted/compiletime/internal/casting.scala new file mode 100644 index 000000000000..285015212f1a --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/casting.scala @@ -0,0 +1,137 @@ +package scala.quoted.compiletime.internal + +import scala.quoted.{Expr, Type} +import scala.quoted.compiletime as pub +import scala.quoted.runtime.impl.{ExprImpl, TypeImpl} + +/////// General /////////////////////////////////////////////////////////////// + +extension (self: Expr[?]) private[internal] inline def cast: ExprImpl = self.asInstanceOf[ExprImpl] +extension (self: Type[?]) private[internal] inline def cast: TypeImpl = self.asInstanceOf[TypeImpl] + +extension (self: pub.Flags) private[internal] inline def cast: Flags = self.asInstanceOf[Flags] +extension (self: pub.Position) private[internal] inline def cast: Position = self.asInstanceOf[Position] +extension (self: pub.SourceFile) private[internal] inline def cast: SourceFile = self.asInstanceOf[SourceFile] +extension (self: pub.Symbol) private[internal] inline def cast: Symbol = self.asInstanceOf[Symbol] +extension (self: pub.Signature) private[internal] inline def cast: Signature = self.asInstanceOf[Signature] + +/////// Constant /////////////////////////////////////////////////////////////// + +extension (self: pub.Constant) private[internal] inline def cast: pub.Constant & Constant = self.asInstanceOf[pub.Constant & Constant] +extension (self: pub.BooleanConstant) private[internal] inline def cast: BooleanConstant = self.asInstanceOf[BooleanConstant] +extension (self: pub.ByteConstant) private[internal] inline def cast: ByteConstant = self.asInstanceOf[ByteConstant] +extension (self: pub.ShortConstant) private[internal] inline def cast: ShortConstant = self.asInstanceOf[ShortConstant] +extension (self: pub.IntConstant) private[internal] inline def cast: IntConstant = self.asInstanceOf[IntConstant] +extension (self: pub.LongConstant) private[internal] inline def cast: LongConstant = self.asInstanceOf[LongConstant] +extension (self: pub.FloatConstant) private[internal] inline def cast: FloatConstant = self.asInstanceOf[FloatConstant] +extension (self: pub.DoubleConstant) private[internal] inline def cast: DoubleConstant = self.asInstanceOf[DoubleConstant] +extension (self: pub.CharConstant) private[internal] inline def cast: CharConstant = self.asInstanceOf[CharConstant] +extension (self: pub.StringConstant) private[internal] inline def cast: StringConstant = self.asInstanceOf[StringConstant] +extension (self: pub.UnitConstant) private[internal] inline def cast: UnitConstant = self.asInstanceOf[UnitConstant] +extension (self: pub.NullConstant) private[internal] inline def cast: NullConstant = self.asInstanceOf[NullConstant] +extension (self: pub.ClassOfConstant) private[internal] inline def cast: ClassOfConstant = self.asInstanceOf[ClassOfConstant] + +/////// Selector /////////////////////////////////////////////////////////////// + +extension (self: pub.Selector) private[internal] inline def cast: Selector = self.asInstanceOf[Selector] +extension (self: pub.SimpleSelector) private[internal] inline def cast: SimpleSelector = self.asInstanceOf[SimpleSelector] +extension (self: pub.RenameSelector) private[internal] inline def cast: RenameSelector = self.asInstanceOf[RenameSelector] +extension (self: pub.OmitSelector) private[internal] inline def cast: OmitSelector = self.asInstanceOf[OmitSelector] +extension (self: pub.GivenSelector) private[internal] inline def cast: GivenSelector = self.asInstanceOf[GivenSelector] + +/////// ParamClause /////////////////////////////////////////////////////////////// + +extension (self: pub.ParamClause) private[internal] inline def cast: ParamClause = self.asInstanceOf[ParamClause] +extension (self: pub.TermParamClause) private[internal] inline def cast: TermParamClause = self.asInstanceOf[TermParamClause] +extension (self: pub.TypeParamClause) private[internal] inline def cast: TypeParamClause = self.asInstanceOf[TypeParamClause] + +/////// TypeRepr /////////////////////////////////////////////////////////////// + +extension (self: pub.TypeRepr) private[internal] inline def cast: TypeRepr = self.asInstanceOf[TypeRepr] +extension (self: pub.NamedType) private[internal] inline def cast: NamedType = self.asInstanceOf[NamedType] +extension (self: pub.TermRef) private[internal] inline def cast: TermRef = self.asInstanceOf[TermRef] +extension (self: pub.TypeRef) private[internal] inline def cast: TypeRef = self.asInstanceOf[TypeRef] +extension (self: pub.ConstantType) private[internal] inline def cast: ConstantType = self.asInstanceOf[ConstantType] +extension (self: pub.SuperType) private[internal] inline def cast: SuperType = self.asInstanceOf[SuperType] +extension (self: pub.Refinement) private[internal] inline def cast: Refinement = self.asInstanceOf[Refinement] +extension (self: pub.AppliedType) private[internal] inline def cast: AppliedType = self.asInstanceOf[AppliedType] +extension (self: pub.AnnotatedType) private[internal] inline def cast: AnnotatedType = self.asInstanceOf[AnnotatedType] +extension (self: pub.AndOrType) private[internal] inline def cast: AndOrType = self.asInstanceOf[AndOrType] +extension (self: pub.AndType) private[internal] inline def cast: AndType = self.asInstanceOf[AndType] +extension (self: pub.OrType) private[internal] inline def cast: OrType = self.asInstanceOf[OrType] +extension (self: pub.MatchType) private[internal] inline def cast: MatchType = self.asInstanceOf[MatchType] +extension (self: pub.ByNameType) private[internal] inline def cast: ByNameType = self.asInstanceOf[ByNameType] +extension (self: pub.ParamRef) private[internal] inline def cast: ParamRef = self.asInstanceOf[ParamRef] +extension (self: pub.ThisType) private[internal] inline def cast: ThisType = self.asInstanceOf[ThisType] +extension (self: pub.RecursiveThis) private[internal] inline def cast: RecursiveThis = self.asInstanceOf[RecursiveThis] +extension (self: pub.RecursiveType) private[internal] inline def cast: RecursiveType = self.asInstanceOf[RecursiveType] +extension (self: pub.LambdaType) private[internal] inline def cast: LambdaType = self.asInstanceOf[LambdaType] +extension (self: pub.MethodOrPoly) private[internal] inline def cast: MethodOrPoly = self.asInstanceOf[MethodOrPoly] +extension (self: pub.MethodType) private[internal] inline def cast: MethodType = self.asInstanceOf[MethodType] +extension (self: pub.PolyType) private[internal] inline def cast: PolyType = self.asInstanceOf[PolyType] +extension (self: pub.TypeLambda) private[internal] inline def cast: TypeLambda = self.asInstanceOf[TypeLambda] +extension (self: pub.MatchCase) private[internal] inline def cast: MatchCase = self.asInstanceOf[MatchCase] +extension (self: pub.TypeBounds) private[internal] inline def cast: TypeBounds = self.asInstanceOf[TypeBounds] +extension (self: pub.NoPrefix) private[internal] inline def cast: NoPrefix = self.asInstanceOf[NoPrefix] +extension (self: pub.FlexibleType) private[internal] inline def cast: FlexibleType = self.asInstanceOf[FlexibleType] + +/////// Tree /////////////////////////////////////////////////////////////// + +extension (self: pub.Tree) private[internal] inline def cast: Tree = self.asInstanceOf[Tree] +extension (self: pub.PackageClause) private[internal] inline def cast: PackageClause = self.asInstanceOf[PackageClause] +extension (self: pub.Statement) private[internal] inline def cast: Statement = self.asInstanceOf[Statement] +extension (self: pub.Import) private[internal] inline def cast: Import = self.asInstanceOf[Import] +extension (self: pub.Export) private[internal] inline def cast: Export = self.asInstanceOf[Export] +extension (self: pub.Definition) private[internal] inline def cast: Definition = self.asInstanceOf[Definition] +extension (self: pub.ClassDef) private[internal] inline def cast: ClassDef = self.asInstanceOf[ClassDef] +extension (self: pub.ValOrDefDef) private[internal] inline def cast: ValOrDefDef = self.asInstanceOf[ValOrDefDef] +extension (self: pub.DefDef) private[internal] inline def cast: DefDef = self.asInstanceOf[DefDef] +extension (self: pub.ValDef) private[internal] inline def cast: ValDef = self.asInstanceOf[ValDef] +extension (self: pub.TypeDef) private[internal] inline def cast: TypeDef = self.asInstanceOf[TypeDef] +extension (self: pub.Term) private[internal] inline def cast: Term = self.asInstanceOf[Term] +extension (self: pub.Ref) private[internal] inline def cast: Ref = self.asInstanceOf[Ref] +extension (self: pub.Ident) private[internal] inline def cast: Ident = self.asInstanceOf[Ident] +extension (self: pub.Wildcard) private[internal] inline def cast: Wildcard = self.asInstanceOf[Wildcard] +extension (self: pub.Select) private[internal] inline def cast: Select = self.asInstanceOf[Select] +extension (self: pub.Literal) private[internal] inline def cast: Literal = self.asInstanceOf[Literal] +extension (self: pub.This) private[internal] inline def cast: This = self.asInstanceOf[This] +extension (self: pub.New) private[internal] inline def cast: New = self.asInstanceOf[New] +extension (self: pub.NamedArg) private[internal] inline def cast: NamedArg = self.asInstanceOf[NamedArg] +extension (self: pub.Apply) private[internal] inline def cast: Apply = self.asInstanceOf[Apply] +extension (self: pub.TypeApply) private[internal] inline def cast: TypeApply = self.asInstanceOf[TypeApply] +extension (self: pub.Super) private[internal] inline def cast: Super = self.asInstanceOf[Super] +extension (self: pub.Typed) private[internal] inline def cast: Typed = self.asInstanceOf[Typed] +extension (self: pub.Assign) private[internal] inline def cast: Assign = self.asInstanceOf[Assign] +extension (self: pub.Block) private[internal] inline def cast: Block = self.asInstanceOf[Block] +extension (self: pub.Closure) private[internal] inline def cast: Closure = self.asInstanceOf[Closure] +extension (self: pub.If) private[internal] inline def cast: If = self.asInstanceOf[If] +extension (self: pub.Match) private[internal] inline def cast: Match = self.asInstanceOf[Match] +extension (self: pub.SummonFrom) private[internal] inline def cast: SummonFrom = self.asInstanceOf[SummonFrom] +extension (self: pub.Try) private[internal] inline def cast: Try = self.asInstanceOf[Try] +extension (self: pub.Return) private[internal] inline def cast: Return = self.asInstanceOf[Return] +extension (self: pub.Repeated) private[internal] inline def cast: Repeated = self.asInstanceOf[Repeated] +extension (self: pub.Inlined) private[internal] inline def cast: Inlined = self.asInstanceOf[Inlined] +extension (self: pub.SelectOuter) private[internal] inline def cast: SelectOuter = self.asInstanceOf[SelectOuter] +extension (self: pub.While) private[internal] inline def cast: While = self.asInstanceOf[While] +extension (self: pub.TypedOrTest) private[internal] inline def cast: TypedOrTest = self.asInstanceOf[TypedOrTest] +extension (self: pub.TypeTree) private[internal] inline def cast: TypeTree = self.asInstanceOf[TypeTree] +extension (self: pub.Inferred) private[internal] inline def cast: Inferred = self.asInstanceOf[Inferred] +extension (self: pub.TypeIdent) private[internal] inline def cast: TypeIdent = self.asInstanceOf[TypeIdent] +extension (self: pub.TypeSelect) private[internal] inline def cast: TypeSelect = self.asInstanceOf[TypeSelect] +extension (self: pub.TypeProjection) private[internal] inline def cast: TypeProjection = self.asInstanceOf[TypeProjection] +extension (self: pub.Singleton) private[internal] inline def cast: Singleton = self.asInstanceOf[Singleton] +extension (self: pub.Refined) private[internal] inline def cast: Refined = self.asInstanceOf[Refined] +extension (self: pub.Applied) private[internal] inline def cast: Applied = self.asInstanceOf[Applied] +extension (self: pub.Annotated) private[internal] inline def cast: Annotated = self.asInstanceOf[Annotated] +extension (self: pub.MatchTypeTree) private[internal] inline def cast: MatchTypeTree = self.asInstanceOf[MatchTypeTree] +extension (self: pub.ByName) private[internal] inline def cast: ByName = self.asInstanceOf[ByName] +extension (self: pub.LambdaTypeTree) private[internal] inline def cast: LambdaTypeTree = self.asInstanceOf[LambdaTypeTree] +extension (self: pub.TypeBind) private[internal] inline def cast: TypeBind = self.asInstanceOf[TypeBind] +extension (self: pub.TypeBlock) private[internal] inline def cast: TypeBlock = self.asInstanceOf[TypeBlock] +extension (self: pub.TypeBoundsTree) private[internal] inline def cast: TypeBoundsTree = self.asInstanceOf[TypeBoundsTree] +extension (self: pub.WildcardTypeTree) private[internal] inline def cast: WildcardTypeTree = self.asInstanceOf[WildcardTypeTree] +extension (self: pub.CaseDef) private[internal] inline def cast: CaseDef = self.asInstanceOf[CaseDef] +extension (self: pub.TypeCaseDef) private[internal] inline def cast: TypeCaseDef = self.asInstanceOf[TypeCaseDef] +extension (self: pub.Bind) private[internal] inline def cast: Bind = self.asInstanceOf[Bind] +extension (self: pub.Unapply) private[internal] inline def cast: Unapply = self.asInstanceOf[Unapply] +extension (self: pub.Alternatives) private[internal] inline def cast: Alternatives = self.asInstanceOf[Alternatives] diff --git a/compiler/src/scala/quoted/compiletime/internal/reflectImpl.scala b/compiler/src/scala/quoted/compiletime/internal/reflectImpl.scala new file mode 100644 index 000000000000..a8c5892501e6 --- /dev/null +++ b/compiler/src/scala/quoted/compiletime/internal/reflectImpl.scala @@ -0,0 +1,131 @@ +package scala.quoted.compiletime +package internal + +import dotty.tools.dotc.core.Contexts.* + +object reflectImpl { + + final class Module(using val ctx: Context) extends reflect.Module { + + override lazy val Symbol: SymbolImpl.Module = new SymbolImpl.Module + override lazy val Position: PositionImpl.Module = new PositionImpl.Module + override lazy val SourceFile: SourceFileImpl.Module = new SourceFileImpl.Module + + override lazy val Constant: ConstantImpl.Module.type = ConstantImpl.Module + override lazy val BooleanConstant: BooleanConstantImpl.Module.type = BooleanConstantImpl.Module + override lazy val ByteConstant: ByteConstantImpl.Module.type = ByteConstantImpl.Module + override lazy val ShortConstant: ShortConstantImpl.Module.type = ShortConstantImpl.Module + override lazy val IntConstant: IntConstantImpl.Module.type = IntConstantImpl.Module + override lazy val LongConstant: LongConstantImpl.Module.type = LongConstantImpl.Module + override lazy val FloatConstant: FloatConstantImpl.Module.type = FloatConstantImpl.Module + override lazy val DoubleConstant: DoubleConstantImpl.Module.type = DoubleConstantImpl.Module + override lazy val CharConstant: CharConstantImpl.Module.type = CharConstantImpl.Module + override lazy val StringConstant: StringConstantImpl.Module.type = StringConstantImpl.Module + override lazy val UnitConstant: UnitConstantImpl.Module.type = UnitConstantImpl.Module + override lazy val NullConstant: NullConstantImpl.Module.type = NullConstantImpl.Module + override lazy val ClassOfConstant: ClassOfConstantImpl.Module.type = ClassOfConstantImpl.Module + + override lazy val TypeRepr: TypeReprImpl.Module.type = TypeReprImpl.Module + override lazy val NamedType: NamedTypeImpl.Module.type = NamedTypeImpl.Module + override lazy val TermRef: TermRefImpl.Module.type = TermRefImpl.Module + override lazy val TypeRef: TypeRefImpl.Module.type = TypeRefImpl.Module + override lazy val ConstantType: ConstantTypeImpl.Module.type = ConstantTypeImpl.Module + override lazy val SuperType: SuperTypeImpl.Module.type = SuperTypeImpl.Module + override lazy val Refinement: RefinementImpl.Module.type = RefinementImpl.Module + override lazy val AppliedType: AppliedTypeImpl.Module.type = AppliedTypeImpl.Module + override lazy val AnnotatedType: AnnotatedTypeImpl.Module.type = AnnotatedTypeImpl.Module + override lazy val AndOrType: AndOrTypeImpl.Module.type = AndOrTypeImpl.Module + override lazy val AndType: AndTypeImpl.Module.type = AndTypeImpl.Module + override lazy val OrType: OrTypeImpl.Module.type = OrTypeImpl.Module + override lazy val MatchType: MatchTypeImpl.Module.type = MatchTypeImpl.Module + override lazy val ByNameType: ByNameTypeImpl.Module.type = ByNameTypeImpl.Module + override lazy val ParamRef: ParamRefImpl.Module.type = ParamRefImpl.Module + override lazy val ThisType: ThisTypeImpl.Module.type = ThisTypeImpl.Module + override lazy val RecursiveThis: RecursiveThisImpl.Module.type = RecursiveThisImpl.Module + override lazy val RecursiveType: RecursiveTypeImpl.Module.type = RecursiveTypeImpl.Module + override lazy val LambdaType: LambdaTypeImpl.Module.type = LambdaTypeImpl.Module + override lazy val MethodOrPoly: MethodOrPolyImpl.Module.type = MethodOrPolyImpl.Module + override lazy val MethodType: MethodTypeImpl.Module.type = MethodTypeImpl.Module + override lazy val PolyType: PolyTypeImpl.Module.type = PolyTypeImpl.Module + override lazy val TypeLambda: TypeLambdaImpl.Module.type = TypeLambdaImpl.Module + override lazy val MatchCase: MatchCaseImpl.Module.type = MatchCaseImpl.Module + override lazy val TypeBounds: TypeBoundsImpl.Module.type = TypeBoundsImpl.Module + override lazy val NoPrefix: NoPrefixImpl.Module.type = NoPrefixImpl.Module + override lazy val FlexibleType: FlexibleTypeImpl.Module.type = FlexibleTypeImpl.Module + + override lazy val Signature: SignatureImpl.Module.type = SignatureImpl.Module + override lazy val Flags: FlagsImpl.Module.type = FlagsImpl.Module + + override lazy val Selector: SelectorImpl.Module.type = SelectorImpl.Module + override lazy val SimpleSelector: SimpleSelectorImpl.Module.type = SimpleSelectorImpl.Module + override lazy val RenameSelector: RenameSelectorImpl.Module.type = RenameSelectorImpl.Module + override lazy val OmitSelector: OmitSelectorImpl.Module.type = OmitSelectorImpl.Module + override lazy val GivenSelector: GivenSelectorImpl.Module.type = GivenSelectorImpl.Module + + override lazy val ParamClause: ParamClauseImpl.Module.type = ParamClauseImpl.Module + override lazy val TermParamClause: TermParamClauseImpl.Module.type = TermParamClauseImpl.Module + override lazy val TypeParamClause: TypeParamClauseImpl.Module.type = TypeParamClauseImpl.Module + + override lazy val Tree: TreeImpl.Module.type = TreeImpl.Module + override lazy val PackageClause: PackageClauseImpl.Module.type = PackageClauseImpl.Module + override lazy val Statement: StatementImpl.Module.type = StatementImpl.Module + override lazy val Import: ImportImpl.Module.type = ImportImpl.Module + override lazy val Export: ExportImpl.Module.type = ExportImpl.Module + override lazy val Definition: DefinitionImpl.Module.type = DefinitionImpl.Module + override lazy val ClassDef: ClassDefImpl.Module.type = ClassDefImpl.Module + override lazy val ValOrDefDef: ValOrDefDefImpl.Module.type = ValOrDefDefImpl.Module + override lazy val DefDef: DefDefImpl.Module.type = DefDefImpl.Module + override lazy val ValDef: ValDefImpl.Module.type = ValDefImpl.Module + override lazy val TypeDef: TypeDefImpl.Module.type = TypeDefImpl.Module + override lazy val Term: TermImpl.Module.type = TermImpl.Module + override lazy val Ref: RefImpl.Module.type = RefImpl.Module + override lazy val Ident: IdentImpl.Module.type = IdentImpl.Module + override lazy val Wildcard: WildcardImpl.Module.type = WildcardImpl.Module + override lazy val Select: SelectImpl.Module.type = SelectImpl.Module + override lazy val Literal: LiteralImpl.Module.type = LiteralImpl.Module + override lazy val This: ThisImpl.Module.type = ThisImpl.Module + override lazy val New: NewImpl.Module.type = NewImpl.Module + override lazy val NamedArg: NamedArgImpl.Module.type = NamedArgImpl.Module + override lazy val Apply: ApplyImpl.Module.type = ApplyImpl.Module + override lazy val TypeApply: TypeApplyImpl.Module.type = TypeApplyImpl.Module + override lazy val Super: SuperImpl.Module.type = SuperImpl.Module + override lazy val Typed: TypedImpl.Module.type = TypedImpl.Module + override lazy val Assign: AssignImpl.Module.type = AssignImpl.Module + override lazy val Block: BlockImpl.Module.type = BlockImpl.Module + override lazy val Closure: ClosureImpl.Module.type = ClosureImpl.Module + override lazy val Lambda: LambdaImpl.Module.type = LambdaImpl.Module + override lazy val If: IfImpl.Module.type = IfImpl.Module + override lazy val Match: MatchImpl.Module.type = MatchImpl.Module + override lazy val SummonFrom: SummonFromImpl.Module.type = SummonFromImpl.Module + override lazy val Try: TryImpl.Module.type = TryImpl.Module + override lazy val Return: ReturnImpl.Module.type = ReturnImpl.Module + override lazy val Repeated: RepeatedImpl.Module.type = RepeatedImpl.Module + override lazy val Inlined: InlinedImpl.Module.type = InlinedImpl.Module + override lazy val SelectOuter: SelectOuterImpl.Module.type = SelectOuterImpl.Module + override lazy val While: WhileImpl.Module.type = WhileImpl.Module + override lazy val TypedOrTest: TypedOrTestImpl.Module.type = TypedOrTestImpl.Module + override lazy val TypeTree: TypeTreeImpl.Module.type = TypeTreeImpl.Module + override lazy val Inferred: InferredImpl.Module.type = InferredImpl.Module + override lazy val TypeIdent: TypeIdentImpl.Module.type = TypeIdentImpl.Module + override lazy val TypeSelect: TypeSelectImpl.Module.type = TypeSelectImpl.Module + override lazy val TypeProjection: TypeProjectionImpl.Module.type = TypeProjectionImpl.Module + override lazy val Singleton: SingletonImpl.Module.type = SingletonImpl.Module + override lazy val Refined: RefinedImpl.Module.type = RefinedImpl.Module + override lazy val Applied: AppliedImpl.Module.type = AppliedImpl.Module + override lazy val Annotated: AnnotatedImpl.Module.type = AnnotatedImpl.Module + override lazy val MatchTypeTree: MatchTypeTreeImpl.Module.type = MatchTypeTreeImpl.Module + override lazy val ByName: ByNameImpl.Module.type = ByNameImpl.Module + override lazy val LambdaTypeTree: LambdaTypeTreeImpl.Module.type = LambdaTypeTreeImpl.Module + override lazy val TypeBind: TypeBindImpl.Module.type = TypeBindImpl.Module + override lazy val TypeBlock: TypeBlockImpl.Module.type = TypeBlockImpl.Module + override lazy val TypeBoundsTree: TypeBoundsTreeImpl.Module.type = TypeBoundsTreeImpl.Module + override lazy val WildcardTypeTree: WildcardTypeTreeImpl.Module.type = WildcardTypeTreeImpl.Module + override lazy val CaseDef: CaseDefImpl.Module.type = CaseDefImpl.Module + override lazy val TypeCaseDef: TypeCaseDefImpl.Module.type = TypeCaseDefImpl.Module + override lazy val Bind: BindImpl.Module.type = BindImpl.Module + override lazy val Unapply: UnapplyImpl.Module.type = UnapplyImpl.Module + override lazy val Alternatives: AlternativesImpl.Module.type = AlternativesImpl.Module + + } + +} \ No newline at end of file diff --git a/library/src/scala/quoted/compiletime/Constant.scala b/library/src/scala/quoted/compiletime/Constant.scala new file mode 100644 index 000000000000..c86f937e2c01 --- /dev/null +++ b/library/src/scala/quoted/compiletime/Constant.scala @@ -0,0 +1,273 @@ +package scala.quoted.compiletime + +/////// Constant /////////////////////////////////////////////////////////////// + +sealed trait Constant { + + def value: Any + + final def show(using p: Printer[Constant]): String = p.show(this) + +} +object Constant { + + def quoted(using quotes: Quotes): Constant.Module = quotes.reflectV2.Constant + given moduleConversion: (quotes: Quotes) => Conversion[Constant.type, Constant.Module] = _ => quotes.reflectV2.Constant + + def unapply(x: Constant): Some[Any] = Some(x.value) + + trait Module private[compiletime] () {} + +} + +/////// BooleanConstant /////////////////////////////////////////////////////////////// + +trait BooleanConstant private[compiletime] () extends Constant { + + override def value: Boolean + +} +object BooleanConstant { + + def quoted(using quotes: Quotes): BooleanConstant.Module = quotes.reflectV2.BooleanConstant + given moduleConversion: (quotes: Quotes) => Conversion[BooleanConstant.type, BooleanConstant.Module] = _ => quotes.reflectV2.BooleanConstant + + def unapply(x: BooleanConstant): Some[Boolean] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Boolean): BooleanConstant + def make(x: Boolean): BooleanConstant + } + +} + +/////// ByteConstant /////////////////////////////////////////////////////////////// + +trait ByteConstant private[compiletime] () extends Constant { + + override def value: Byte + +} +object ByteConstant { + + def quoted(using quotes: Quotes): ByteConstant.Module = quotes.reflectV2.ByteConstant + given moduleConversion: (quotes: Quotes) => Conversion[ByteConstant.type, ByteConstant.Module] = _ => quotes.reflectV2.ByteConstant + + def unapply(x: ByteConstant): Some[Byte] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Byte): ByteConstant + def make(x: Byte): ByteConstant + } + +} + +/////// ShortConstant /////////////////////////////////////////////////////////////// + +trait ShortConstant private[compiletime] () extends Constant { + + override def value: Short + +} +object ShortConstant { + + def quoted(using quotes: Quotes): ShortConstant.Module = quotes.reflectV2.ShortConstant + given moduleConversion: (quotes: Quotes) => Conversion[ShortConstant.type, ShortConstant.Module] = _ => quotes.reflectV2.ShortConstant + + def unapply(x: ShortConstant): Some[Short] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Short): ShortConstant + def make(x: Short): ShortConstant + } + +} + +/////// IntConstant /////////////////////////////////////////////////////////////// + +trait IntConstant private[compiletime] () extends Constant { + + override def value: Int + +} +object IntConstant { + + def quoted(using quotes: Quotes): IntConstant.Module = quotes.reflectV2.IntConstant + given moduleConversion: (quotes: Quotes) => Conversion[IntConstant.type, IntConstant.Module] = _ => quotes.reflectV2.IntConstant + + def unapply(x: IntConstant): Some[Int] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Int): IntConstant + def make(x: Int): IntConstant + } + +} + +/////// LongConstant /////////////////////////////////////////////////////////////// + +trait LongConstant private[compiletime] () extends Constant { + + override def value: Long + +} +object LongConstant { + + def quoted(using quotes: Quotes): LongConstant.Module = quotes.reflectV2.LongConstant + given moduleConversion: (quotes: Quotes) => Conversion[LongConstant.type, LongConstant.Module] = _ => quotes.reflectV2.LongConstant + + def unapply(x: LongConstant): Some[Long] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Long): LongConstant + def make(x: Long): LongConstant + } + +} + +/////// FloatConstant /////////////////////////////////////////////////////////////// + +trait FloatConstant private[compiletime] () extends Constant { + + override def value: Float + +} +object FloatConstant { + + def quoted(using quotes: Quotes): FloatConstant.Module = quotes.reflectV2.FloatConstant + given moduleConversion: (quotes: Quotes) => Conversion[FloatConstant.type, FloatConstant.Module] = _ => quotes.reflectV2.FloatConstant + + def unapply(x: FloatConstant): Some[Float] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Float): FloatConstant + def make(x: Float): FloatConstant + } + +} + +/////// DoubleConstant /////////////////////////////////////////////////////////////// + +trait DoubleConstant private[compiletime] () extends Constant { + + override def value: Double + +} +object DoubleConstant { + + def quoted(using quotes: Quotes): DoubleConstant.Module = quotes.reflectV2.DoubleConstant + given moduleConversion: (quotes: Quotes) => Conversion[DoubleConstant.type, DoubleConstant.Module] = _ => quotes.reflectV2.DoubleConstant + + def unapply(x: DoubleConstant): Some[Double] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Double): DoubleConstant + def make(x: Double): DoubleConstant + } + +} + +/////// CharConstant /////////////////////////////////////////////////////////////// + +trait CharConstant private[compiletime] () extends Constant { + + override def value: Char + +} +object CharConstant { + + def quoted(using quotes: Quotes): CharConstant.Module = quotes.reflectV2.CharConstant + given moduleConversion: (quotes: Quotes) => Conversion[CharConstant.type, CharConstant.Module] = _ => quotes.reflectV2.CharConstant + + def unapply(x: CharConstant): Some[Char] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: Char): CharConstant + def make(x: Char): CharConstant + } + +} + +/////// StringConstant /////////////////////////////////////////////////////////////// + +trait StringConstant private[compiletime] () extends Constant { + + override def value: String + +} +object StringConstant { + + def quoted(using quotes: Quotes): StringConstant.Module = quotes.reflectV2.StringConstant + given moduleConversion: (quotes: Quotes) => Conversion[StringConstant.type, StringConstant.Module] = _ => quotes.reflectV2.StringConstant + + def unapply(x: StringConstant): Some[String] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: String): StringConstant + def make(x: String): StringConstant + } + +} + +/////// UnitConstant /////////////////////////////////////////////////////////////// + +trait UnitConstant private[compiletime] () extends Constant { + + override def value: Unit + +} +object UnitConstant { + + def quoted(using quotes: Quotes): UnitConstant.Module = quotes.reflectV2.UnitConstant + given moduleConversion: (quotes: Quotes) => Conversion[UnitConstant.type, UnitConstant.Module] = _ => quotes.reflectV2.UnitConstant + + def unapply(x: UnitConstant): true = true + + trait Module private[compiletime] () { + def apply(): UnitConstant + def make(): UnitConstant + } + +} + +/////// NullConstant /////////////////////////////////////////////////////////////// + +trait NullConstant private[compiletime] () extends Constant { + + override def value: Null + +} +object NullConstant { + + def quoted(using quotes: Quotes): NullConstant.Module = quotes.reflectV2.NullConstant + given moduleConversion: (quotes: Quotes) => Conversion[NullConstant.type, NullConstant.Module] = _ => quotes.reflectV2.NullConstant + + def unapply(x: NullConstant): true = true + + trait Module private[compiletime] () { + def apply(): NullConstant + def make(): NullConstant + } + +} + +/////// ClassOfConstant /////////////////////////////////////////////////////////////// + +trait ClassOfConstant private[compiletime] () extends Constant { + + override def value: TypeRepr + +} +object ClassOfConstant { + + def quoted(using quotes: Quotes): ClassOfConstant.Module = quotes.reflectV2.ClassOfConstant + given moduleConversion: (quotes: Quotes) => Conversion[ClassOfConstant.type, ClassOfConstant.Module] = _ => quotes.reflectV2.ClassOfConstant + + def unapply(x: ClassOfConstant): Some[TypeRepr] = Some(x.value) + + trait Module private[compiletime] () { + def apply(x: TypeRepr): ClassOfConstant + def make(x: TypeRepr): ClassOfConstant + } + +} diff --git a/library/src/scala/quoted/compiletime/Flags.scala b/library/src/scala/quoted/compiletime/Flags.scala new file mode 100644 index 000000000000..668977c689dd --- /dev/null +++ b/library/src/scala/quoted/compiletime/Flags.scala @@ -0,0 +1,73 @@ +package scala.quoted.compiletime + +trait Flags private[compiletime] () { + + /** Is the given flag set a subset of this flag sets. */ + def is(that: Flags): Boolean + + /** Union of the two flag sets. */ + def |(that: Flags): Flags + + /** Intersection of the two flag sets. */ + def &(that: Flags): Flags + + /** Shows the flags as a String. */ + def show: String + +} +object Flags { + + def quoted(using quotes: Quotes): Flags.Module = quotes.reflectV2.Flags + given moduleConversion: (quotes: Quotes) => Conversion[Flags.type, Flags.Module] = _ => quotes.reflectV2.Flags + + trait Module private[compiletime] () { + def Abstract: Flags + def AbsOverride: Flags + def Artifact: Flags + def Case: Flags + def CaseAccessor: Flags + def Contravariant: Flags + def Covariant: Flags + def Deferred: Flags + def EmptyFlags: Flags + def Enum: Flags + def Erased: Flags + def Exported: Flags + def ExtensionMethod: Flags + def FieldAccessor: Flags + def Final: Flags + def Given: Flags + def HasDefault: Flags + def Implicit: Flags + def Infix: Flags + def Inline: Flags + def Invisible: Flags + def JavaDefined: Flags + def JavaStatic: Flags + def JavaAnnotation: Flags + def Lazy: Flags + def Local: Flags + def Macro: Flags + def Method: Flags + def Module: Flags + def Mutable: Flags + def NoInits: Flags + def Opaque: Flags + def Open: Flags + def Override: Flags + def Package: Flags + def Param: Flags + def ParamAccessor: Flags + def Private: Flags + def PrivateLocal: Flags + def Protected: Flags + def Scala2x: Flags + def Sealed: Flags + def StableRealizable: Flags + @deprecated("Use JavaStatic instead", "3.3.0") def Static: Flags + def Synthetic: Flags + def Trait: Flags + def Transparent: Flags + } + +} \ No newline at end of file diff --git a/library/src/scala/quoted/compiletime/MethodTypeKind.scala b/library/src/scala/quoted/compiletime/MethodTypeKind.scala new file mode 100644 index 000000000000..9056d0072b79 --- /dev/null +++ b/library/src/scala/quoted/compiletime/MethodTypeKind.scala @@ -0,0 +1,16 @@ +package scala.quoted.compiletime + +/** Type which decides on the kind of parameter list represented by `MethodType`. */ +sealed trait MethodTypeKind +object MethodTypeKind { + + /** Represents a parameter list without any implicitness of parameters, like (x1: X1, x2: X2, ...). */ + case object Plain extends MethodTypeKind + + /** Represents a parameter list with implicit parameters, like `(implicit X1, ..., Xn)`, `(using X1, ..., Xn)`, `(using x1: X1, ..., xn: Xn)`. */ + case object Implicit extends MethodTypeKind + + /** Represents a parameter list of a contextual method, like `(using X1, ..., Xn)` or `(using x1: X1, ..., xn: Xn)`. */ + case object Contextual extends MethodTypeKind + +} diff --git a/library/src/scala/quoted/compiletime/ParamClause.scala b/library/src/scala/quoted/compiletime/ParamClause.scala new file mode 100644 index 000000000000..e153fef026cc --- /dev/null +++ b/library/src/scala/quoted/compiletime/ParamClause.scala @@ -0,0 +1,103 @@ +package scala.quoted.compiletime + +import scala.annotation.experimental + +/////// ParamClause /////////////////////////////////////////////////////////////// + +/** + * A parameter clause `[X1, ..., Xn]` or `(x1: X1, ..., xn: Xx)` + * + * `[X1, ..., Xn]` are represented with `TypeParamClause` and `(x1: X1, ..., xn: Xx)` are represented with `TermParamClause` + * + * `ParamClause` encodes the following enumeration + * ```scala + * //{ + * import scala.quoted.* + * def inQuotes(using Quotes) = { + * val q: Quotes = summon[Quotes] + * import q.reflect.* + * //} + * enum ParamClause: + * case TypeParamClause(params: List[TypeDef]) + * case TermParamClause(params: List[ValDef]) + * //{ + * } + * //} + * ``` + */ +sealed trait ParamClause private[compiletime] () { + + /** List of parameters of the clause. */ + def params: List[ValDef] | List[TypeDef] +} +object ParamClause { + + def quoted(using quotes: Quotes): ParamClause.Module = quotes.reflectV2.ParamClause + given moduleConversion: (quotes: Quotes) => Conversion[ParamClause.type, ParamClause.Module] = _ => quotes.reflectV2.ParamClause + + trait Module private[compiletime] () {} + +} + +/////// TermParamClause /////////////////////////////////////////////////////////////// + +/** + * A term parameter clause `(x1: X1, ..., xn: Xx)` + * Can also be `(implicit X1, ..., Xn)`, `(given X1, ..., Xn)` or `(given x1: X1, ..., xn: Xn)` + */ +trait TermParamClause private[compiletime] () extends ParamClause { + + /** List of parameters of the clause. */ + def params: List[ValDef] + + /** Is this an implicit parameter clause `(implicit x1: X1, ..., xn: Xn)`. */ + def isImplicit: Boolean + + /** Is this a given parameter clause `(using X1, ..., Xn)` or `(using x1: X1, ..., xn: Xn)`. */ + def isGiven: Boolean + + /** List of `erased` flags for each parameter of the clause. */ + @experimental + def erasedArgs: List[Boolean] + + /** Whether the clause has any erased parameters. */ + @experimental + def hasErasedArgs: Boolean + +} +object TermParamClause { + + def quoted(using quotes: Quotes): TermParamClause.Module = quotes.reflectV2.TermParamClause + given moduleConversion: (quotes: Quotes) => Conversion[TermParamClause.type, TermParamClause.Module] = _ => quotes.reflectV2.TermParamClause + + def unapply(x: TermParamClause): Some[List[ValDef]] = Some(x.params) + + trait Module private[compiletime] () { + def apply(params: List[ValDef]): TermParamClause + def make(params: List[ValDef]): TermParamClause + } + +} + +/////// TypeParamClause /////////////////////////////////////////////////////////////// + +/** A type parameter clause `[X1, ..., Xn]`. */ +trait TypeParamClause private[compiletime] () extends ParamClause { + + /** List of parameters of the clause. */ + def params: List[TypeDef] + +} +object TypeParamClause { + + def quoted(using quotes: Quotes): TypeParamClause.Module = quotes.reflectV2.TypeParamClause + given moduleConversion: (quotes: Quotes) => Conversion[TypeParamClause.type, TypeParamClause.Module] = _ => quotes.reflectV2.TypeParamClause + + def unapply(x: TypeParamClause): Some[List[TypeDef]] = Some(x.params) + + trait Module private[compiletime] () { + def apply(params: List[TypeDef]): TypeParamClause + def make(params: List[TypeDef]): TypeParamClause + } + +} diff --git a/library/src/scala/quoted/compiletime/Position.scala b/library/src/scala/quoted/compiletime/Position.scala new file mode 100644 index 000000000000..4bd1cf48dfe2 --- /dev/null +++ b/library/src/scala/quoted/compiletime/Position.scala @@ -0,0 +1,48 @@ +package scala.quoted.compiletime + +trait Position private[compiletime] () { + + /** The start offset in the source file. */ + def start: Int + + /** The end offset in the source file. */ + def end: Int + + /** Source file in which this position is located. */ + def sourceFile: SourceFile + + /** The start line in the source file. */ + def startLine: Int + + /** The end line in the source file. */ + def endLine: Int + + /** The start column in the source file. */ + def startColumn: Int + + /** The end column in the source file. */ + def endColumn: Int + + /** Source code within the position. */ + def sourceCode: Option[String] + +} +object Position { + + def quoted(using quotes: Quotes): Position.Module = quotes.reflectV2.Position + given moduleConversion: (quotes: Quotes) => Conversion[Position.type, Position.Module] = _ => quotes.reflectV2.Position + + trait Module private[compiletime] () { + + /** Position of the expansion site of the macro. */ + def ofMacroExpansion: Position + + /** Creates a new position in the source with the given range. The range must be contained in the file. */ + def apply(sourceFile: SourceFile, start: Int, end: Int): Position + + /** Creates a new position in the source with the given range. The range must be contained in the file. */ + def make(sourceFile: SourceFile, start: Int, end: Int): Position + + } + +} diff --git a/library/src/scala/quoted/compiletime/Printer.scala b/library/src/scala/quoted/compiletime/Printer.scala new file mode 100644 index 000000000000..2423be5f828b --- /dev/null +++ b/library/src/scala/quoted/compiletime/Printer.scala @@ -0,0 +1,5 @@ +package scala.quoted.compiletime + +trait Printer[T] { + def show(x: T): String +} diff --git a/library/src/scala/quoted/compiletime/Quotes.scala b/library/src/scala/quoted/compiletime/Quotes.scala new file mode 100644 index 000000000000..3f7790be515b --- /dev/null +++ b/library/src/scala/quoted/compiletime/Quotes.scala @@ -0,0 +1,9 @@ +package scala.quoted.compiletime + +import scala.quoted.compiletime as pub + +trait Quotes { + + lazy val reflectV2: pub.reflect.Module + +} diff --git a/library/src/scala/quoted/compiletime/Selector.scala b/library/src/scala/quoted/compiletime/Selector.scala new file mode 100644 index 000000000000..06e23b4479a4 --- /dev/null +++ b/library/src/scala/quoted/compiletime/Selector.scala @@ -0,0 +1,106 @@ +package scala.quoted.compiletime + +import scala.annotation.experimental + +/////// Selector /////////////////////////////////////////////////////////////// + +/** Import/Export selectors: + * - SimpleSelector: `.bar` in `import foo.bar` + * - RenameSelector: `.{bar => baz}` in `export foo.{bar => baz}` + * - OmitSelector: `.{bar => _}` in `import foo.{bar => _}` + * - GivenSelector: `.given`/`.{given T}` in `export foo.given`/`import foo.{given T}` + */ +sealed trait Selector private[compiletime] () +object Selector { + + def quoted(using quotes: Quotes): Selector.Module = quotes.reflectV2.Selector + given moduleConversion: (quotes: Quotes) => Conversion[Selector.type, Selector.Module] = _ => quotes.reflectV2.Selector + + trait Module private[compiletime] () {} + +} + +/////// SimpleSelector /////////////////////////////////////////////////////////////// + +/** Simple import/export selector: `.bar` in `import foo.bar`. */ +trait SimpleSelector private[compiletime] () extends Selector { + def name: String + def namePos: Position +} +object SimpleSelector { + + def quoted(using quotes: Quotes): SimpleSelector.Module = quotes.reflectV2.SimpleSelector + given moduleConversion: (quotes: Quotes) => Conversion[SimpleSelector.type, SimpleSelector.Module] = _ => quotes.reflectV2.SimpleSelector + + def unapply(x: SimpleSelector): Some[String] = Some(x.name) + + trait Module private[compiletime] () { + @experimental def apply(name: String): SimpleSelector + @experimental def make(name: String): SimpleSelector + } + +} + +/////// RenameSelector /////////////////////////////////////////////////////////////// + +/** Rename import/export selector: `.{bar => baz}` in `import foo.{bar => baz}`. */ +trait RenameSelector private[compiletime] () extends Selector { + def fromName: String + def fromPos: Position + def toName: String + def toPos: Position +} +object RenameSelector { + + def quoted(using quotes: Quotes): RenameSelector.Module = quotes.reflectV2.RenameSelector + given moduleConversion: (quotes: Quotes) => Conversion[RenameSelector.type, RenameSelector.Module] = _ => quotes.reflectV2.RenameSelector + + def unapply(x: RenameSelector): (String, String) = (x.fromName, x.toName) + + trait Module private[compiletime] () { + @experimental def apply(fromName: String, toName: String): RenameSelector + @experimental def make(fromName: String, toName: String): RenameSelector + } + +} + +/////// OmitSelector /////////////////////////////////////////////////////////////// + +/** Omit import/export selector: `.{bar => _}` in `import foo.{bar => _}`. */ +trait OmitSelector private[compiletime] () extends Selector { + def name: String + def namePos: Position +} +object OmitSelector { + + def quoted(using quotes: Quotes): OmitSelector.Module = quotes.reflectV2.OmitSelector + given moduleConversion: (quotes: Quotes) => Conversion[OmitSelector.type, OmitSelector.Module] = _ => quotes.reflectV2.OmitSelector + + def unapply(x: OmitSelector): Some[String] = Some(x.name) + + trait Module private[compiletime] () { + @experimental def apply(name: String): OmitSelector + @experimental def make(name: String): OmitSelector + } + +} + +/////// GivenSelector /////////////////////////////////////////////////////////////// + +/** given import/export selector: `.given`/`.{given T}` in `import foo.given`/`export foo.{given T}`. */ +trait GivenSelector private[compiletime] () extends Selector { + def bound: Option[TypeTree] +} +object GivenSelector { + + def quoted(using quotes: Quotes): GivenSelector.Module = quotes.reflectV2.GivenSelector + given moduleConversion: (quotes: Quotes) => Conversion[GivenSelector.type, GivenSelector.Module] = _ => quotes.reflectV2.GivenSelector + + def unapply(x: GivenSelector): Some[Option[TypeTree]] = Some(x.bound) + + trait Module private[compiletime] () { + @experimental def apply(bound: Option[TypeTree]): GivenSelector + @experimental def make(bound: Option[TypeTree]): GivenSelector + } + +} diff --git a/library/src/scala/quoted/compiletime/Signature.scala b/library/src/scala/quoted/compiletime/Signature.scala new file mode 100644 index 000000000000..814621d671ac --- /dev/null +++ b/library/src/scala/quoted/compiletime/Signature.scala @@ -0,0 +1,28 @@ +package scala.quoted.compiletime + +/////// Signature /////////////////////////////////////////////////////////////// + +/** The signature of a method. */ +trait Signature private[compiletime] () { + /** The signatures of the method parameters. + * + * Each *type parameter section* is represented by a single Int corresponding + * to the number of type parameters in the section. + * Each *term parameter* is represented by a String corresponding to the fully qualified + * name of the parameter type. + */ + def paramSigs: List[String | Int] + /** The signature of the result type. */ + def resultSig: String +} +object Signature { + + def quoted(using quotes: Quotes): Signature.Module = quotes.reflectV2.Signature + given moduleConversion: (quotes: Quotes) => Conversion[Signature.type, Signature.Module] = _ => quotes.reflectV2.Signature + + /** Matches the method signature and returns its parameters and result type. */ + def unapply(sig: Signature): (List[String | Int], String) = (sig.paramSigs, sig.resultSig) + + trait Module private[compiletime] () {} + +} diff --git a/library/src/scala/quoted/compiletime/SourceFile.scala b/library/src/scala/quoted/compiletime/SourceFile.scala new file mode 100644 index 000000000000..366342bd4d1a --- /dev/null +++ b/library/src/scala/quoted/compiletime/SourceFile.scala @@ -0,0 +1,35 @@ +package scala.quoted.compiletime + +trait SourceFile private[compiletime] () { + + /** Path to this source file. May be `None` for virtual files such as in the REPL. */ + def getJPath: Option[java.nio.file.Path] + + /** Name of the source file. */ + def name: String + + /** + * Path of the source file. + * + * It does not necessarily point to a path in the filesystem, it could be the path of a virtual file. + * Use `getJPath` to get paths to the filesystem. + */ + def path: String + + /** Content of this source file. */ + def content: Option[String] + +} +object SourceFile { + + def quoted(using quotes: Quotes): SourceFile.Module = quotes.reflectV2.SourceFile + given moduleConversion: (quotes: Quotes) => Conversion[SourceFile.type, SourceFile.Module] = _ => quotes.reflectV2.SourceFile + + trait Module private[compiletime] () { + + /** Returns the source file being compiled. The path is relative to the current working directory. */ + def current: SourceFile + + } + +} diff --git a/library/src/scala/quoted/compiletime/Symbol.scala b/library/src/scala/quoted/compiletime/Symbol.scala new file mode 100644 index 000000000000..aeefdd0714c7 --- /dev/null +++ b/library/src/scala/quoted/compiletime/Symbol.scala @@ -0,0 +1,19 @@ +package scala.quoted.compiletime + +trait Symbol private[compiletime] () { + + // TODO: Add methods + +} +object Symbol { + + def quoted(using quotes: Quotes): Symbol.Module = quotes.reflectV2.Symbol + given moduleConversion: (quotes: Quotes) => Conversion[Symbol.type, Symbol.Module] = _ => quotes.reflectV2.Symbol + + trait Module private[compiletime] () { + + // TODO: Add methods + + } + +} diff --git a/library/src/scala/quoted/compiletime/Tree.scala b/library/src/scala/quoted/compiletime/Tree.scala new file mode 100644 index 000000000000..645308d33417 --- /dev/null +++ b/library/src/scala/quoted/compiletime/Tree.scala @@ -0,0 +1,1883 @@ +package scala.quoted.compiletime + +import scala.quoted.Expr +import scala.quoted.Type + +/////// Tree /////////////////////////////////////////////////////////////// + +/** Tree representing code written in the source. */ +sealed trait Tree private[compiletime] () { + + /** Position in the source code. */ + def pos: Position + + /** Symbol of defined or referred by this tree. */ + def symbol: Symbol + + /** Shows the tree as String. */ + def show(using Printer[Tree]): String + + /** Does this tree represent a valid expression? */ + def isExpr: Boolean + + /** Converts this tree to an `quoted.Expr[Any]` if the tree is a valid expression or throws. */ + def asExpr: Expr[Any] + + /** Converts this tree to an `quoted.Expr[T]` if the tree is a valid expression or throws. */ + def asExprOf[T](using Type[T]): Expr[T] + + /** Changes the owner of the symbols in the tree. */ + def changeOwner(newOwner: Symbol): Tree + +} +object Tree { + + def quoted(using quotes: Quotes): Tree.Module = quotes.reflectV2.Tree + given moduleConversion: (quotes: Quotes) => Conversion[Tree.type, Tree.Module] = _ => quotes.reflectV2.Tree + + trait Module private[compiletime] () {} + +} + +/////// PackageClause /////////////////////////////////////////////////////////////// + +/** + * Tree representing a package clause in the source code + * + * ```scala sc:nocompile + * package foo { + * // package stats + * } + * ``` + * + * or + * + * ```scala sc:nocompile + * package foo.bar + * // package stats + * ``` + */ +trait PackageClause private[compiletime] () extends Tree { + + /** Tree containing the package name. */ + def pid: Ref + + /** Definitions, imports or exports within the package. */ + def stats: List[Tree] +} +object PackageClause { + + def quoted(using quotes: Quotes): PackageClause.Module = quotes.reflectV2.PackageClause + given moduleConversion: (quotes: Quotes) => Conversion[PackageClause.type, PackageClause.Module] = _ => quotes.reflectV2.PackageClause + + def unapply(tree: PackageClause): (Ref, List[Tree]) = (tree.pid, tree.stats) + + trait Module private[compiletime] () { + + /** Creates a package clause `package pid { stats }`. */ + def apply(pid: Ref, stats: List[Tree]): PackageClause + + /** Creates a package clause `package pid { stats }`. */ + def make(pid: Ref, stats: List[Tree]): PackageClause + } + +} + +/////// Statement /////////////////////////////////////////////////////////////// + +/** Tree representing a statement in the source code. */ +sealed trait Statement private[compiletime] () extends Tree +object Statement { + + def quoted(using quotes: Quotes): Statement.Module = quotes.reflectV2.Statement + given moduleConversion: (quotes: Quotes) => Conversion[Statement.type, Statement.Module] = _ => quotes.reflectV2.Statement + + trait Module private[compiletime] () {} + +} + +/////// Import /////////////////////////////////////////////////////////////// + +/** + * Tree representing an import in the source code. + * + * See also documentation on `Selector`. + */ +trait Import private[compiletime] () extends Statement { + + /** Qualifier of the import. */ + def expr: Term + + /** + * List selectors of the import + * + * See documentation on `Selector` + */ + def selectors: List[Selector] +} +object Import { + + def quoted(using quotes: Quotes): Import.Module = quotes.reflectV2.Import + given moduleConversion: (quotes: Quotes) => Conversion[Import.type, Import.Module] = _ => quotes.reflectV2.Import + + def unapply(tree: Import): (Term, List[Selector]) = (tree.expr, tree.selectors) + + trait Module private[compiletime] () { + + /** Creates an `Import` with the given qualifier and selectors. */ + def apply(expr: Term, selectors: List[Selector]): Import + + /** Creates an `Import` with the given qualifier and selectors. */ + def make(expr: Term, selectors: List[Selector]): Import + } + +} + +/////// Export /////////////////////////////////////////////////////////////// + +/** + * Tree representing an export clause in the source code. + * Export forwarders generated from this clause appear in the same scope. + */ +trait Export private[compiletime] () extends Statement { + + /** Qualifier of the export. */ + def expr: Term + + /** + * List selectors of the export + * + * See documentation on `Selector` + */ + def selectors: List[Selector] +} +object Export { + + def quoted(using quotes: Quotes): Export.Module = quotes.reflectV2.Export + given moduleConversion: (quotes: Quotes) => Conversion[Export.type, Export.Module] = _ => quotes.reflectV2.Export + + def unapply(tree: Export): (Term, List[Selector]) = (tree.expr, tree.selectors) + + trait Module private[compiletime] () {} + +} + +/////// Definition /////////////////////////////////////////////////////////////// + +/** Tree representing a definition in the source code. It can be `ClassDef`, `TypeDef`, `DefDef` or `ValDef`. */ +sealed trait Definition private[compiletime] () extends Statement { + + /** Name of the definition. */ + def name: String +} +object Definition { + + def quoted(using quotes: Quotes): Definition.Module = quotes.reflectV2.Definition + given moduleConversion: (quotes: Quotes) => Conversion[Definition.type, Definition.Module] = _ => quotes.reflectV2.Definition + + trait Module private[compiletime] () {} + +} + +/////// ClassDef /////////////////////////////////////////////////////////////// + +/** Tree representing a class definition. This includes anonymous class definitions and the class of a module object. */ +trait ClassDef private[compiletime] () extends Definition { + + /** The primary constructor of this class. */ + def constructor: DefDef + + /** + * List of extended parent classes or traits. + * The first parent is always a class. + */ + def parents: List[Tree] + + /** + * Self-type of the class + * + * ```scala + * //{ + * type T + * //} + * class C { self: T => + * ??? + * } + * ``` + */ + def self: Option[ValDef] + + /** + * Statements within the class + * + * ```scala + * class C { + * ??? // statements + * } + * ``` + */ + def body: List[Statement] +} +object ClassDef { + + def quoted(using quotes: Quotes): ClassDef.Module = quotes.reflectV2.ClassDef + given moduleConversion: (quotes: Quotes) => Conversion[ClassDef.type, ClassDef.Module] = _ => quotes.reflectV2.ClassDef + + def unapply(cdef: ClassDef): (String, DefDef, List[Tree], Option[ValDef], List[Statement]) = (cdef.name, cdef.constructor, cdef.parents, cdef.self, cdef.body) + + trait Module private[compiletime] () { + + /** + * Creates a class definition tree + * + * @param cls The class symbol. A new class symbol can be created using `Symbol.newClass`. + * @param parents The parents trees class. The trees must align with the parent types of `cls`. + * Parents can be `TypeTree`s if they don't have term parameter, + * otherwise the can be `Term` containing the `New` applied to the parameters of the extended class. + * @param body List of members of the class. The members must align with the members of `cls`. + */ + def apply(cls: Symbol, parents: List[Tree], body: List[Statement]): ClassDef + + /** Creates a class definition tree */ + def make(cls: Symbol, parents: List[Tree], body: List[Statement]): ClassDef + + /** + * Creates the ValDef and ClassDef of a module (equivalent to an `object` declaration in source code). + * + * Equivalent to + * ``` + * def module(module: Symbol, parents: List[Tree], body: List[Statement]): (ValDef, ClassDef) = + * val modCls = module.moduleClass + * val modClassDef = ClassDef(modCls, parents, body) + * val modValDef = ValDef(module, Some(Apply(Select(New(TypeIdent(modCls)), cls.primaryConstructor), Nil))) + * List(modValDef, modClassDef) + * ``` + * + * @param module the module symbol (created using `Symbol.newModule`) + * @param parents parents of the module class + * @param body body of the module class + * @return The module lazy val definition and module class definition. + * These should be added one after the other (in that order) in the body of a class or statements of a block. + * + * @syntax markdown + */ + def module(module: Symbol, parents: List[Tree], body: List[Statement]): (ValDef, ClassDef) + } + +} + +/////// ValOrDefDef /////////////////////////////////////////////////////////////// + +/** + * Tree representing a value or method definition in the source code. + * This includes `def`, `val`, `lazy val`, `var`, `object` and parameter definitions. + */ +sealed trait ValOrDefDef private[compiletime] () extends Definition { + + /** The type tree of this `val` or `def` definition. */ + def tpt: TypeTree + + /** The right-hand side of this `val` or `def` definition. */ + def rhs: Option[Term] +} +object ValOrDefDef { + + def quoted(using quotes: Quotes): ValOrDefDef.Module = quotes.reflectV2.ValOrDefDef + given moduleConversion: (quotes: Quotes) => Conversion[ValOrDefDef.type, ValOrDefDef.Module] = _ => quotes.reflectV2.ValOrDefDef + + trait Module private[compiletime] () {} + +} + +/////// DefDef /////////////////////////////////////////////////////////////// + +/** Tree representing a method definition in the source code. */ +trait DefDef private[compiletime] () extends ValOrDefDef { + + /** List of type and term parameter clauses. */ + def paramss: List[ParamClause] + + /** + * List of leading type parameters or Nil if the method does not have leading type parameters. + * + * Note: Non leading type parameters can be found in extension methods such as + * ```scala + * //{ + * type A + * type T + * //} + * extension (a: A) def f[T]() = ??? + * ``` + */ + def leadingTypeParams: List[TypeDef] + + /** + * List of parameter clauses following the leading type parameters or all clauses. + * Returns all parameter clauses if there are no leading type parameters. + * + * Non leading type parameters can be found in extension methods such as + * ```scala + * //{ + * type T + * type A + * //} + * extension (a: A) def f[T]() = ??? + * ``` + */ + def trailingParamss: List[ParamClause] + + /** List of term parameter clauses. */ + def termParamss: List[TermParamClause] + + /** The tree of the return type of this `def` definition. */ + def returnTpt: TypeTree +} +object DefDef { + + def quoted(using quotes: Quotes): DefDef.Module = quotes.reflectV2.DefDef + given moduleConversion: (quotes: Quotes) => Conversion[DefDef.type, DefDef.Module] = _ => quotes.reflectV2.DefDef + + def unapply(ddef: DefDef): (String, List[ParamClause], TypeTree, Option[Term]) = (ddef.name, ddef.paramss, ddef.returnTpt, ddef.rhs) + + trait Module private[compiletime] () { + + /** + * Creates a method definition `def f[..](...)` with the signature defined in the symbol. + * + * The `rhsFn` is a function that receives references to its parameters, and should return + * `Some` containing the implementation of the method, or `None` if the method has no implementation. + * Any definition directly inside the implementation should have `symbol` as owner. + * + * Use `Symbol.asQuotes` to create the rhs using quoted code. + * + * See also: `Tree.changeOwner` + */ + def apply(symbol: Symbol, rhsFn: List[List[Tree]] => Option[Term]): DefDef + + /** Creates a method definition `def f[..](...)` with the signature defined in the symbol. */ + def make(symbol: Symbol, rhsFn: List[List[Tree]] => Option[Term]): DefDef + } + +} + +/////// ValDef /////////////////////////////////////////////////////////////// + +/** Tree representing a value definition in the source code. This includes `val`, `lazy val`, `var`, `object` and parameter definitions. */ +trait ValDef private[compiletime] () extends ValOrDefDef +object ValDef { + + def quoted(using quotes: Quotes): ValDef.Module = quotes.reflectV2.ValDef + given moduleConversion: (quotes: Quotes) => Conversion[ValDef.type, ValDef.Module] = _ => quotes.reflectV2.ValDef + + def unapply(vdef: ValDef): (String, TypeTree, Option[Term]) = (vdef.name, vdef.tpt, vdef.rhs) + + trait Module private[compiletime] () { + + /** + * Creates a value definition `val x`, `var x` or `lazy val x` with the signature defined in the symbol. + * + * The `rhs` should return `Some` containing the implementation of the method, + * or `None` if the method has no implementation. + * Any definition directly inside the implementation should have `symbol` as owner. + * + * Use `Symbol.asQuotes` to create the rhs using quoted code. + * + * See also: `Tree.changeOwner` + */ + def apply(symbol: Symbol, rhs: Option[Term]): ValDef + + /** Creates a value definition `val x`, `var x` or `lazy val x` with the signature defined in the symbol. */ + def make(symbol: Symbol, rhs: Option[Term]): ValDef + + /** + * Creates a block `{ val = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, "x", rhs1, Flags.Lazy) { x => + * ValDef.let(x.symbol.owner, "y", rhs2, Flags.Mutable) { y => + * // use `x` and `y` + * } + * } + * ``` + * + * @param flags extra flags to with which the symbol should be constructed. Can be `Final | Implicit | Lazy | Mutable | Given | Synthetic` + */ + def let(owner: Symbol, name: String, rhs: Term, flags: Flags)(body: Ref => Term): Term + + /** + * Creates a block `{ val = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, "x", rhs1) { x => + * ValDef.let(x.symbol.owner, "y", rhs2) { y => + * // use `x` and `y` + * } + * } + * ``` + */ + def let(owner: Symbol, name: String, rhs: Term)(body: Ref => Term): Term + + /** + * Creates a block `{ val x = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, rhs1) { x => + * ValDef.let(owner, rhs2) { y => + * // use `x` and `y` + * } + * } + * ``` + */ + def let(owner: Symbol, rhs: Term)(body: Ref => Term): Term + + /** + * Creates a block `{ val x1 = ; ...; val xn = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, rhsList) { xs => + * ... + * } + * ``` + */ + def let(owner: Symbol, terms: List[Term])(body: List[Ref] => Term): Term + } + +} + +/////// TypeDef /////////////////////////////////////////////////////////////// + +/** Tree representing a type (parameter or member) definition in the source code. */ +trait TypeDef private[compiletime] () extends Definition { + + /** The type bounds on the right-hand side of this `type` definition. */ + def rhs: Tree +} +object TypeDef { + + def quoted(using quotes: Quotes): TypeDef.Module = quotes.reflectV2.TypeDef + given moduleConversion: (quotes: Quotes) => Conversion[TypeDef.type, TypeDef.Module] = _ => quotes.reflectV2.TypeDef + + def unapply(tdef: TypeDef): (String, Tree) = (tdef.name, tdef.rhs) + + trait Module private[compiletime] () { + def apply(symbol: Symbol): TypeDef + def make(symbol: Symbol): TypeDef + } + +} + +/////// Term /////////////////////////////////////////////////////////////// + +/** Tree representing an expression in the source code. */ +sealed trait Term private[compiletime] () extends Statement { + + /** TypeRepr of this term. */ + def tpe: TypeRepr + + /** + * Replaces Inlined nodes and InlineProxy references to underlying arguments. + * The resulting tree is useful for inspection of the value or content of a non-inline argument. + * + * Warning: This tree may contain references that are out of scope and should not be used in the generated code. + * This method should only used to port Scala 2 that used to access their outer scope unsoundly. + */ + def underlyingArgument: Term + + /** + * Replaces Ident nodes references to the underlying tree that defined them. + * The resulting tree is useful for inspection of the definition of some bindings. + * + * Warning: This tree may contain references that are out of scope and should not be used in the generated code. + * This method should only used to port Scala 2 that used to access their outer scope unsoundly. + */ + def underlying: Term + + /** Converts a partially applied term into a lambda expression. */ + def etaExpand(owner: Symbol): Term + + /** A unary apply node with given argument: `tree(arg)`. */ + def appliedTo(arg: Term): Term + + /** An apply node with given arguments: `tree(arg, args0, ..., argsN)`. */ + def appliedTo(arg: Term, args: Term*): Term + + /** An apply node with given argument list `tree(args(0), ..., args(args.length - 1))`. */ + def appliedToArgs(args: List[Term]): Apply + + /** + * The current tree applied to given argument lists: + * `tree (argss(0)) ... (argss(argss.length -1))` + */ + def appliedToArgss(argss: List[List[Term]]): Term + + /** The current tree applied to (): `tree()`. */ + def appliedToNone: Apply + + /** The current tree applied to `()` unless the tree's widened type is parameterless or expects type parameters. */ + def ensureApplied: Term + + /** The current tree applied to given type argument: `tree[targ]`. */ + def appliedToType(targ: TypeRepr): Term + + /** The current tree applied to given type arguments: `tree[targ0, ..., targN]`. */ + def appliedToTypes(targs: List[TypeRepr]): Term + + /** The current tree applied to given type argument list: `tree[targs(0), ..., targs(targs.length - 1)]`. */ + def appliedToTypeTrees(targs: List[TypeTree]): Term + + /** A select node that selects the given symbol. */ + def select(sym: Symbol): Select +} +object Term { + + def quoted(using quotes: Quotes): Term.Module = quotes.reflectV2.Term + given moduleConversion: (quotes: Quotes) => Conversion[Term.type, Term.Module] = _ => quotes.reflectV2.Term + + trait Module private[compiletime] () { + + /** + * Returns a term that is functionally equivalent to `t`, + * however if `t` is of the form `((y1, ..., yn) => e2)(e1, ..., en)` + * then it optimizes the top most call by returning `Some` + * with the result of beta-reducing the function application. + * Similarly, all outermost curried function applications will be beta-reduced, if possible. + * Otherwise returns `None`. + * + * To retain semantics the argument `ei` is bound as `val yi = ei` and by-name arguments to `def yi = ei`. + * Some bindings may be elided as an early optimization. + * + * Example: + * ```scala sc:nocompile + * ((a: Int, b: Int) => a + b).apply(x, y) + * ``` + * will be reduced to + * ```scala sc:nocompile + * val a = x + * val b = y + * a + b + * ``` + * + * Generally: + * ```scala sc:nocompile + * ([X1, Y1, ...] => (x1, y1, ...) => ... => [Xn, Yn, ...] => (xn, yn, ...) => f[X1, Y1, ..., Xn, Yn, ...](x1, y1, ..., xn, yn, ...))).apply[Tx1, Ty1, ...](myX1, myY1, ...)....apply[Txn, Tyn, ...](myXn, myYn, ...) + * ``` + * will be reduced to + * ```scala sc:nocompile + * type X1 = Tx1 + * type Y1 = Ty1 + * ... + * val x1 = myX1 + * val y1 = myY1 + * ... + * type Xn = Txn + * type Yn = Tyn + * ... + * val xn = myXn + * val yn = myYn + * ... + * f[X1, Y1, ..., Xn, Yn, ...](x1, y1, ..., xn, yn, ...) + * ``` + */ + def betaReduce(term: Term): Option[Term] + } + +} + +/////// Ref /////////////////////////////////////////////////////////////// + +/** Tree representing a reference to definition. */ +sealed trait Ref private[compiletime] () extends Term +object Ref { + + def quoted(using quotes: Quotes): Ref.Module = quotes.reflectV2.Ref + given moduleConversion: (quotes: Quotes) => Conversion[Ref.type, Ref.Module] = _ => quotes.reflectV2.Ref + + trait Module private[compiletime] () { + + /** A tree representing the same reference as the given type. */ + def term(tp: TermRef): Ref + + /** + * Creates a reference tree from a symbol + * + * If `sym` refers to a class member `foo` in class `C`, + * returns a tree representing `C.this.foo`. + * + * If `sym` refers to an object member `foo` in object C, itself in prefix + * `pre` (which might include `.this`, if it contains a class), + * returns `pre.C.foo`. + * + * If `sym` refers to a local definition `foo`, returns + * a tree representing `foo`. + * + * @note In all cases, the constructed tree should only + * be spliced into the places where such accesses make sense. + * For example, it is incorrect to have `C.this.foo` outside + * the class body of `C`, or have `foo` outside the lexical + * scope for the definition of `foo`. + */ + def apply(sym: Symbol): Ref + + /** Creates a reference tree from a symbol */ + def make(sym: Symbol): Ref + } + +} + +/////// Ident /////////////////////////////////////////////////////////////// + +/** Tree representing a reference to definition with a given name. */ +trait Ident private[compiletime] () extends Ref { + + /** Name of this `Ident`. */ + def name: String +} +object Ident { + + def quoted(using quotes: Quotes): Ident.Module = quotes.reflectV2.Ident + given moduleConversion: (quotes: Quotes) => Conversion[Ident.type, Ident.Module] = _ => quotes.reflectV2.Ident + + /** Matches a term identifier and returns its name. */ + def unapply(tree: Ident): Some[String] = Some(tree.name) + + trait Module private[compiletime] () { + def apply(tmref: TermRef): Term + def make(tmref: TermRef): Term + } + +} + +/////// Wildcard /////////////////////////////////////////////////////////////// + +/** Pattern representing a `_` wildcard. */ +trait Wildcard private[compiletime] () extends Ident +object Wildcard { + + def quoted(using quotes: Quotes): Wildcard.Module = quotes.reflectV2.Wildcard + given moduleConversion: (quotes: Quotes) => Conversion[Wildcard.type, Wildcard.Module] = _ => quotes.reflectV2.Wildcard + + def unapply(wildcard: Wildcard): true = true + + trait Module private[compiletime] () { + + /** Creates a tree representing a `_` wildcard. */ + def apply(): Wildcard + + /** Creates a tree representing a `_` wildcard. */ + def make(): Wildcard + } + +} + +/////// Select /////////////////////////////////////////////////////////////// + +/** Tree representing a selection of definition with a given name on a given prefix. */ +trait Select private[compiletime] () extends Ref { + + /** Qualifier of the `qualifier.name`. */ + def qualifier: Term + + /** Name of this `Select`. */ + def name: String + + /** Signature of this method. */ + def signature: Option[Signature] +} +object Select { + + def quoted(using quotes: Quotes): Select.Module = quotes.reflectV2.Select + given moduleConversion: (quotes: Quotes) => Conversion[Select.type, Select.Module] = _ => quotes.reflectV2.Select + + def unapply(x: Select): (Term, String) = (x.qualifier, x.name) + + trait Module private[compiletime] () { + + /** Selects a term member by symbol. */ + def apply(qualifier: Term, symbol: Symbol): Select + + /** Selects a term member by symbol. */ + def make(qualifier: Term, symbol: Symbol): Select + + /** + * Selects a field or a non-overloaded method by name + * + * @note The method will produce an assertion error if the selected + * method is overloaded. The method `overloaded` should be used + * in that case. + */ + def unique(qualifier: Term, name: String): Select + + /** Calls an overloaded method with the given type and term parameters. */ + def overloaded(qualifier: Term, name: String, targs: List[TypeRepr], args: List[Term]): Term + + /** Calls an overloaded method with the given type and term parameters. */ + def overloaded(qualifier: Term, name: String, targs: List[TypeRepr], args: List[Term], returnType: TypeRepr): Term + } + +} + +/////// Literal /////////////////////////////////////////////////////////////// + +/** Tree representing a literal value in the source code. */ +trait Literal private[compiletime] () extends Term { + + /** Value of this literal. */ + def constant: Constant +} +object Literal { + + def quoted(using quotes: Quotes): Literal.Module = quotes.reflectV2.Literal + given moduleConversion: (quotes: Quotes) => Conversion[Literal.type, Literal.Module] = _ => quotes.reflectV2.Literal + + def unapply(x: Literal): Some[Constant] = Some(x.constant) + + trait Module private[compiletime] () { + + /** Creates a literal constant. */ + def apply(constant: Constant): Literal + + /** Creates a literal constant. */ + def make(constant: Constant): Literal + } + +} + +/////// This /////////////////////////////////////////////////////////////// + +/** Tree representing `this` or `C.this` in the source code. */ +trait This private[compiletime] () extends Term { + + /** + * Returns `C` if the underlying tree is of the form `C.this` + * + * Otherwise, return `None`. + */ + def id: Option[String] +} +object This { + + def quoted(using quotes: Quotes): This.Module = quotes.reflectV2.This + given moduleConversion: (quotes: Quotes) => Conversion[This.type, This.Module] = _ => quotes.reflectV2.This + + def unapply(x: This): Some[Option[String]] = Some(x.id) + + trait Module private[compiletime] () { + + /** Creates a `C.this` for `C` pointing to `cls`. */ + def apply(cls: Symbol): This + + /** Creates a `C.this` for `C` pointing to `cls`. */ + def make(cls: Symbol): This + } + +} + +/////// New /////////////////////////////////////////////////////////////// + +/** Tree representing `new` in the source code. */ +trait New private[compiletime] () extends Term { + + /** Returns the type tree of this `new`. */ + def tpt: TypeTree +} +object New { + + def quoted(using quotes: Quotes): New.Module = quotes.reflectV2.New + given moduleConversion: (quotes: Quotes) => Conversion[New.type, New.Module] = _ => quotes.reflectV2.New + + def unapply(x: New): Some[TypeTree] = Some(x.tpt) + + trait Module private[compiletime] () { + + /** Creates a `new `. */ + def apply(tpt: TypeTree): New + + /** Creates a `new `. */ + def make(tpt: TypeTree): New + } + +} + +/////// NamedArg /////////////////////////////////////////////////////////////// + +/** Tree representing an argument passed with an explicit name. Such as `arg1 = x` in `foo(arg1 = x)`. */ +trait NamedArg private[compiletime] () extends Term { + + /** The name part of `name = arg`. */ + def name: String + + /** The argument part of `name = arg`. */ + def value: Term +} +object NamedArg { + + def quoted(using quotes: Quotes): NamedArg.Module = quotes.reflectV2.NamedArg + given moduleConversion: (quotes: Quotes) => Conversion[NamedArg.type, NamedArg.Module] = _ => quotes.reflectV2.NamedArg + + def unapply(x: NamedArg): (String, Term) = (x.name, x.value) + + trait Module private[compiletime] () { + + /** Creates a named argument ` = `. */ + def apply(name: String, arg: Term): NamedArg + + /** Creates a named argument ` = `. */ + def make(name: String, arg: Term): NamedArg + } + +} + +/////// Apply /////////////////////////////////////////////////////////////// + +/** + * Tree representing an application of arguments. + * It represents a single list of arguments, multiple argument lists will have nested `Apply`s + */ +trait Apply private[compiletime] () extends Term { + + /** + * The `fun` part of an (implicit) application like `fun(args)` + * + * It may be a partially applied method: + * ```scala + * def f(x1: Int)(x2: Int) = ??? + * f(1)(2) + * ``` + * - `fun` is `f(1)` in the `Apply` of `f(1)(2)` + * - `fun` is `f` in the `Apply` of `f(1)` + */ + def fun: Term + + /** + * The arguments (implicitly) passed to the method + * + * The `Apply` may be a partially applied method: + * ```scala + * def f(x1: Int)(x2: Int) = ??? + * f(1)(2) + * ``` + * - `args` is `(2)` in the `Apply` of `f(1)(2)` + * - `args` is `(1)` in the `Apply` of `f(1)` + */ + def args: List[Term] +} +object Apply { + + def quoted(using quotes: Quotes): Apply.Module = quotes.reflectV2.Apply + given moduleConversion: (quotes: Quotes) => Conversion[Apply.type, Apply.Module] = _ => quotes.reflectV2.Apply + + def unapply(x: Apply): (Term, List[Term]) = (x.fun, x.args) + + trait Module private[compiletime] () { + + /** Creates a function application `()`. */ + def apply(fun: Term, args: List[Term]): Apply + + /** Creates a function application `()`. */ + def make(fun: Term, args: List[Term]): Apply + } + +} + +/////// TypeApply /////////////////////////////////////////////////////////////// + +/** Tree representing an application of type arguments. */ +trait TypeApply private[compiletime] () extends Term { + + /** + * The `fun` part of an (inferred) type application like `fun[Args]` + * + * It may be a partially applied method: + * ```scala + * //{ + * type T + * //} + * extension (x: Int) def f[T](y: T) = ??? + * // represented as + * // def f(x: Int)[T](y: T) = ??? + * + * 1.f[Int](2) + * // represented as + * // f(1)[Int](2) + * ``` + * - `fun` is `f(1)` in the `TypeApply` of `f(1)[Int]` + */ + def fun: Term + + /** + * The (inferred) type arguments passed to the method + * + * The `TypeApply` may be a partially applied method: + * ```scala + * //{ + * type T + * //} + * extension (x: Int) def f[T](y: T) = ??? + * // represented as + * // def f(x: Int)[T](y: T) = ??? + * + * 1.f[Int](2) + * // represented as + * // f(1)[Int](2) + * ``` + * - `fun` is `[Int]` in the `TypeApply` of `f(1)[Int]` + */ + def args: List[TypeTree] +} +object TypeApply { + + def quoted(using quotes: Quotes): TypeApply.Module = quotes.reflectV2.TypeApply + given moduleConversion: (quotes: Quotes) => Conversion[TypeApply.type, TypeApply.Module] = _ => quotes.reflectV2.TypeApply + + def unapply(x: TypeApply): (Term, List[TypeTree]) = (x.fun, x.args) + + trait Module private[compiletime] () { + + /** Creates a function type application `[]`. */ + def apply(fun: Term, args: List[TypeTree]): TypeApply + + /** Creates a function type application `[]`. */ + def make(fun: Term, args: List[TypeTree]): TypeApply + } + +} + +/////// Super /////////////////////////////////////////////////////////////// + +/** Tree representing `super` in the source code. */ +trait Super private[compiletime] () extends Term { + def qualifier: Term + def id: Option[String] + def idPos: Position +} +object Super { + + def quoted(using quotes: Quotes): Super.Module = quotes.reflectV2.Super + given moduleConversion: (quotes: Quotes) => Conversion[Super.type, Super.Module] = _ => quotes.reflectV2.Super + + def unapply(x: Super): (Term, Option[String]) = (x.qualifier, x.id) + + trait Module private[compiletime] () { + + /** Creates a `.super[`. */ + def apply(qual: Term, mix: Option[String]): Super + + /** Creates a `.super[`. */ + def make(qual: Term, mix: Option[String]): Super + } + +} + +/////// Typed /////////////////////////////////////////////////////////////// + +/** + * Tree representing a type ascription `x: T` in the source code. + * + * Also represents a pattern that contains a term `x`. + * Other `: T` patterns use the more general `TypedOrTest`. + */ +trait Typed private[compiletime] () extends Term, TypedOrTest { + def expr: Term + def tpt: TypeTree +} +object Typed { + + def quoted(using quotes: Quotes): Typed.Module = quotes.reflectV2.Typed + given moduleConversion: (quotes: Quotes) => Conversion[Typed.type, Typed.Module] = _ => quotes.reflectV2.Typed + + def unapply(x: Typed): (Term, TypeTree) = (x.expr, x.tpt) + + trait Module private[compiletime] () { + + /** Creates a type ascription `: `. */ + def apply(expr: Term, tpt: TypeTree): Typed + + /** Creates a type ascription `: `. */ + def make(expr: Term, tpt: TypeTree): Typed + } + +} + +/////// Assign /////////////////////////////////////////////////////////////// + +/** Tree representing an assignment `x = y` in the source code. */ +trait Assign private[compiletime] () extends Term { + def lhs: Term + def rhs: Term +} +object Assign { + + def quoted(using quotes: Quotes): Assign.Module = quotes.reflectV2.Assign + given moduleConversion: (quotes: Quotes) => Conversion[Assign.type, Assign.Module] = _ => quotes.reflectV2.Assign + + def unapply(x: Assign): (Term, Term) = (x.lhs, x.rhs) + + trait Module private[compiletime] () { + + /** Creates an assignment ` = `. */ + def apply(lhs: Term, rhs: Term): Assign + + /** Creates an assignment ` = `. */ + def make(lhs: Term, rhs: Term): Assign + } + +} + +/////// Block /////////////////////////////////////////////////////////////// + +/** Tree representing a block `{ ... }` in the source code. */ +trait Block private[compiletime] () extends Term { + def statements: List[Statement] + def expr: Term +} +object Block { + + def quoted(using quotes: Quotes): Block.Module = quotes.reflectV2.Block + given moduleConversion: (quotes: Quotes) => Conversion[Block.type, Block.Module] = _ => quotes.reflectV2.Block + + def unapply(x: Block): (List[Statement], Term) = (x.statements, x.expr) + + trait Module private[compiletime] () { + + /** Creates a block `{ ; }`. */ + def apply(stats: List[Statement], expr: Term): Block + + /** Creates a block `{ ; }`. */ + def make(stats: List[Statement], expr: Term): Block + } + +} + +/////// Closure /////////////////////////////////////////////////////////////// + +/** + * A lambda `(...) => ...` in the source code is represented as + * a local method and a closure: + * + * { + * def m(...) = ... + * closure(m) + * } + */ +trait Closure private[compiletime] () extends Term { + def meth: Term + def tpeOpt: Option[TypeRepr] +} +object Closure { + + def quoted(using quotes: Quotes): Closure.Module = quotes.reflectV2.Closure + given moduleConversion: (quotes: Quotes) => Conversion[Closure.type, Closure.Module] = _ => quotes.reflectV2.Closure + + def unapply(x: Closure): (Term, Option[TypeRepr]) = (x.meth, x.tpeOpt) + + trait Module private[compiletime] () { + def apply(meth: Term, tpe: Option[TypeRepr]): Closure + def make(meth: Term, tpe: Option[TypeRepr]): Closure + } + +} + +/////// Lambda /////////////////////////////////////////////////////////////// + +/** + * A lambda `(...) => ...` in the source code is represented as + * a local method and a closure: + * + * ```scala sc:nocompile + * { + * def m(...) = ... + * closure(m) + * } + * ``` + * @note Due to the encoding, in pattern matches the case for `Lambda` + * should come before the case for `Block` to avoid mishandling + * of `Lambda`. + */ +object Lambda { + + def quoted(using quotes: Quotes): Lambda.Module = quotes.reflectV2.Lambda + given moduleConversion: (quotes: Quotes) => Conversion[Lambda.type, Lambda.Module] = _ => quotes.reflectV2.Lambda + + trait Module private[compiletime] () { + + /** + * Matches a lambda definition of the form + * ```scala sc:nocompile + * Block((DefDef(_, _, params :: Nil, _, Some(body))) :: Nil, Closure(meth, _)) + * ``` + * Extracts the parameter definitions and body. + */ + def unapply(tree: Block): Option[(List[ValDef], Term)] + + /** + * Generates a lambda with the given method type. + * ```scala sc:nocompile + * Block((DefDef(_, _, params :: Nil, _, Some(rhsFn(meth, paramRefs)))) :: Nil, Closure(meth, _)) + * ``` + * + * Usage: + * ``` + * val mtpe = MethodType(List("arg1"))(_ => List(TypeRepr.of[Int]), _ => TypeRepr.of[Int]) + * Lambda(owner, mtpe, { + * case (methSym, List(arg1: Term)) => + * ValDef.let(methSym, f(arg1)) { ... } + * } + * ) + * ``` + * + * Usage with quotes: + * ``` + * val mtpe = MethodType(List("arg1"))(_ => List(TypeRepr.of[Int]), _ => TypeRepr.of[Int]) + * Lambda(owner, mtpe, { + * case (methSym, List(arg1: Term)) => + * given Quotes = methSym.asQuotes + * '{ ... } + * } + * ) + * ``` + * + * @param owner owner of the generated `meth` symbol + * @param tpe Type of the definition + * @param rhsFn Function that receives the `meth` symbol and the a list of references to the `params` + */ + def apply(owner: Symbol, tpe: MethodType, rhsFn: (Symbol, List[Tree]) => Tree): Block + + /** Generates a lambda with the given method type. */ + def make(owner: Symbol, tpe: MethodType, rhsFn: (Symbol, List[Tree]) => Tree): Block + } + +} + +/////// If /////////////////////////////////////////////////////////////// + +/** Tree representing an if/then/else `if (...) ... else ...` in the source code. */ +trait If private[compiletime] () extends Term { + def cond: Term + def thenp: Term + def elsep: Term + def isInline: Boolean +} +object If { + + def quoted(using quotes: Quotes): If.Module = quotes.reflectV2.If + given moduleConversion: (quotes: Quotes) => Conversion[If.type, If.Module] = _ => quotes.reflectV2.If + + def unapply(tree: If): (Term, Term, Term) = (tree.cond, tree.thenp, tree.elsep) + + trait Module private[compiletime] () { + + /** Creates an if/then/else `if () else `. */ + def apply(cond: Term, thenp: Term, elsep: Term): If + + /** Creates an if/then/else `if () else `. */ + def make(cond: Term, thenp: Term, elsep: Term): If + } + +} + +/////// Match /////////////////////////////////////////////////////////////// + +/** Tree representing a pattern match `x match { ... }` in the source code. */ +trait Match private[compiletime] () extends Term { + def scrutinee: Term + def cases: List[CaseDef] + def isInline: Boolean +} +object Match { + + def quoted(using quotes: Quotes): Match.Module = quotes.reflectV2.Match + given moduleConversion: (quotes: Quotes) => Conversion[Match.type, Match.Module] = _ => quotes.reflectV2.Match + + def unapply(x: Match): (Term, List[CaseDef]) = (x.scrutinee, x.cases) + + trait Module private[compiletime] () { + + /** Creates a pattern match ` match { }`. */ + def apply(selector: Term, cases: List[CaseDef]): Match + + /** Creates a pattern match ` match { }`. */ + def make(selector: Term, cases: List[CaseDef]): Match + } + +} + +/////// SummonFrom /////////////////////////////////////////////////////////////// + +/** Tree representing a summoning match `summonFrom { ... }` in the source code. */ +trait SummonFrom private[compiletime] () extends Term { + def cases: List[CaseDef] +} +object SummonFrom { + + def quoted(using quotes: Quotes): SummonFrom.Module = quotes.reflectV2.SummonFrom + given moduleConversion: (quotes: Quotes) => Conversion[SummonFrom.type, SummonFrom.Module] = _ => quotes.reflectV2.SummonFrom + + def unapply(x: SummonFrom): Some[List[CaseDef]] = Some(x.cases) + + trait Module private[compiletime] () { + + /** Creates a pattern match `given match { }`. */ + def apply(cases: List[CaseDef]): SummonFrom + + /** Creates a pattern match `given match { }`. */ + def make(cases: List[CaseDef]): SummonFrom + } + +} + +/////// Try /////////////////////////////////////////////////////////////// + +/** Tree representing a try catch `try x catch { ... } finally { ... }` in the source code. */ +trait Try private[compiletime] () extends Term { + def body: Term + def cases: List[CaseDef] + def finalizer: Option[Term] +} +object Try { + + def quoted(using quotes: Quotes): Try.Module = quotes.reflectV2.Try + given moduleConversion: (quotes: Quotes) => Conversion[Try.type, Try.Module] = _ => quotes.reflectV2.Try + + def unapply(x: Try): (Term, List[CaseDef], Option[Term]) = (x.body, x.cases, x.finalizer) + + trait Module private[compiletime] () { + + /** Creates a try/catch `try catch { } finally `. */ + def apply(expr: Term, cases: List[CaseDef], finalizer: Option[Term]): Try + + /** Creates a try/catch `try catch { } finally `. */ + def make(expr: Term, cases: List[CaseDef], finalizer: Option[Term]): Try + } + +} + +/////// Return /////////////////////////////////////////////////////////////// + +/** Tree representing a `return` in the source code. */ +trait Return private[compiletime] () extends Term { + def expr: Term + def from: Symbol +} +object Return { + + def quoted(using quotes: Quotes): Return.Module = quotes.reflectV2.Return + given moduleConversion: (quotes: Quotes) => Conversion[Return.type, Return.Module] = _ => quotes.reflectV2.Return + + def unapply(x: Return): (Term, Symbol) = (x.expr, x.from) + + trait Module private[compiletime] () { + + /** Creates `return `. */ + def apply(expr: Term, from: Symbol): Return + + /** Creates `return `. */ + def make(expr: Term, from: Symbol): Return + } + +} + +/////// Repeated /////////////////////////////////////////////////////////////// + +/** + * Tree representing a variable argument list in the source code. + * + * This tree is used to encode varargs terms. The Repeated encapsulates + * the sequence of the elements but needs to be wrapped in a + * `scala.[T]` (see `defn.RepeatedParamClass`). For example the + * arguments `1, 2` of `List.apply(1, 2)` can be represented as follows: + * + * ```scala + * //{ + * import scala.quoted._ + * def inQuotes(using Quotes) = { + * val q: Quotes = summon[Quotes] + * import q.reflect._ + * //} + * val intArgs = List(Literal(IntConstant(1)), Literal(IntConstant(2))) + * Typed( + * Repeated(intArgs, TypeTree.of[Int]), + * Inferred(defn.RepeatedParamClass.typeRef.appliedTo(TypeRepr.of[Int])) + * ) + * //{ + * } + * //} + * ``` + */ +trait Repeated private[compiletime] () extends Term { + def elems: List[Term] + def elemtpt: TypeTree +} +object Repeated { + + def quoted(using quotes: Quotes): Repeated.Module = quotes.reflectV2.Repeated + given moduleConversion: (quotes: Quotes) => Conversion[Repeated.type, Repeated.Module] = _ => quotes.reflectV2.Repeated + + def unapply(x: Repeated): (List[Term], TypeTree) = (x.elems, x.elemtpt) + + trait Module private[compiletime] () { + + /** Creates a literal sequence of elements. */ + def apply(elems: List[Term], tpt: TypeTree): Repeated + + /** Creates a literal sequence of elements. */ + def make(elems: List[Term], tpt: TypeTree): Repeated + } + +} + +/////// Inlined /////////////////////////////////////////////////////////////// + +/** Tree representing the scope of an inlined tree. */ +trait Inlined private[compiletime] () extends Term { + def call: Option[Tree] + def bindings: List[Definition] + def body: Term +} +object Inlined { + + def quoted(using quotes: Quotes): Inlined.Module = quotes.reflectV2.Inlined + given moduleConversion: (quotes: Quotes) => Conversion[Inlined.type, Inlined.Module] = _ => quotes.reflectV2.Inlined + + def unapply(x: Inlined): (Option[Tree], List[Definition], Term) = (x.call, x.bindings, x.body) + + trait Module private[compiletime] () { + def apply(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined + def make(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined + } + +} + +/////// SelectOuter /////////////////////////////////////////////////////////////// + +/** Tree representing a selection of definition with a given name on a given prefix and number of nested scopes of inlined trees. */ +trait SelectOuter private[compiletime] () extends Term { + def qualifier: Term + def name: String + def level: Int +} +object SelectOuter { + + def quoted(using quotes: Quotes): SelectOuter.Module = quotes.reflectV2.SelectOuter + given moduleConversion: (quotes: Quotes) => Conversion[SelectOuter.type, SelectOuter.Module] = _ => quotes.reflectV2.SelectOuter + + def unapply(x: SelectOuter): (Term, String, Int) = (x.qualifier, x.name, x.level) + + trait Module private[compiletime] () { + def apply(qualifier: Term, name: String, levels: Int): SelectOuter + def make(qualifier: Term, name: String, levels: Int): SelectOuter + } + +} + +/////// While /////////////////////////////////////////////////////////////// + +/** Tree representing a while loop. */ +trait While private[compiletime] () extends Term { + def cond: Term + def body: Term +} +object While { + + def quoted(using quotes: Quotes): While.Module = quotes.reflectV2.While + given moduleConversion: (quotes: Quotes) => Conversion[While.type, While.Module] = _ => quotes.reflectV2.While + + def unapply(x: While): (Term, Term) = (x.cond, x.body) + + trait Module private[compiletime] () { + + /** Creates a while loop `while () ` and returns (, ). */ + def apply(cond: Term, body: Term): While + + /** Creates a while loop `while () ` and returns (, ). */ + def make(cond: Term, body: Term): While + } + +} + +/////// TypedOrTest /////////////////////////////////////////////////////////////// + +/** Tree representing a type ascription or type test pattern `x: T` in the source code. */ +sealed trait TypedOrTest private[compiletime] () extends Tree { + def tree: Tree + def tpt: TypeTree +} +object TypedOrTest { + + def quoted(using quotes: Quotes): TypedOrTest.Module = quotes.reflectV2.TypedOrTest + given moduleConversion: (quotes: Quotes) => Conversion[TypedOrTest.type, TypedOrTest.Module] = _ => quotes.reflectV2.TypedOrTest + + def unapply(x: TypedOrTest): (Tree, TypeTree) = (x.tree, x.tpt) + + trait Module private[compiletime] () { + + /** Creates a type ascription `: `. */ + def apply(expr: Tree, tpt: TypeTree): TypedOrTest + + /** Creates a type ascription `: `. */ + def make(expr: Tree, tpt: TypeTree): TypedOrTest + } + +} + +/////// TypeTree /////////////////////////////////////////////////////////////// + +/** Type tree representing a type written in the source. */ +sealed trait TypeTree private[compiletime] () extends Tree { + + /** TypeRepr of this type tree. */ + def tpe: TypeRepr +} +object TypeTree { + + def quoted(using quotes: Quotes): TypeTree.Module = quotes.reflectV2.TypeTree + given moduleConversion: (quotes: Quotes) => Conversion[TypeTree.type, TypeTree.Module] = _ => quotes.reflectV2.TypeTree + + trait Module private[compiletime] () { + + /** Returns the tree of type or kind (TypeTree) of T. */ + def of[T <: AnyKind](using Type[T]): TypeTree + + /** + * Returns a type tree reference to the symbol + * + * @param typeSymbol The type symbol for which we are creating a type tree reference. + */ + def ref(typeSymbol: Symbol): TypeTree + } + +} + +/////// Inferred /////////////////////////////////////////////////////////////// + +/** Type tree representing an inferred type. */ +trait Inferred private[compiletime] () extends TypeTree +object Inferred { + + def quoted(using quotes: Quotes): Inferred.Module = quotes.reflectV2.Inferred + given moduleConversion: (quotes: Quotes) => Conversion[Inferred.type, Inferred.Module] = _ => quotes.reflectV2.Inferred + + def unapply(x: Inferred): true = true + + trait Module private[compiletime] () { + def apply(tpe: TypeRepr): Inferred + def make(tpe: TypeRepr): Inferred + } + +} + +/////// TypeIdent /////////////////////////////////////////////////////////////// + +/** Type tree representing a reference to definition with a given name. */ +trait TypeIdent private[compiletime] () extends TypeTree { + def name: String +} +object TypeIdent { + + def quoted(using quotes: Quotes): TypeIdent.Module = quotes.reflectV2.TypeIdent + given moduleConversion: (quotes: Quotes) => Conversion[TypeIdent.type, TypeIdent.Module] = _ => quotes.reflectV2.TypeIdent + + def unapply(x: TypeIdent): Some[String] = Some(x.name) + + trait Module private[compiletime] () { + def apply(sym: Symbol): TypeTree + def make(sym: Symbol): TypeTree + } + +} + +/////// TypeSelect /////////////////////////////////////////////////////////////// + +/** Type tree representing a selection of definition with a given name on a given term prefix. */ +trait TypeSelect private[compiletime] () extends TypeTree { + def qualifier: Term + def name: String +} +object TypeSelect { + + def quoted(using quotes: Quotes): TypeSelect.Module = quotes.reflectV2.TypeSelect + given moduleConversion: (quotes: Quotes) => Conversion[TypeSelect.type, TypeSelect.Module] = _ => quotes.reflectV2.TypeSelect + + def unapply(x: TypeSelect): (Term, String) = (x.qualifier, x.name) + + trait Module private[compiletime] () { + def apply(qualifier: Term, name: String): TypeSelect + def make(qualifier: Term, name: String): TypeSelect + } + +} + +/////// TypeProjection /////////////////////////////////////////////////////////////// + +/** Type tree representing a selection of definition with a given name on a given type prefix. */ +trait TypeProjection private[compiletime] () extends TypeTree { + def qualifier: TypeTree + def name: String +} +object TypeProjection { + + def quoted(using quotes: Quotes): TypeProjection.Module = quotes.reflectV2.TypeProjection + given moduleConversion: (quotes: Quotes) => Conversion[TypeProjection.type, TypeProjection.Module] = _ => quotes.reflectV2.TypeProjection + + def unapply(x: TypeProjection): (TypeTree, String) = (x.qualifier, x.name) + + trait Module private[compiletime] () { + def apply(qualifier: TypeTree, name: String): TypeProjection + def make(qualifier: TypeTree, name: String): TypeProjection + } + +} + +/////// Singleton /////////////////////////////////////////////////////////////// + +/** Type tree representing a singleton type. */ +trait Singleton private[compiletime] () extends TypeTree { + def ref: Term +} +object Singleton { + + def quoted(using quotes: Quotes): Singleton.Module = quotes.reflectV2.Singleton + given moduleConversion: (quotes: Quotes) => Conversion[Singleton.type, Singleton.Module] = _ => quotes.reflectV2.Singleton + + def unapply(x: Singleton): Some[Term] = Some(x.ref) + + trait Module private[compiletime] () { + def apply(ref: Term): Singleton + def make(ref: Term): Singleton + } + +} + +/////// Refined /////////////////////////////////////////////////////////////// + +/** Type tree representing a type refinement. */ +trait Refined private[compiletime] () extends TypeTree { + def tpt: TypeTree + def refinements: List[Definition] +} +object Refined { + + def quoted(using quotes: Quotes): Refined.Module = quotes.reflectV2.Refined + given moduleConversion: (quotes: Quotes) => Conversion[Refined.type, Refined.Module] = _ => quotes.reflectV2.Refined + + def unapply(x: Refined): (TypeTree, List[Definition]) = (x.tpt, x.refinements) + + trait Module private[compiletime] () { + + /** + * Creates and types a Refined AST node. + * @param tpt - parent type being refined + * @param refinements - List of definitions represesenting refinements + * @param refineCls - symbol of the class of which the refinement definitions originally come from + * @return + */ + def apply(tpt: TypeTree, refinements: List[Definition], refineCls: Symbol): Refined + + /** Creates and types a Refined AST node. */ + def make(tpt: TypeTree, refinements: List[Definition], refineCls: Symbol): Refined + } + +} + +/////// Applied /////////////////////////////////////////////////////////////// + +/** Type tree representing a type application. */ +trait Applied private[compiletime] () extends TypeTree { + def tpt: TypeTree + def args: List[Tree] +} +object Applied { + + def quoted(using quotes: Quotes): Applied.Module = quotes.reflectV2.Applied + given moduleConversion: (quotes: Quotes) => Conversion[Applied.type, Applied.Module] = _ => quotes.reflectV2.Applied + + def unapply(x: Applied): (TypeTree, List[Tree]) = (x.tpt, x.args) + + trait Module private[compiletime] () { + def apply(tpt: TypeTree, args: List[Tree]): Applied + def make(tpt: TypeTree, args: List[Tree]): Applied + } + +} + +/////// Annotated /////////////////////////////////////////////////////////////// + +/** Type tree representing an annotated type. */ +trait Annotated private[compiletime] () extends TypeTree { + def arg: TypeTree + def annotation: Term +} +object Annotated { + + def quoted(using quotes: Quotes): Annotated.Module = quotes.reflectV2.Annotated + given moduleConversion: (quotes: Quotes) => Conversion[Annotated.type, Annotated.Module] = _ => quotes.reflectV2.Annotated + + def unapply(x: Annotated): (TypeTree, Term) = (x.arg, x.annotation) + + trait Module private[compiletime] () { + def apply(arg: TypeTree, annotation: Term): Annotated + def make(arg: TypeTree, annotation: Term): Annotated + } + +} + +/////// MatchTypeTree /////////////////////////////////////////////////////////////// + +/** Type tree representing a type match. */ +trait MatchTypeTree private[compiletime] () extends TypeTree { + def bound: Option[TypeTree] + def selector: TypeTree + def cases: List[TypeCaseDef] +} +object MatchTypeTree { + + def quoted(using quotes: Quotes): MatchTypeTree.Module = quotes.reflectV2.MatchTypeTree + given moduleConversion: (quotes: Quotes) => Conversion[MatchTypeTree.type, MatchTypeTree.Module] = _ => quotes.reflectV2.MatchTypeTree + + def unapply(x: MatchTypeTree): (Option[TypeTree], TypeTree, List[TypeCaseDef]) = (x.bound, x.selector, x.cases) + + trait Module private[compiletime] () { + def apply(bound: Option[TypeTree], selector: TypeTree, cases: List[TypeCaseDef]): MatchTypeTree + def make(bound: Option[TypeTree], selector: TypeTree, cases: List[TypeCaseDef]): MatchTypeTree + } + +} + +/////// ByName /////////////////////////////////////////////////////////////// + +/** Type tree representing a by name parameter. */ +trait ByName private[compiletime] () extends TypeTree { + def result: TypeTree +} +object ByName { + + def quoted(using quotes: Quotes): ByName.Module = quotes.reflectV2.ByName + given moduleConversion: (quotes: Quotes) => Conversion[ByName.type, ByName.Module] = _ => quotes.reflectV2.ByName + + def unapply(x: ByName): Some[TypeTree] = Some(x.result) + + trait Module private[compiletime] () { + def apply(result: TypeTree): ByName + def make(result: TypeTree): ByName + } + +} + +/////// LambdaTypeTree /////////////////////////////////////////////////////////////// + +/** Type tree representing a lambda abstraction type. */ +trait LambdaTypeTree private[compiletime] () extends TypeTree { + def tparams: List[TypeDef] + def body: Tree +} +object LambdaTypeTree { + + def quoted(using quotes: Quotes): LambdaTypeTree.Module = quotes.reflectV2.LambdaTypeTree + given moduleConversion: (quotes: Quotes) => Conversion[LambdaTypeTree.type, LambdaTypeTree.Module] = _ => quotes.reflectV2.LambdaTypeTree + + def unapply(tree: LambdaTypeTree): (List[TypeDef], Tree) = (tree.tparams, tree.body) + + trait Module private[compiletime] () { + def apply(tparams: List[TypeDef], body: Tree): LambdaTypeTree + def make(tparams: List[TypeDef], body: Tree): LambdaTypeTree + } + +} + +/////// TypeBind /////////////////////////////////////////////////////////////// + +/** Type tree representing a type binding. */ +trait TypeBind private[compiletime] () extends TypeTree { + def name: String + def body: Tree +} +object TypeBind { + + def quoted(using quotes: Quotes): TypeBind.Module = quotes.reflectV2.TypeBind + given moduleConversion: (quotes: Quotes) => Conversion[TypeBind.type, TypeBind.Module] = _ => quotes.reflectV2.TypeBind + + def unapply(x: TypeBind): (String, Tree) = (x.name, x.body) + + trait Module private[compiletime] () {} + +} + +/////// TypeBlock /////////////////////////////////////////////////////////////// + +/** Type tree within a block with aliases `{ type U1 = ... ; T[U1, U2] }`. */ +trait TypeBlock private[compiletime] () extends TypeTree { + def aliases: List[TypeDef] + def tpt: TypeTree +} +object TypeBlock { + + def quoted(using quotes: Quotes): TypeBlock.Module = quotes.reflectV2.TypeBlock + given moduleConversion: (quotes: Quotes) => Conversion[TypeBlock.type, TypeBlock.Module] = _ => quotes.reflectV2.TypeBlock + + def unapply(x: TypeBlock): (List[TypeDef], TypeTree) = (x.aliases, x.tpt) + + trait Module private[compiletime] () { + def apply(aliases: List[TypeDef], tpt: TypeTree): TypeBlock + def make(aliases: List[TypeDef], tpt: TypeTree): TypeBlock + } + +} + +/////// TypeBoundsTree /////////////////////////////////////////////////////////////// + +/** Type tree representing a type bound written in the source. */ +trait TypeBoundsTree private[compiletime] () extends Tree { + def tpe: TypeBounds + def low: TypeTree + def hi: TypeTree +} +object TypeBoundsTree { + + def quoted(using quotes: Quotes): TypeBoundsTree.Module = quotes.reflectV2.TypeBoundsTree + given moduleConversion: (quotes: Quotes) => Conversion[TypeBoundsTree.type, TypeBoundsTree.Module] = _ => quotes.reflectV2.TypeBoundsTree + + def unapply(x: TypeBoundsTree): (TypeTree, TypeTree) = (x.low, x.hi) + + trait Module private[compiletime] () { + def apply(low: TypeTree, hi: TypeTree): TypeBoundsTree + def make(low: TypeTree, hi: TypeTree): TypeBoundsTree + } + +} + +/////// WildcardTypeTree /////////////////////////////////////////////////////////////// + +/** + * Type tree representing wildcard type bounds written in the source. + * The wildcard type `?` (for example in in `List[?]`) will be a type tree that + * represents a type but has `TypeBounds` inside. + */ +trait WildcardTypeTree private[compiletime] () extends Tree { + def tpe: TypeRepr +} +object WildcardTypeTree { + + def quoted(using quotes: Quotes): WildcardTypeTree.Module = quotes.reflectV2.WildcardTypeTree + given moduleConversion: (quotes: Quotes) => Conversion[WildcardTypeTree.type, WildcardTypeTree.Module] = _ => quotes.reflectV2.WildcardTypeTree + + def unapply(x: WildcardTypeTree): true = true + + trait Module private[compiletime] () { + def apply(tpe: TypeRepr): WildcardTypeTree + def make(tpe: TypeRepr): WildcardTypeTree + } + +} + +/////// CaseDef /////////////////////////////////////////////////////////////// + +/** Branch of a pattern match or catch clause. */ +trait CaseDef private[compiletime] () extends Tree { + def pattern: Tree + def guard: Option[Term] + def rhs: Term +} +object CaseDef { + + def quoted(using quotes: Quotes): CaseDef.Module = quotes.reflectV2.CaseDef + given moduleConversion: (quotes: Quotes) => Conversion[CaseDef.type, CaseDef.Module] = _ => quotes.reflectV2.CaseDef + + def unapply(x: CaseDef): (Tree, Option[Term], Term) = (x.pattern, x.guard, x.rhs) + + trait Module private[compiletime] () { + def apply(pattern: Tree, guard: Option[Term], rhs: Term): CaseDef + def make(pattern: Tree, guard: Option[Term], rhs: Term): CaseDef + } + +} + +/////// TypeCaseDef /////////////////////////////////////////////////////////////// + +/** Branch of a type pattern match. */ +trait TypeCaseDef private[compiletime] () extends Tree { + def pattern: TypeTree + def rhs: TypeTree +} +object TypeCaseDef { + + def quoted(using quotes: Quotes): TypeCaseDef.Module = quotes.reflectV2.TypeCaseDef + given moduleConversion: (quotes: Quotes) => Conversion[TypeCaseDef.type, TypeCaseDef.Module] = _ => quotes.reflectV2.TypeCaseDef + + def unapply(tree: TypeCaseDef): (TypeTree, TypeTree) = (tree.pattern, tree.rhs) + + trait Module private[compiletime] () { + def apply(pattern: TypeTree, rhs: TypeTree): TypeCaseDef + def make(pattern: TypeTree, rhs: TypeTree): TypeCaseDef + } + +} + +/////// Bind /////////////////////////////////////////////////////////////// + +/** Pattern representing a `_ @ _` binding. */ +trait Bind private[compiletime] () extends Tree { + def name: String + def pattern: Tree +} +object Bind { + + def quoted(using quotes: Quotes): Bind.Module = quotes.reflectV2.Bind + given moduleConversion: (quotes: Quotes) => Conversion[Bind.type, Bind.Module] = _ => quotes.reflectV2.Bind + + def unapply(pattern: Bind): (String, Tree) = (pattern.name, pattern.pattern) + + trait Module private[compiletime] () { + def apply(sym: Symbol, pattern: Tree): Bind + def make(sym: Symbol, pattern: Tree): Bind + } + +} + +/////// Unapply /////////////////////////////////////////////////////////////// + +/** Pattern representing a `Xyz(...)` unapply. */ +trait Unapply private[compiletime] () extends Tree { + def fun: Term + def implicits: List[Term] + def patterns: List[Tree] +} +object Unapply { + + def quoted(using quotes: Quotes): Unapply.Module = quotes.reflectV2.Unapply + given moduleConversion: (quotes: Quotes) => Conversion[Unapply.type, Unapply.Module] = _ => quotes.reflectV2.Unapply + + def unapply(x: Unapply): (Term, List[Term], List[Tree]) = (x.fun, x.implicits, x.patterns) + + trait Module private[compiletime] () { + + /** Creates an `Unapply` tree representing a pattern `()(using )`. */ + def apply(fun: Term, implicits: List[Term], patterns: List[Tree]): Unapply + + /** Creates an `Unapply` tree representing a pattern `()(using )`. */ + def make(fun: Term, implicits: List[Term], patterns: List[Tree]): Unapply + } + +} + +/////// Alternatives /////////////////////////////////////////////////////////////// + +/** Pattern representing `X | Y | ...` alternatives. */ +trait Alternatives private[compiletime] () extends Tree { + def patterns: List[Tree] +} +object Alternatives { + + def quoted(using quotes: Quotes): Alternatives.Module = quotes.reflectV2.Alternatives + given moduleConversion: (quotes: Quotes) => Conversion[Alternatives.type, Alternatives.Module] = _ => quotes.reflectV2.Alternatives + + def unapply(x: Alternatives): Some[List[Tree]] = Some(x.patterns) + + trait Module private[compiletime] () { + def apply(patterns: List[Tree]): Alternatives + def make(patterns: List[Tree]): Alternatives + } + +} diff --git a/library/src/scala/quoted/compiletime/TypeRepr.scala b/library/src/scala/quoted/compiletime/TypeRepr.scala new file mode 100644 index 000000000000..586461a40a6e --- /dev/null +++ b/library/src/scala/quoted/compiletime/TypeRepr.scala @@ -0,0 +1,751 @@ +package scala.quoted.compiletime + +import scala.annotation.experimental +import scala.quoted.Type + +/////// TypeRepr /////////////////////////////////////////////////////////////// + +/** A type, type constructors, type bounds or NoPrefix. */ +sealed trait TypeRepr { + + /** Shows the type as a String. */ + final def show(using p: Printer[TypeRepr]): String = p.show(this) + + /** + * Converts this `TypeRepr` to an `Type[?]` + * + * Usage: + * ```scala + * //{ + * import scala.quoted.* + * def f(using Quotes) = { + * val q: Quotes = summon[Quotes] + * import q.reflect.* + * val typeRepr: TypeRepr = ??? + * //} + * typeRepr.asType match + * case '[t] => + * '{ val x: t = ??? } + * //{ + * } + * //} + * ``` + */ + def asType: Type[?] + + /** + * Is `self` type the same as `that` type? + * This is the case iff `self <:< that` and `that <:< self`. + */ + def =:=(that: TypeRepr): Boolean + + /** Is this type a subtype of that type? */ + def <:<(that: TypeRepr): Boolean + + /** + * Widen from singleton type to its underlying non-singleton + * base type by applying one or more `underlying` dereferences, + * Also go from => T to T. + * Identity for all other types. Example: + * + * class Outer { class C ; val x: C } + * def o: Outer + * .widen = o.C + */ + def widen: TypeRepr + + /** + * Widen from TermRef to its underlying non-termref + * base type, while also skipping ByName types. + */ + def widenTermRefByName: TypeRepr + + /** Widen from ByName type to its result type. */ + def widenByName: TypeRepr + + /** Follow aliases, annotated types until type is no longer alias type, annotated type. */ + def dealias: TypeRepr + + /** Follow non-opaque aliases, annotated types until type is no longer alias type, annotated type. */ + def dealiasKeepOpaques: TypeRepr + + /** + * A simplified version of this type which is equivalent wrt =:= to this type. + * Reduces typerefs, applied match types, and and or types. + */ + def simplified: TypeRepr + + def classSymbol: Option[Symbol] + def typeSymbol: Symbol + def termSymbol: Symbol + def isSingleton: Boolean + + /** + * The type of `member` as seen from prefix `self`. + * + * Also see `typeRef` and `termRef` + */ + def memberType(member: Symbol): TypeRepr + + /** The base classes of this type with the class itself as first element. */ + def baseClasses: List[Symbol] + + /** + * The least type instance of given class which is a super-type + * of this type. Example: + * {{{ + * class D[T] + * class C extends p.D[Int] + * ThisType(C).baseType(D) = p.D[Int] + * }}} + */ + def baseType(cls: Symbol): TypeRepr + + /** Is this type an instance of a non-bottom subclass of the given class `cls`? */ + def derivesFrom(cls: Symbol): Boolean + + /** + * Is this type a function type? + * + * @return true if the dealiased type of `self` without refinement is `FunctionN[T1, T2, ..., Tn]` + * + * @note The function + * + * - returns true for `given Int => Int` and `erased Int => Int` + * - returns false for `List[Int]`, despite that `List[Int] <:< Int => Int`. + */ + def isFunctionType: Boolean + + /** + * Is this type an context function type? + * + * @see `isFunctionType` + */ + def isContextFunctionType: Boolean + + /** + * Is this type a function type with erased parameters? + * + * @see `isFunctionType` + */ + def isErasedFunctionType: Boolean + + /** + * Is this type a dependent function type? + * + * @see `isFunctionType` + */ + def isDependentFunctionType: Boolean + + /** + * Is this type a `TupleN` type? + * + * @return true if the dealiased type of `self` is `TupleN[T1, T2, ..., Tn]` + */ + def isTupleN: Boolean + + /** The type , reduced if possible. */ + def select(sym: Symbol): TypeRepr + + /** The current type applied to given type arguments: `this[targ]`. */ + def appliedTo(targ: TypeRepr): TypeRepr + + /** The current type applied to given type arguments: `this[targ0, ..., targN]`. */ + def appliedTo(targs: List[TypeRepr]): TypeRepr + + /** + * Substitutes all types that refer in their symbol attribute to + * one of the symbols in `from` by the corresponding types in `to`. + */ + def substituteTypes(from: List[Symbol], to: List[TypeRepr]): TypeRepr + + /** The applied type arguments (empty if there is no such arguments). */ + def typeArgs: List[TypeRepr] + +} +object TypeRepr { + + def quoted(using quotes: Quotes): TypeRepr.Module = quotes.reflectV2.TypeRepr + given moduleConversion: (quotes: Quotes) => Conversion[TypeRepr.type, TypeRepr.Module] = _ => quotes.reflectV2.TypeRepr + + trait Module private[compiletime] () { + + /** Returns the type or kind (TypeRepr) of T. */ + def of[T <: AnyKind](using Type[T]): TypeRepr + + /** Returns the type constructor of the runtime (erased) class. */ + def typeConstructorOf(clazz: Class[?]): TypeRepr + + } + +} + +/////// TermRef /////////////////////////////////////////////////////////////// + +/** Type of a reference to a type or term symbol. */ +sealed trait NamedType extends TypeRepr { + def qualifier: TypeRepr + def name: String +} +object NamedType { + + def quoted(using quotes: Quotes): NamedType.Module = quotes.reflectV2.NamedType + given moduleConversion: (quotes: Quotes) => Conversion[NamedType.type, NamedType.Module] = _ => quotes.reflectV2.NamedType + + trait Module private[compiletime] () {} + +} + +/////// TermRef /////////////////////////////////////////////////////////////// + +/** Type of a reference to a term symbol. */ +trait TermRef private[compiletime] () extends NamedType +object TermRef { + + def quoted(using quotes: Quotes): TermRef.Module = quotes.reflectV2.TermRef + given moduleConversion: (quotes: Quotes) => Conversion[TermRef.type, TermRef.Module] = _ => quotes.reflectV2.TermRef + + def unapply(x: TermRef): (TypeRepr, String) = (x.qualifier, x.name) + + trait Module private[compiletime] () { + def apply(qual: TypeRepr, name: String): TermRef + def make(qual: TypeRepr, name: String): TermRef + } + +} + +/////// TypeRef /////////////////////////////////////////////////////////////// + +/** Type of a reference to a type symbol. */ +trait TypeRef private[compiletime] () extends NamedType { + def isOpaqueAlias: Boolean + def translucentSuperType: TypeRepr +} +object TypeRef { + + def quoted(using quotes: Quotes): TypeRef.Module = quotes.reflectV2.TypeRef + given moduleConversion: (quotes: Quotes) => Conversion[TypeRef.type, TypeRef.Module] = _ => quotes.reflectV2.TypeRef + + def unapply(x: TypeRef): (TypeRepr, String) = (x.qualifier, x.name) + + trait Module private[compiletime] () {} + +} + +/////// ConstantType /////////////////////////////////////////////////////////////// + +/** A singleton type representing a known constant value. */ +trait ConstantType private[compiletime] () extends TypeRepr { + def constant: Constant +} +object ConstantType { + + def quoted(using quotes: Quotes): ConstantType.Module = quotes.reflectV2.ConstantType + given moduleConversion: (quotes: Quotes) => Conversion[ConstantType.type, ConstantType.Module] = _ => quotes.reflectV2.ConstantType + + def unapply(x: ConstantType): Some[Constant] = Some(x.constant) + + trait Module private[compiletime] () { + def apply(x: Constant): ConstantType + def make(x: Constant): ConstantType + } + +} + +/////// SuperType /////////////////////////////////////////////////////////////// + +/** Type of a `super` reference. */ +trait SuperType private[compiletime] () extends TypeRepr { + def thistpe: TypeRepr + def supertpe: TypeRepr +} +object SuperType { + + def quoted(using quotes: Quotes): SuperType.Module = quotes.reflectV2.SuperType + given moduleConversion: (quotes: Quotes) => Conversion[SuperType.type, SuperType.Module] = _ => quotes.reflectV2.SuperType + + def unapply(x: SuperType): (TypeRepr, TypeRepr) = (x.thistpe, x.supertpe) + + trait Module private[compiletime] () { + def apply(thistpe: TypeRepr, supertpe: TypeRepr): SuperType + def make(thistpe: TypeRepr, supertpe: TypeRepr): SuperType + } + +} + +/////// Refinement /////////////////////////////////////////////////////////////// + +/** A type with a type refinement `T { type U }`. */ +trait Refinement private[compiletime] () extends TypeRepr { + def parent: TypeRepr + def name: String + def info: TypeRepr +} +object Refinement { + + def quoted(using quotes: Quotes): Refinement.Module = quotes.reflectV2.Refinement + given moduleConversion: (quotes: Quotes) => Conversion[Refinement.type, Refinement.Module] = _ => quotes.reflectV2.Refinement + + def unapply(x: Refinement): (TypeRepr, String, TypeRepr) = (x.parent, x.name, x.info) + + trait Module private[compiletime] () { + def apply(parent: TypeRepr, name: String, info: TypeRepr): Refinement + def make(parent: TypeRepr, name: String, info: TypeRepr): Refinement + } + +} + +/////// AppliedType /////////////////////////////////////////////////////////////// + +/** A higher kinded type applied to some types `T[U]`. */ +trait AppliedType private[compiletime] () extends TypeRepr { + def tycon: TypeRepr + def args: List[TypeRepr] +} +object AppliedType { + + def quoted(using quotes: Quotes): AppliedType.Module = quotes.reflectV2.AppliedType + given moduleConversion: (quotes: Quotes) => Conversion[AppliedType.type, AppliedType.Module] = _ => quotes.reflectV2.AppliedType + + def unapply(x: AppliedType): (TypeRepr, List[TypeRepr]) = (x.tycon, x.args) + + trait Module private[compiletime] () { + + /** Applied the type constructor `T` to a list of type arguments `T_1,..,T_n` to create `T[T_1,..,T_n]`. */ + def apply(tycon: TypeRepr, args: List[TypeRepr]): AppliedType + + /** Applied the type constructor `T` to a list of type arguments `T_1,..,T_n` to create `T[T_1,..,T_n]`. */ + def make(tycon: TypeRepr, args: List[TypeRepr]): AppliedType + } + +} + +/////// AppliedType /////////////////////////////////////////////////////////////// + +/** A type with an annotation `T @foo` */ +trait AnnotatedType private[compiletime] () extends TypeRepr { + def underlying: TypeRepr + // def annotation: Term // TODO: Term +} +object AnnotatedType { + + def quoted(using quotes: Quotes): AnnotatedType.Module = quotes.reflectV2.AnnotatedType + given moduleConversion: (quotes: Quotes) => Conversion[AnnotatedType.type, AnnotatedType.Module] = _ => quotes.reflectV2.AnnotatedType + + // def unapply(x: AnnotatedType): (TypeRepr, Term) = (x.underlying, x.annotation) // TODO: Term + + trait Module private[compiletime] () { + // def apply(underlying: TypeRepr, annot: Term): AnnotatedType // TODO: Term + // def make(underlying: TypeRepr, annot: Term): AnnotatedType // TODO: Term + } + +} + +/////// AppliedType /////////////////////////////////////////////////////////////// + +/** Intersection type `T & U` or an union type `T | U`. */ +sealed trait AndOrType extends TypeRepr { + def left: TypeRepr + def right: TypeRepr +} +object AndOrType { + + def quoted(using quotes: Quotes): AndOrType.Module = quotes.reflectV2.AndOrType + given moduleConversion: (quotes: Quotes) => Conversion[AndOrType.type, AndOrType.Module] = _ => quotes.reflectV2.AndOrType + + trait Module private[compiletime] () {} + +} + +/////// AndType /////////////////////////////////////////////////////////////// + +/** Intersection type `T & U`. */ +trait AndType private[compiletime] () extends AndOrType +object AndType { + + def quoted(using quotes: Quotes): AndType.Module = quotes.reflectV2.AndType + given moduleConversion: (quotes: Quotes) => Conversion[AndType.type, AndType.Module] = _ => quotes.reflectV2.AndType + + def unapply(x: AndType): (TypeRepr, TypeRepr) = (x.left, x.right) + + trait Module private[compiletime] () { + def apply(lhs: TypeRepr, rhs: TypeRepr): AndType + def make(lhs: TypeRepr, rhs: TypeRepr): AndType + } + +} + +/////// OrType /////////////////////////////////////////////////////////////// + +/** Union type `T | U`. */ +trait OrType private[compiletime] () extends AndOrType +object OrType { + + def quoted(using quotes: Quotes): OrType.Module = quotes.reflectV2.OrType + given moduleConversion: (quotes: Quotes) => Conversion[OrType.type, OrType.Module] = _ => quotes.reflectV2.OrType + + def unapply(x: OrType): (TypeRepr, TypeRepr) = (x.left, x.right) + + trait Module private[compiletime] () { + def apply(lhs: TypeRepr, rhs: TypeRepr): OrType + def make(lhs: TypeRepr, rhs: TypeRepr): OrType + } + +} + +/////// MatchType /////////////////////////////////////////////////////////////// + +/** Type match `T match { case U => ... }`. */ +trait MatchType private[compiletime] () extends TypeRepr { + def bound: TypeRepr + def scrutinee: TypeRepr + def cases: List[TypeRepr] +} +object MatchType { + + def quoted(using quotes: Quotes): MatchType.Module = quotes.reflectV2.MatchType + given moduleConversion: (quotes: Quotes) => Conversion[MatchType.type, MatchType.Module] = _ => quotes.reflectV2.MatchType + + def unapply(x: MatchType): (TypeRepr, TypeRepr, List[TypeRepr]) = (x.bound, x.scrutinee, x.cases) + + trait Module private[compiletime] () { + def apply(bound: TypeRepr, scrutinee: TypeRepr, cases: List[TypeRepr]): MatchType + def make(bound: TypeRepr, scrutinee: TypeRepr, cases: List[TypeRepr]): MatchType + } + +} + +/////// ByNameType /////////////////////////////////////////////////////////////// + +/** + * Type of a by-name definition of type `=>T`. + * + * May represent by-name parameter such as `thunk` in + * ```scala + * //{ + * type T + * //} + * def log[T](thunk: => T): T = ??? + * ``` + * + * May also represent a the return type of a parameterless method definition such as + * ```scala + * def foo: Int = ??? + * ``` + */ +trait ByNameType private[compiletime] () extends TypeRepr { + def underlying: TypeRepr +} +object ByNameType { + + def quoted(using quotes: Quotes): ByNameType.Module = quotes.reflectV2.ByNameType + given moduleConversion: (quotes: Quotes) => Conversion[ByNameType.type, ByNameType.Module] = _ => quotes.reflectV2.ByNameType + + def unapply(x: ByNameType): Some[TypeRepr] = Some(x.underlying) + + trait Module private[compiletime] () { + def apply(underlying: TypeRepr): TypeRepr + def make(underlying: TypeRepr): TypeRepr + } + +} + +/////// ParamRef /////////////////////////////////////////////////////////////// + +/** Type of a parameter reference. */ +trait ParamRef private[compiletime] () extends TypeRepr { + def binder: TypeRepr + def paramNum: Int +} +object ParamRef { + + def quoted(using quotes: Quotes): ParamRef.Module = quotes.reflectV2.ParamRef + given moduleConversion: (quotes: Quotes) => Conversion[ParamRef.type, ParamRef.Module] = _ => quotes.reflectV2.ParamRef + + def unapply(x: ParamRef): (TypeRepr, Int) = (x.binder, x.paramNum) + + trait Module private[compiletime] () {} + +} + +/////// ThisType /////////////////////////////////////////////////////////////// + +/** Type of `this`. */ +trait ThisType private[compiletime] () extends TypeRepr { + def tref: TypeRepr +} +object ThisType { + + def quoted(using quotes: Quotes): ThisType.Module = quotes.reflectV2.ThisType + given moduleConversion: (quotes: Quotes) => Conversion[ThisType.type, ThisType.Module] = _ => quotes.reflectV2.ThisType + + def unapply(x: ThisType): Some[TypeRepr] = Some(x.tref) + + trait Module private[compiletime] () {} + +} + +/////// RecursiveThis /////////////////////////////////////////////////////////////// + +/** A type that is recursively defined `this`. */ +trait RecursiveThis private[compiletime] () extends TypeRepr { + def binder: RecursiveType +} +object RecursiveThis { + + def quoted(using quotes: Quotes): RecursiveThis.Module = quotes.reflectV2.RecursiveThis + given moduleConversion: (quotes: Quotes) => Conversion[RecursiveThis.type, RecursiveThis.Module] = _ => quotes.reflectV2.RecursiveThis + + def unapply(x: RecursiveThis): Some[RecursiveType] = Some(x.binder) + + trait Module private[compiletime] () {} + +} + +/////// RecursiveType /////////////////////////////////////////////////////////////// + +/** A type that is recursively defined. */ +trait RecursiveType private[compiletime] () extends TypeRepr { + def underlying: TypeRepr + def recThis: RecursiveThis +} +object RecursiveType { + + def quoted(using quotes: Quotes): RecursiveType.Module = quotes.reflectV2.RecursiveType + given moduleConversion: (quotes: Quotes) => Conversion[RecursiveType.type, RecursiveType.Module] = _ => quotes.reflectV2.RecursiveType + + def unapply(x: RecursiveType): Some[TypeRepr] = Some(x.underlying) + + trait Module private[compiletime] () { + + /** + * Creates a RecType, normalizing its contents. This means: + * + * 1. Nested Rec types on the type's spine are merged with the outer one. + * 2. Any refinement of the form `type T = z.T` on the spine of the type + * where `z` refers to the created rec-type is replaced by + * `type T`. This avoids infinite recursions later when we + * try to follow these references. + */ + def apply(parentExp: RecursiveType => TypeRepr): RecursiveType + + /** Creates a RecType, normalizing its contents. */ + def make(parentExp: RecursiveType => TypeRepr): RecursiveType + + } + +} + +/////// LambdaType /////////////////////////////////////////////////////////////// + +/** Type of the definition of a method taking a single list of type or term parameters. */ +sealed trait LambdaType extends TypeRepr { + def paramNames: List[String] + def paramTypes: List[TypeRepr] + def resType: TypeRepr +} +object LambdaType { + + def quoted(using quotes: Quotes): LambdaType.Module = quotes.reflectV2.LambdaType + given moduleConversion: (quotes: Quotes) => Conversion[LambdaType.type, LambdaType.Module] = _ => quotes.reflectV2.LambdaType + + trait Module private[compiletime] () {} + +} + +/////// MethodOrPoly /////////////////////////////////////////////////////////////// + +/** Type of the definition of a method taking a single list of type or term parameters. */ +sealed trait MethodOrPoly extends LambdaType +object MethodOrPoly { + + def quoted(using quotes: Quotes): MethodOrPoly.Module = quotes.reflectV2.MethodOrPoly + given moduleConversion: (quotes: Quotes) => Conversion[MethodOrPoly.type, MethodOrPoly.Module] = _ => quotes.reflectV2.MethodOrPoly + + trait Module private[compiletime] () {} + +} + +/////// MethodType /////////////////////////////////////////////////////////////// + +/** Type of the definition of a method taking a single list of parameters. It's return type may be a MethodType. */ +trait MethodType private[compiletime] () extends MethodOrPoly { + + /** Is this the type of parameter clause like `(implicit X1, ..., Xn)`, `(using X1, ..., Xn)` or `(using x1: X1, ..., xn: Xn)`. */ + def isImplicit: Boolean + + /** Is this the type of parameter clause like `(using X1, ..., Xn)` or `(using x1: X1, x2: X2, ... )`. */ + def isContextual: Boolean + + /** Returns a MethodTypeKind object representing the implicitness of the MethodType parameter clause. */ + def methodTypeKind: MethodTypeKind + + /** List of `erased` flags for each parameters of the clause. */ + @experimental + def erasedParams: List[Boolean] + + /** Whether the clause has any erased parameters. */ + @experimental + def hasErasedParams: Boolean + def param(idx: Int): TypeRepr +} +object MethodType { + + def quoted(using quotes: Quotes): MethodType.Module = quotes.reflectV2.MethodType + given moduleConversion: (quotes: Quotes) => Conversion[MethodType.type, MethodType.Module] = _ => quotes.reflectV2.MethodType + + def unapply(x: MethodType): (List[String], List[TypeRepr], TypeRepr) = (x.paramNames, x.paramTypes, x.resType) + + trait Module private[compiletime] () { + def apply(paramNames: List[String])(paramInfosExp: MethodType => List[TypeRepr], resultTypeExp: MethodType => TypeRepr): MethodType + def make(paramNames: List[String])(paramInfosExp: MethodType => List[TypeRepr], resultTypeExp: MethodType => TypeRepr): MethodType + def apply(kind: MethodTypeKind)(paramNames: List[String])(paramInfosExp: MethodType => List[TypeRepr], resultTypeExp: MethodType => TypeRepr): MethodType + def make(kind: MethodTypeKind)(paramNames: List[String])(paramInfosExp: MethodType => List[TypeRepr], resultTypeExp: MethodType => TypeRepr): MethodType + } + +} + +/////// /////////////////////////////////////////////////////////////// + +/** Type of the definition of a method taking a list of type parameters. It's return type may be a MethodType. */ +trait PolyType private[compiletime] () extends MethodOrPoly { + def param(idx: Int): TypeRepr + def paramBounds: List[TypeBounds] +} +object PolyType { + + def quoted(using quotes: Quotes): PolyType.Module = quotes.reflectV2.PolyType + given moduleConversion: (quotes: Quotes) => Conversion[PolyType.type, PolyType.Module] = _ => quotes.reflectV2.PolyType + + def unapply(x: PolyType): (List[String], List[TypeBounds], TypeRepr) = (x.paramNames, x.paramBounds, x.resType) + + trait Module private[compiletime] () { + def apply(paramNames: List[String])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => TypeRepr): PolyType + def make(paramNames: List[String])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => TypeRepr): PolyType + } + +} + +/////// TypeLambda /////////////////////////////////////////////////////////////// + +/** Type of the definition of a type lambda taking a list of type parameters. It's return type may be a TypeLambda. */ +trait TypeLambda private[compiletime] () extends LambdaType { + + /** Reference to the i-th parameter. */ + def param(idx: Int): TypeRepr + + /** Type bounds of the i-th parameter. */ + def paramBounds: List[TypeBounds] + + /** + * Variance flags for the i-th parameter + * + * Variance flags can be one of `Flags.{Covariant, Contravariant, EmptyFlags}`. + */ + def paramVariances: List[Flags] +} +object TypeLambda { + + def quoted(using quotes: Quotes): TypeLambda.Module = quotes.reflectV2.TypeLambda + given moduleConversion: (quotes: Quotes) => Conversion[TypeLambda.type, TypeLambda.Module] = _ => quotes.reflectV2.TypeLambda + + def unapply(x: TypeLambda): (List[String], List[TypeBounds], TypeRepr) = (x.paramNames, x.paramBounds, x.resType) + + trait Module private[compiletime] () { + def apply(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => TypeRepr): TypeLambda + def make(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => TypeRepr): TypeLambda + } + +} + +/////// MatchCase /////////////////////////////////////////////////////////////// + +/** + * Case of a `MatchType` containing pattern `case P => R`. + * + * Note: cases with type bindings are represented nested in a `TypeLambda`. + */ +trait MatchCase private[compiletime] () extends TypeRepr { + + /** Pattern `P` of `case P => R` in a `MatchType`. */ + def pattern: TypeRepr + + /** RHS `R` of `case P => R` in a `MatchType`. */ + def rhs: TypeRepr +} +object MatchCase { + + def quoted(using quotes: Quotes): MatchCase.Module = quotes.reflectV2.MatchCase + given moduleConversion: (quotes: Quotes) => Conversion[MatchCase.type, MatchCase.Module] = _ => quotes.reflectV2.MatchCase + + def unapply(x: MatchCase): (TypeRepr, TypeRepr) = (x.pattern, x.rhs) + + trait Module private[compiletime] () { + /* Create match type case `case => ` */ + def apply(pattern: TypeRepr, rhs: TypeRepr): MatchCase + /* Create match type case `case => ` */ + def make(pattern: TypeRepr, rhs: TypeRepr): MatchCase + } + +} + +/////// TypeBounds /////////////////////////////////////////////////////////////// + +/** Type bounds. */ +trait TypeBounds private[compiletime] () extends TypeRepr { + def low: TypeRepr + def hi: TypeRepr +} +object TypeBounds { + + def quoted(using quotes: Quotes): TypeBounds.Module = quotes.reflectV2.TypeBounds + given moduleConversion: (quotes: Quotes) => Conversion[TypeBounds.type, TypeBounds.Module] = _ => quotes.reflectV2.TypeBounds + + def unapply(x: TypeBounds): (TypeRepr, TypeRepr) = (x.low, x.hi) + + trait Module private[compiletime] () { + def apply(low: TypeRepr, hi: TypeRepr): TypeBounds + def make(low: TypeRepr, hi: TypeRepr): TypeBounds + def empty: TypeBounds + def upper(hi: TypeRepr): TypeBounds + def lower(lo: TypeRepr): TypeBounds + } + +} + +/////// NoPrefix /////////////////////////////////////////////////////////////// + +/** NoPrefix for a type selection. */ +trait NoPrefix private[compiletime] () extends TypeRepr +object NoPrefix { + + def quoted(using quotes: Quotes): NoPrefix.Module = quotes.reflectV2.NoPrefix + given moduleConversion: (quotes: Quotes) => Conversion[NoPrefix.type, NoPrefix.Module] = _ => quotes.reflectV2.NoPrefix + + def unapply(x: NoPrefix): true = true + + trait Module private[compiletime] () {} + +} + +/////// FlexibleType /////////////////////////////////////////////////////////////// + +/** Flexible types for explicit nulls. */ +trait FlexibleType private[compiletime] () extends TypeRepr { + def underlying: TypeRepr + def lo: TypeRepr + def hi: TypeRepr +} +object FlexibleType { + + def quoted(using quotes: Quotes): FlexibleType.Module = quotes.reflectV2.FlexibleType + given moduleConversion: (quotes: Quotes) => Conversion[FlexibleType.type, FlexibleType.Module] = _ => quotes.reflectV2.FlexibleType + + def unapply(x: FlexibleType): Option[TypeRepr] = Some(x.underlying) + + trait Module private[compiletime] () { + def apply(tp: TypeRepr): FlexibleType + def make(tp: TypeRepr): FlexibleType + } + +} diff --git a/library/src/scala/quoted/compiletime/reflect.scala b/library/src/scala/quoted/compiletime/reflect.scala new file mode 100644 index 000000000000..7a69b89176dd --- /dev/null +++ b/library/src/scala/quoted/compiletime/reflect.scala @@ -0,0 +1,129 @@ +package scala.quoted.compiletime + +import scala.quoted.compiletime as pub + +object reflect { + + trait Module { + + lazy val Symbol: pub.Symbol.Module + lazy val Position: pub.Position.Module + lazy val SourceFile: pub.SourceFile.Module + lazy val Signature: pub.Signature.Module + lazy val Flags: pub.Flags.Module + + lazy val Selector: pub.Selector.Module + lazy val SimpleSelector: pub.SimpleSelector.Module + lazy val RenameSelector: pub.RenameSelector.Module + lazy val OmitSelector: pub.OmitSelector.Module + lazy val GivenSelector: pub.GivenSelector.Module + + lazy val ParamClause: pub.ParamClause.Module + lazy val TermParamClause: pub.TermParamClause.Module + lazy val TypeParamClause: pub.TypeParamClause.Module + + lazy val Constant: pub.Constant.Module + lazy val BooleanConstant: pub.BooleanConstant.Module + lazy val ByteConstant: pub.ByteConstant.Module + lazy val ShortConstant: pub.ShortConstant.Module + lazy val IntConstant: pub.IntConstant.Module + lazy val LongConstant: pub.LongConstant.Module + lazy val FloatConstant: pub.FloatConstant.Module + lazy val DoubleConstant: pub.DoubleConstant.Module + lazy val CharConstant: pub.CharConstant.Module + lazy val StringConstant: pub.StringConstant.Module + lazy val UnitConstant: pub.UnitConstant.Module + lazy val NullConstant: pub.NullConstant.Module + lazy val ClassOfConstant: pub.ClassOfConstant.Module + + lazy val TypeRepr: pub.TypeRepr.Module + lazy val NamedType: pub.NamedType.Module + lazy val TermRef: pub.TermRef.Module + lazy val TypeRef: pub.TypeRef.Module + lazy val ConstantType: pub.ConstantType.Module + lazy val SuperType: pub.SuperType.Module + lazy val Refinement: pub.Refinement.Module + lazy val AppliedType: pub.AppliedType.Module + lazy val AnnotatedType: pub.AnnotatedType.Module + lazy val AndOrType: pub.AndOrType.Module + lazy val AndType: pub.AndType.Module + lazy val OrType: pub.OrType.Module + lazy val MatchType: pub.MatchType.Module + lazy val ByNameType: pub.ByNameType.Module + lazy val ParamRef: pub.ParamRef.Module + lazy val ThisType: pub.ThisType.Module + lazy val RecursiveThis: pub.RecursiveThis.Module + lazy val RecursiveType: pub.RecursiveType.Module + lazy val LambdaType: pub.LambdaType.Module + lazy val MethodOrPoly: pub.MethodOrPoly.Module + lazy val MethodType: pub.MethodType.Module + lazy val PolyType: pub.PolyType.Module + lazy val TypeLambda: pub.TypeLambda.Module + lazy val MatchCase: pub.MatchCase.Module + lazy val TypeBounds: pub.TypeBounds.Module + lazy val NoPrefix: pub.NoPrefix.Module + lazy val FlexibleType: pub.FlexibleType.Module + + lazy val Tree: pub.Tree.Module + lazy val PackageClause: pub.PackageClause.Module + lazy val Statement: pub.Statement.Module + lazy val Import: pub.Import.Module + lazy val Export: pub.Export.Module + lazy val Definition: pub.Definition.Module + lazy val ClassDef: pub.ClassDef.Module + lazy val ValOrDefDef: pub.ValOrDefDef.Module + lazy val DefDef: pub.DefDef.Module + lazy val ValDef: pub.ValDef.Module + lazy val TypeDef: pub.TypeDef.Module + lazy val Term: pub.Term.Module + lazy val Ref: pub.Ref.Module + lazy val Ident: pub.Ident.Module + lazy val Wildcard: pub.Wildcard.Module + lazy val Select: pub.Select.Module + lazy val Literal: pub.Literal.Module + lazy val This: pub.This.Module + lazy val New: pub.New.Module + lazy val NamedArg: pub.NamedArg.Module + lazy val Apply: pub.Apply.Module + lazy val TypeApply: pub.TypeApply.Module + lazy val Super: pub.Super.Module + lazy val Typed: pub.Typed.Module + lazy val Assign: pub.Assign.Module + lazy val Block: pub.Block.Module + lazy val Closure: pub.Closure.Module + lazy val Lambda: pub.Lambda.Module + lazy val If: pub.If.Module + lazy val Match: pub.Match.Module + lazy val SummonFrom: pub.SummonFrom.Module + lazy val Try: pub.Try.Module + lazy val Return: pub.Return.Module + lazy val Repeated: pub.Repeated.Module + lazy val Inlined: pub.Inlined.Module + lazy val SelectOuter: pub.SelectOuter.Module + lazy val While: pub.While.Module + lazy val TypedOrTest: pub.TypedOrTest.Module + lazy val TypeTree: pub.TypeTree.Module + lazy val Inferred: pub.Inferred.Module + lazy val TypeIdent: pub.TypeIdent.Module + lazy val TypeSelect: pub.TypeSelect.Module + lazy val TypeProjection: pub.TypeProjection.Module + lazy val Singleton: pub.Singleton.Module + lazy val Refined: pub.Refined.Module + lazy val Applied: pub.Applied.Module + lazy val Annotated: pub.Annotated.Module + lazy val MatchTypeTree: pub.MatchTypeTree.Module + lazy val ByName: pub.ByName.Module + lazy val LambdaTypeTree: pub.LambdaTypeTree.Module + lazy val TypeBind: pub.TypeBind.Module + lazy val TypeBlock: pub.TypeBlock.Module + lazy val TypeBoundsTree: pub.TypeBoundsTree.Module + lazy val WildcardTypeTree: pub.WildcardTypeTree.Module + lazy val CaseDef: pub.CaseDef.Module + lazy val TypeCaseDef: pub.TypeCaseDef.Module + lazy val Bind: pub.Bind.Module + lazy val Unapply: pub.Unapply.Module + lazy val Alternatives: pub.Alternatives.Module + + } + +}