diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala new file mode 100644 index 000000000000..5986f68952ff --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala @@ -0,0 +1,21 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.ast.tpd + +trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with TastyCoreImpl with Helpers { + + def CaseDefDeco(caseDef: CaseDef): CaseDefAPI = new CaseDefAPI { + def pattern(implicit ctx: Context): Pattern = caseDef.pat + def guard(implicit ctx: Context): Option[Term] = optional(caseDef.guard) + def rhs(implicit ctx: Context): Term = caseDef.body + } + + object CaseDef extends CaseDefExtractor { + def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = x match { + case x: tpd.CaseDef => + Some(x.pat, optional(x.guard), x.body) + case _ => None + } + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala new file mode 100644 index 000000000000..e7c5ed5c7d6a --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala @@ -0,0 +1,107 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.core.Constants + +import scala.tasty.util.Show + +trait ConstantOpsImpl extends scala.tasty.reflect.ConstantOps with TastyCoreImpl { + + def ConstantDeco(const: Constant): ConstantAPI = new ConstantAPI { + def value: Any = const.value + } + + object Constant extends ConstantModule { + + object Unit extends UnitExtractor { + def unapply(x: Constant): Boolean = x match { + case x: Constants.Constant => x.tag == Constants.UnitTag + case _ => false + } + } + + object Null extends NullExtractor { + def unapply(x: Constant): Boolean = x match { + case x: Constants.Constant => x.tag == Constants.NullTag + case _ => false + } + } + + object Boolean extends BooleanExtractor { + def unapply(x: Constant): Option[Boolean] = x match { + case x: Constants.Constant if x.tag == Constants.BooleanTag => Some(x.booleanValue) + case _ => None + } + } + + object Byte extends ByteExtractor { + def unapply(x: Constant): Option[Byte] = x match { + case x: Constants.Constant if x.tag == Constants.ByteTag => Some(x.byteValue) + case _ => None + } + } + + object Short extends ShortExtractor { + def unapply(x: Constant): Option[Short] = x match { + case x: Constants.Constant if x.tag == Constants.ShortTag => Some(x.shortValue) + case _ => None + } + } + + object Char extends CharExtractor { + def unapply(x: Constant): Option[Char] = x match { + case x: Constants.Constant if x.tag == Constants.CharTag => Some(x.charValue) + case _ => None + } + } + + object Int extends IntExtractor { + def unapply(x: Constant): Option[Int] = x match { + case x: Constants.Constant if x.tag == Constants.IntTag => Some(x.intValue) + case _ => None + } + } + + object Long extends LongExtractor { + def unapply(x: Constant): Option[Long] = x match { + case x: Constants.Constant if x.tag == Constants.LongTag => Some(x.longValue) + case _ => None + } + } + + object Float extends FloatExtractor { + def unapply(x: Constant): Option[Float] = x match { + case x: Constants.Constant if x.tag == Constants.FloatTag => Some(x.floatValue) + case _ => None + } + } + + object Double extends DoubleExtractor { + def unapply(x: Constant): Option[Double] = x match { + case x: Constants.Constant if x.tag == Constants.DoubleTag => Some(x.doubleValue) + case _ => None + } + } + + object String extends StringExtractor { + def unapply(x: Constant): Option[String] = x match { + case x: Constants.Constant if x.tag == Constants.StringTag => Some(x.stringValue) + case _ => None + } + } + + object ClassTag extends ClassTagExtractor { + def unapply(x: Constant): Option[Type] = x match { + case x: Constants.Constant if x.tag == Constants.ClazzTag => Some(x.typeValue) + case _ => None + } + } + + object Symbol extends SymbolExtractor { + def unapply(x: Constant): Option[scala.Symbol] = x match { + case x: Constants.Constant if x.tag == Constants.ScalaSymbolTag => Some(x.scalaSymbolValue) + case _ => None + } + } + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ContextOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ContextOpsImpl.scala new file mode 100644 index 000000000000..5a9970a5a49c --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ContextOpsImpl.scala @@ -0,0 +1,19 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.core.Contexts +import dotty.tools.dotc.tastyreflect.FromSymbol.definitionFromSym +import dotty.tools.dotc.util.{Positions, SourcePosition} + +trait ContextOpsImpl extends scala.tasty.reflect.ContextOps with TastyCoreImpl { + + val rootContext: Contexts.Context + + def ContextDeco(ctx: Context): ContextAPI = new ContextAPI { + def owner: Definition = definitionFromSym(ctx.owner)(ctx) + + def source: java.nio.file.Path = ctx.compilationUnit.source.file.jpath + } + + def rootPosition: SourcePosition = SourcePosition(rootContext.source, Positions.NoPosition) + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala b/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala index 3c553e5de0e8..41a3b69f6ca2 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala @@ -3,7 +3,7 @@ package dotty.tools.dotc.tastyreflect import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Flags._ -class FlagSet(flags: Flags.FlagSet) extends scala.tasty.FlagSet { +class FlagSet(flags: Flags.FlagSet) extends scala.tasty.reflect.FlagSet { def isProtected: Boolean = flags.is(Protected) def isAbstract: Boolean = flags.is(Abstract) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/Helpers.scala b/compiler/src/dotty/tools/dotc/tastyreflect/Helpers.scala new file mode 100644 index 000000000000..6c6970f15b88 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/Helpers.scala @@ -0,0 +1,10 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.ast.Trees + +trait Helpers { + + protected final def optional[T <: Trees.Tree[_]](tree: T): Option[tree.type] = + if (tree.isEmpty) None else Some(tree) + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/IdOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/IdOpsImpl.scala new file mode 100644 index 000000000000..391d4c73a5b4 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/IdOpsImpl.scala @@ -0,0 +1,16 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.core.Decorators._ + +trait IdOpsImpl extends scala.tasty.reflect.IdOps with TastyCoreImpl { + + def IdDeco(id: Id): IdAPI = new IdAPI { + def pos(implicit ctx: Context): Position = id.pos + def name(implicit ctx: Context): String = id.name.toString + } + + object Id extends IdExtractor { + def unapply(id: Id): Option[String] = Some(id.name.toString) + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ImportSelectorOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ImportSelectorOpsImpl.scala new file mode 100644 index 000000000000..6d499574d8a2 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ImportSelectorOpsImpl.scala @@ -0,0 +1,29 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.ast.{Trees, untpd} +import dotty.tools.dotc.core.StdNames.nme + +trait ImportSelectorOpsImpl extends scala.tasty.reflect.ImportSelectorOps with TastyCoreImpl { + + object SimpleSelector extends SimpleSelectorExtractor { + def unapply(x: ImportSelector)(implicit ctx: Context): Option[Id] = x match { + case x: untpd.Ident => Some(x) + case _ => None + } + } + + object RenameSelector extends RenameSelectorExtractor { + def unapply(x: ImportSelector)(implicit ctx: Context): Option[(Id, Id)] = x match { + case Trees.Thicket((id1: untpd.Ident) :: (id2: untpd.Ident) :: Nil) if id2.name != nme.WILDCARD => Some(id1, id2) + case _ => None + } + } + + object OmitSelector extends OmitSelectorExtractor { + def unapply(x: ImportSelector)(implicit ctx: Context): Option[Id] = x match { + case Trees.Thicket((id: untpd.Ident) :: Trees.Ident(nme.WILDCARD) :: Nil) => Some(id) + case _ => None + } + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala new file mode 100644 index 000000000000..0eed6293b3f5 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala @@ -0,0 +1,65 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.ast.{Trees, tpd} +import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.Types + +import scala.tasty.util.Show + +trait PatternOpsImpl extends scala.tasty.reflect.PatternOps with TastyCoreImpl { + + // ----- Patterns ------------------------------------------------- + + def PatternDeco(pattern: Pattern): PatternAPI = new PatternAPI { + def pos(implicit ctx: Context): Position = pattern.pos + def tpe(implicit ctx: Context): Types.Type = pattern.tpe.stripTypeVar + } + + object Pattern extends PatternModule { + + object Value extends ValueExtractor { + def unapply(x: Pattern)(implicit ctx: Context): Option[Term] = x match { + case lit: tpd.Literal => Some(lit) + case ref: tpd.RefTree if ref.isTerm => Some(ref) + case ths: tpd.This => Some(ths) + case _ => None + } + } + + object Bind extends BindExtractor { + def unapply(x: Pattern)(implicit ctx: Context): Option[(String, Pattern)] = x match { + case x: tpd.Bind if x.name.isTermName => Some(x.name.toString, x.body) + case _ => None + } + } + + object Unapply extends UnapplyExtractor { + def unapply(x: Pattern)(implicit ctx: Context): Option[(Term, List[Term], List[Pattern])] = x match { + case Trees.UnApply(fun, implicits, patterns) => Some((fun, implicits, effectivePatterns(patterns))) + case Trees.Typed(Trees.UnApply(fun, implicits, patterns), _) => Some((fun, implicits, effectivePatterns(patterns))) + case _ => None + } + private def effectivePatterns(patterns: List[Pattern]): List[Pattern] = patterns match { + case patterns0 :+ Trees.SeqLiteral(elems, _) => patterns0 ::: elems + case _ => patterns + } + } + + object Alternative extends AlternativeExtractor { + def unapply(x: Pattern)(implicit ctx: Context): Option[List[Pattern]] = x match { + case x: tpd.Alternative => Some(x.trees) + case _ => None + } + } + + object TypeTest extends TypeTestExtractor { + def unapply(x: Pattern)(implicit ctx: Context): Option[TypeTree] = x match { + case Trees.Typed(Trees.UnApply(_, _, _), _) => None + case Trees.Typed(_, tpt) => Some(tpt) + case _ => None + } + } + + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/PositionOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/PositionOpsImpl.scala new file mode 100644 index 000000000000..28febff4b2e2 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/PositionOpsImpl.scala @@ -0,0 +1,18 @@ +package dotty.tools.dotc.tastyreflect + +trait PositionOpsImpl extends scala.tasty.reflect.PositionOps with TastyCoreImpl { + + def PositionDeco(pos: Position): PositionAPI = new PositionAPI { + def start: Int = pos.start + def end: Int = pos.end + + def sourceFile: java.nio.file.Path = pos.source.file.jpath + + def startLine: Int = pos.startLine + def endLine: Int = pos.endLine + + def startColumn: Int = pos.startColumn + def endColumn: Int = pos.endColumn + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/PrintersImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/PrintersImpl.scala new file mode 100644 index 000000000000..d691871f9746 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/PrintersImpl.scala @@ -0,0 +1,43 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.core.Contexts + +import scala.tasty.util.{Show, ShowExtractors, ShowSourceCode} + +trait PrintersImpl extends scala.tasty.reflect.Printers with scala.tasty.reflect.TastyCore { tasty: TastyImpl => + + def showExtractors: Show[tasty.type] = new ShowExtractors[tasty.type](this) + + def showSourceCode: Show[tasty.type] = new ShowSourceCode[tasty.type](this) + + /** Adds `show` as an extension method of a `Tree` */ + def TreeShowDeco(tree: Tree): ShowAPI = new ShowAPI { + def show(implicit ctx: Contexts.Context, s: Show[tasty.type]): String = s.showTree(tree) + } + + /** Adds `show` as an extension method of a `TypeOrBoundsTree` */ + def TypeOrBoundsTreeShowDeco(tpt: TypeOrBoundsTree): ShowAPI = new ShowAPI { + def show(implicit ctx: Contexts.Context, s: Show[tasty.type]): String = s.showTypeOrBoundsTree(tpt) + } + + /** Adds `show` as an extension method of a `TypeOrBounds` */ + def TypeOrBoundsShowDeco(tpe: TypeOrBounds): ShowAPI = new ShowAPI { + def show(implicit ctx: Contexts.Context, s: Show[tasty.type]): String = s.showTypeOrBounds(tpe) + } + + /** Adds `show` as an extension method of a `CaseDef` */ + def CaseDefShowDeco(caseDef: CaseDef): ShowAPI = new ShowAPI { + def show(implicit ctx: Contexts.Context, s: Show[tasty.type]): String = s.showCaseDef(caseDef) + } + + /** Adds `show` as an extension method of a `Pattern` */ + def PatternShowDeco(pattern: Pattern): ShowAPI = new ShowAPI { + def show(implicit ctx: Contexts.Context, s: Show[tasty.type]): String = s.showPattern(pattern) + } + + /** Adds `show` as an extension method of a `Constant` */ + def ConstantShowDeco(const: Constant): ShowAPI = new ShowAPI { + def show(implicit ctx: Contexts.Context, s: Show[tasty.type]): String = s.showConstant(const) + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala new file mode 100644 index 000000000000..abe93835ef36 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala @@ -0,0 +1,49 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.core.Contexts +import dotty.tools.dotc.core.quoted.PickledQuotes +import dotty.tools.dotc.reporting.Reporter +import dotty.tools.dotc.reporting.diagnostic.MessageContainer + +trait QuotedOpsImpl extends scala.tasty.reflect.QuotedOps with TastyCoreImpl { + + def QuotedExprDeco[T](x: scala.quoted.Expr[T]): QuotedExprAPI = new QuotedExprAPI { + def toTasty(implicit ctx: Context): Term = PickledQuotes.quotedExprToTree(x) + } + + def QuotedTypeDeco[T](x: scala.quoted.Type[T]): QuotedTypeAPI = new QuotedTypeAPI { + def toTasty(implicit ctx: Context): TypeTree = PickledQuotes.quotedTypeToTree(x) + } + + def TermToQuoteDeco(term: Term): TermToQuotedAPI = new TermToQuotedAPI { + + def toExpr[T: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[T] = { + typecheck(ctx) + new scala.quoted.Exprs.TastyTreeExpr(term).asInstanceOf[scala.quoted.Expr[T]] + } + + private def typecheck[T: scala.quoted.Type](ctx: Contexts.Context): Unit = { + implicit val ctx0: Contexts.FreshContext = ctx.fresh + ctx0.setTyperState(ctx0.typerState.fresh()) + ctx0.typerState.setReporter(new Reporter { + def doReport(m: MessageContainer)(implicit ctx: Contexts.Context): Unit = () + }) + val tp = QuotedTypeDeco(implicitly[scala.quoted.Type[T]]).toTasty + ctx0.typer.typed(term, tp.tpe) + if (ctx0.reporter.hasErrors) { + val stack = new Exception().getStackTrace + def filter(elem: StackTraceElement) = + elem.getClassName.startsWith("dotty.tools.dotc.tasty.TastyImpl") || + !elem.getClassName.startsWith("dotty.tools.dotc") + throw new scala.tasty.TastyTypecheckError( + s"""Error during tasty reflection while typing term + |term: ${term.show} + |with expected type: ${tp.tpe.show} + | + | ${stack.takeWhile(filter).mkString("\n ")} + """.stripMargin + ) + } + } + } +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/SignatureOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/SignatureOpsImpl.scala new file mode 100644 index 000000000000..0099732d3797 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/SignatureOpsImpl.scala @@ -0,0 +1,16 @@ +package dotty.tools.dotc.tastyreflect + +trait SignatureOpsImpl extends scala.tasty.reflect.SignatureOps with TastyCoreImpl { + + object Signature extends SignatureExtractor { + def unapply(x: Signature)(implicit ctx: Context): Option[(List[String], String)] = { + Some((x.paramsSig.map(_.toString), x.resSig.toString)) + } + } + + def SignatureDeco(sig: Signature): SignatureAPI = new SignatureAPI { + def paramSigs: List[String] = sig.paramsSig.map(_.toString) + def resultSig: String = sig.resSig.toString + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala new file mode 100644 index 000000000000..38e2533ae9b6 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala @@ -0,0 +1,54 @@ +package dotty.tools.dotc +package tastyreflect + +import dotty.tools.dotc.ast.{tpd, untpd} +import dotty.tools.dotc.core.Constants +import dotty.tools.dotc.core.Types + +trait TastyCoreImpl extends scala.tasty.reflect.TastyCore { + + type Context = core.Contexts.Context + + type Parent = tpd.Tree + + type Tree = tpd.Tree + type PackageClause = tpd.PackageDef + type Statement = tpd.Tree + type Import = tpd.Import + type Definition = tpd.Tree + type ClassDef = tpd.TypeDef + type TypeDef = tpd.TypeDef + type DefDef = tpd.DefDef + type ValDef = tpd.ValDef + type PackageDef = PackageDefinition + type Term = tpd.Tree + + type CaseDef = tpd.CaseDef + + type Pattern = tpd.Tree + + type TypeOrBoundsTree = tpd.Tree + type TypeTree = tpd.Tree + type TypeBoundsTree = tpd.Tree + + type TypeOrBounds = Types.Type + type NoPrefix = Types.NoPrefix.type + type TypeBounds = Types.TypeBounds + type Type = Types.Type + type RecursiveType = Types.RecType + type LambdaType[ParamInfo] = Types.LambdaType { type PInfo = ParamInfo } + type MethodType = Types.MethodType + type PolyType = Types.PolyType + type TypeLambda = Types.TypeLambda + + type ImportSelector = untpd.Tree + + type Id = untpd.Ident + + type Signature = core.Signature + + type Position = util.SourcePosition + + type Constant = Constants.Constant + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala index afcbc2685303..454208329706 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala @@ -1,1158 +1,5 @@ package dotty.tools.dotc.tastyreflect -import dotty.tools.dotc.ast.{Trees, tpd, untpd} -import dotty.tools.dotc.core -import dotty.tools.dotc.core.Decorators._ -import dotty.tools.dotc.core.StdNames.nme -import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core._ -import dotty.tools.dotc.core.quoted.PickledQuotes -import dotty.tools.dotc.reporting.Reporter -import dotty.tools.dotc.reporting.diagnostic.MessageContainer -import dotty.tools.dotc.util.{Positions, SourcePosition} -import scala.quoted -import scala.tasty.util.{Show, ShowExtractors, ShowSourceCode} - -import dotty.tools.dotc.tastyreflect.FromSymbol._ - -class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty with StandardDefinitions { self => - - // ===== Quotes =================================================== - - def QuotedExprDeco[T](x: quoted.Expr[T]): QuotedExprAPI = new QuotedExprAPI { - def toTasty(implicit ctx: Context): Term = PickledQuotes.quotedExprToTree(x) - } - - def QuotedTypeDeco[T](x: quoted.Type[T]): QuotedTypeAPI = new QuotedTypeAPI { - def toTasty(implicit ctx: Context): TypeTree = PickledQuotes.quotedTypeToTree(x) - } - - // ===== Show ===================================================== - - def defaultShow: Show[this.type] = showExtractors - - def showExtractors: Show[this.type] = new ShowExtractors(this) - - def showSourceCode: Show[this.type] = new ShowSourceCode(this) - - // ===== Contexts ================================================= - - type Context = Contexts.Context - - def ContextDeco(ctx: Context): ContextAPI = new ContextAPI { - def owner: Definition = definitionFromSym(ctx.owner)(ctx) - - def source: java.nio.file.Path = ctx.compilationUnit.source.file.jpath - } - - def rootPosition: SourcePosition = SourcePosition(rootContext.source, Positions.NoPosition) - - // ===== Id ======================================================= - - type Id = untpd.Ident - - def IdDeco(id: Id): IdAPI = new IdAPI { - def pos(implicit ctx: Context): Position = id.pos - def name(implicit ctx: Context): String = id.name.toString - } - - object Id extends IdExtractor { - def unapply(id: Id): Option[String] = Some(id.name.toString) - } - - // ===== Trees ==================================================== - - type Tree = tpd.Tree - - def TreeDeco(tree: Tree): TreeAPI = new TreeAPI { - def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showTree(tree) - def pos(implicit ctx: Context): Position = tree.pos - } - - type PackageClause = tpd.PackageDef - - object IsPackageClause extends IsPackageClauseExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[PackageClause] = tree match { - case x: tpd.PackageDef => Some(x) - case _ => None - } - } - - object PackageClause extends PackageClauseExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Tree])] = tree match { - case x: tpd.PackageDef => Some((x.pid, x.stats)) - case _ => None - } - } - - def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI { - def definition(implicit ctx: Context): Definition = packageDefFromSym(pack.symbol) - } - - // ----- Statements ----------------------------------------------- - - type Statement = tpd.Tree - - type Import = tpd.Import - - object Import extends ImportExtractor { - def unapply(x: Tree)(implicit ctx: Context): Option[(Term, List[ImportSelector])] = x match { - case x: tpd.Import => Some((x.expr, x.selectors)) - case _ => None - } - } - - def ImportDeco(imp: Import): ImportAPI = new ImportAPI { - def expr(implicit ctx: Context): Tree = imp.expr - def selector(implicit ctx: Context): List[ImportSelector] = imp.selectors - } - - type ImportSelector = untpd.Tree - - object SimpleSelector extends SimpleSelectorExtractor { - def unapply(x: ImportSelector)(implicit ctx: Context): Option[Id] = x match { - case x: untpd.Ident => Some(x) - case _ => None - } - } - - object RenameSelector extends RenameSelectorExtractor { - def unapply(x: ImportSelector)(implicit ctx: Context): Option[(Id, Id)] = x match { - case Trees.Thicket((id1: untpd.Ident) :: (id2: untpd.Ident) :: Nil) if id2.name != nme.WILDCARD => Some(id1, id2) - case _ => None - } - } - - object OmitSelector extends OmitSelectorExtractor { - def unapply(x: ImportSelector)(implicit ctx: Context): Option[Id] = x match { - case Trees.Thicket((id: untpd.Ident) :: Trees.Ident(nme.WILDCARD) :: Nil) => Some(id) - case _ => None - } - } - - // ----- Definitions ---------------------------------------------- - - type Definition = tpd.Tree /* tpd.MemberDef | PackageDefinition */ - - object IsDefinition extends IsDefinitionExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[Definition] = tree match { - case tree: tpd.MemberDef => Some(tree) - case tree: PackageDefinition => Some(tree) - case _ => None - } - } - - def DefinitionDeco(definition: Definition): DefinitionAPI = new DefinitionAPI { - - def name(implicit ctx: Context): String = definition.symbol.name.toString - - def owner(implicit ctx: Context): Definition = definitionFromSym(definition.symbol.owner) - - def flags(implicit ctx: Context): FlagSet = - new FlagSet(definition.symbol.flags) - - def privateWithin(implicit ctx: Context): Option[Type] = { - val within = definition.symbol.privateWithin - if (within.exists && !definition.symbol.is(core.Flags.Protected)) Some(within.typeRef) - else None - } - - def protectedWithin(implicit ctx: Context): Option[Type] = { - val within = definition.symbol.privateWithin - if (within.exists && definition.symbol.is(core.Flags.Protected)) Some(within.typeRef) - else None - } - - def annots(implicit ctx: Context): List[Term] = { - definition.symbol.annotations.flatMap { - case _: core.Annotations.LazyBodyAnnotation => Nil - case annot => annot.tree :: Nil - } - } - - def localContext(implicit ctx: Context): Context = - if (definition.hasType && definition.symbol.exists) ctx.withOwner(definition.symbol) - else ctx - } - - // ClassDef - - type ClassDef = tpd.TypeDef - - object IsClassDef extends IsClassDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[ClassDef] = tree match { - case x: tpd.TypeDef if x.isClassDef => Some(x) - case _ => None - } - } - - object ClassDef extends ClassDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, DefDef, List[Parent], Option[ValDef], List[Statement])] = tree match { - case Trees.TypeDef(name, impl: tpd.Template) => - Some((name.toString, impl.constr, impl.parents, optional(impl.self), impl.body)) - case _ => None - } - } - - def ClassDefDeco(cdef: ClassDef): ClassDefAPI = new ClassDefAPI { - private def rhs = cdef.rhs.asInstanceOf[tpd.Template] - def constructor(implicit ctx: Context): DefDef = rhs.constr - def parents(implicit ctx: Context): List[tpd.Tree] = rhs.parents - def self(implicit ctx: Context): Option[tpd.ValDef] = optional(rhs.self) - def body(implicit ctx: Context): List[tpd.Tree] = rhs.body - } - - // DefDef - - type DefDef = tpd.DefDef - - object IsDefDef extends IsDefDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[DefDef] = tree match { - case x: tpd.DefDef => Some(x) - case _ => None - } - } - - object DefDef extends DefDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] = tree match { - case x: tpd.DefDef => - Some((x.name.toString, x.tparams, x.vparamss, x.tpt, optional(x.rhs))) - case _ => None - } - } - - def DefDefDeco(ddef: DefDef): DefDefAPI = new DefDefAPI { - def typeParams(implicit ctx: Context): List[TypeDef] = ddef.tparams - def paramss(implicit ctx: Context): List[List[ValDef]] = ddef.vparamss - def returnTpt(implicit ctx: Context): TypeTree = ddef.tpt - def rhs(implicit ctx: Context): Option[Tree] = optional(ddef.rhs) - } - - // ValDef - - type ValDef = tpd.ValDef - - object IsValDef extends IsValDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[ValDef] = tree match { - case x: tpd.ValDef => Some(x) - case _ => None - } - } - - object ValDef extends ValDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] = tree match { - case x: tpd.ValDef => - Some((x.name.toString, x.tpt, optional(x.rhs))) - case _ => None - } - } - - def ValDefDeco(vdef: ValDef): ValDefAPI = new ValDefAPI { - def tpt(implicit ctx: Context): TypeTree = vdef.tpt - def rhs(implicit ctx: Context): Option[Tree] = optional(vdef.rhs) - } - - // TypeDef - - type TypeDef = tpd.TypeDef - - object IsTypeDef extends IsTypeDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[TypeDef] = tree match { - case x: tpd.TypeDef if !x.symbol.isClass => Some(x) - case _ => None - } - } - - object TypeDef extends TypeDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree /* TypeTree | TypeBoundsTree */)] = tree match { - case x: tpd.TypeDef if !x.symbol.isClass => Some((x.name.toString, x.rhs)) - case _ => None - } - } - - def TypeDefDeco(tdef: TypeDef): TypeDefAPI = new TypeDefAPI { - def rhs(implicit ctx: Context): TypeOrBoundsTree = tdef.rhs - } - - // PackageDef - - type PackageDef = PackageDefinition - - def PackageDefDeco(pdef: PackageDef): PackageDefAPI = new PackageDefAPI { - - def owner(implicit ctx: Context): PackageDefinition = packageDefFromSym(pdef.symbol.owner) - - def members(implicit ctx: Context): List[Statement] = { - if (pdef.symbol.is(core.Flags.JavaDefined)) Nil // FIXME should also support java packages - else pdef.symbol.info.decls.iterator.map(definitionFromSym).toList - } - } - - object IsPackageDef extends IsPackageDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[PackageDef] = tree match { - case x: PackageDefinition => Some(x) - case _ => None - } - } - - object PackageDef extends PackageDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, PackageDef)] = tree match { - case x: PackageDefinition => - Some((x.symbol.name.toString, packageDefFromSym(x.symbol.owner))) - case _ => None - } - } - - // ----- Parents -------------------------------------------------- - - type Parent = tpd.Tree - - // ----- Terms ---------------------------------------------------- - - type Term = tpd.Tree - - def TermDeco(term: Term): TermAPI = new TermAPI { - - def pos(implicit ctx: Context): Position = term.pos - - def tpe(implicit ctx: Context): Types.Type = term.tpe - - def toExpr[T: quoted.Type](implicit ctx: Context): quoted.Expr[T] = { - typecheck(ctx) - new quoted.Exprs.TastyTreeExpr(term).asInstanceOf[quoted.Expr[T]] - } - - private def typecheck[T: quoted.Type](ctx: Contexts.Context): Unit = { - implicit val ctx0: Contexts.FreshContext = ctx.fresh - ctx0.setTyperState(ctx0.typerState.fresh()) - ctx0.typerState.setReporter(new Reporter { - def doReport(m: MessageContainer)(implicit ctx: Contexts.Context): Unit = () - }) - val tp = QuotedTypeDeco(implicitly[quoted.Type[T]]).toTasty - ctx0.typer.typed(term, tp.tpe) - if (ctx0.reporter.hasErrors) { - val stack = new Exception().getStackTrace - def filter(elem: StackTraceElement) = - elem.getClassName.startsWith("dotty.tools.dotc.tasty.TastyImpl") || - !elem.getClassName.startsWith("dotty.tools.dotc") - throw new scala.tasty.TastyTypecheckError( - s"""Error during tasty reflection while typing term - |term: ${term.show} - |with expected type: ${tp.tpe.show} - | - | ${stack.takeWhile(filter).mkString("\n ")} - """.stripMargin - ) - } - } - } - - object IsTerm extends IsTermExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[Term] = - if (tree.isTerm) Some(tree) else None - def unapply(parent: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[Term] = - if (parent.isTerm) Some(parent) else None - } - - object Term extends TermModule { - - object Ident extends IdentExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[String] = x match { - case x: tpd.Ident if x.isTerm => Some(x.name.show) - case _ => None - } - } - - object Select extends SelectExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, String, Option[Signature])] = x match { - case x: tpd.Select if x.isTerm => - val sig = - if (x.symbol.signature == core.Signature.NotAMethod) None - else Some(x.symbol.signature) - Some((x.qualifier, x.name.toString, sig)) - case _ => None - } - } - - object Literal extends LiteralExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[Constant] = x match { - case Trees.Literal(const) => Some(const) - case _ => None - } - } - - object This extends ThisExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[Option[Id]] = x match { - case Trees.This(qual) => Some(optional(qual)) - case _ => None - } - } - - object New extends NewExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[TypeTree] = x match { - case x: tpd.New => Some(x.tpt) - case _ => None - } - } - - object NamedArg extends NamedArgExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(String, Term)] = x match { - case x: tpd.NamedArg if x.name.isInstanceOf[Names.TermName] => Some((x.name.toString, x.arg)) - case _ => None - } - } - - object Apply extends ApplyExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[Term])] = x match { - case x: tpd.Apply => Some((x.fun, x.args)) - case _ => None - } - } - - object TypeApply extends TypeApplyExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[TypeTree])] = x match { - case x: tpd.TypeApply => Some((x.fun, x.args)) - case _ => None - } - } - - object Super extends SuperExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, Option[Id])] = x match { - case x: tpd.Super => Some((x.qual, if (x.mix.isEmpty) None else Some(x.mix))) - case _ => None - } - } - - object Typed extends TypedExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, TypeTree)] = x match { - case x: tpd.Typed => Some((x.expr, x.tpt)) - case _ => None - } - } - - object Assign extends AssignExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { - case x: tpd.Assign => Some((x.lhs, x.rhs)) - case _ => None - } - } - - object Block extends BlockExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(List[Statement], Term)] = normalizedLoops(x) match { - case Trees.Block(_, expr) if expr.symbol.is(Flags.Label) => None // while or doWhile loops - case Trees.Block(stats, expr) => Some((stats, expr)) - case _ => None - } - /** Normalizes non Blocks. - * i) Put `while` and `doWhile` loops in their own blocks: `{ def while$() = ...; while$() }` - * ii) Put closures in their own blocks: `{ def anon$() = ...; closure(anon$, ...) }` - */ - private def normalizedLoops(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match { - case block: tpd.Block if block.stats.size > 1 => - def normalizeInnerLoops(stats: List[tpd.Tree]): List[tpd.Tree] = stats match { - case (x: tpd.DefDef) :: y :: xs if needsNormalization(y) => - tpd.Block(x :: Nil, y) :: normalizeInnerLoops(xs) - case x :: xs => x :: normalizeInnerLoops(xs) - case Nil => Nil - } - if (needsNormalization(block.expr)) { - val stats1 = normalizeInnerLoops(block.stats.init) - val normalLoop = tpd.Block(block.stats.last :: Nil, block.expr) - tpd.Block(stats1, normalLoop) - } else { - val stats1 = normalizeInnerLoops(block.stats) - tpd.cpy.Block(block)(stats1, block.expr) - } - case _ => tree - } - - /** If it is the second statement of a loop or a closure. See: `normalizedLoops` */ - private def needsNormalization(tree: tpd.Tree)(implicit ctx: Context): Boolean = tree match { - case _: tpd.Closure => true - case _ => tree.symbol.is(Flags.Label) - } - } - - object Inlined extends InlinedExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Option[Term], List[Statement], Term)] = x match { - case x: tpd.Inlined => - Some((optional(x.call), x.bindings, x.expansion)) - case _ => None - } - } - - object Lambda extends LambdaExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, Option[TypeTree])] = x match { - case x: tpd.Closure => Some((x.meth, optional(x.tpt))) - case _ => None - } - } - - object If extends IfExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term, Term)] = x match { - case x: tpd.If => Some((x.cond, x.thenp, x.elsep)) - case _ => None - } - } - - object Match extends MatchExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[CaseDef])] = x match { - case x: tpd.Match => Some((x.selector, x.cases)) - case _ => None - } - } - - object Try extends TryExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[CaseDef], Option[Term])] = x match { - case x: tpd.Try => Some((x.expr, x.cases, optional(x.finalizer))) - case _ => None - } - } - - object Return extends ReturnExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[Term] = x match { - case x: tpd.Return => Some(x.expr) - case _ => None - } - } - - object Repeated extends RepeatedExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[List[Term]] = x match { - case x: tpd.SeqLiteral => Some(x.elems) - case _ => None - } - } - - object SelectOuter extends SelectOuterExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, Int, Type)] = x match { - case x: tpd.Select => - x.name match { - case NameKinds.OuterSelectName(_, levels) => Some((x.qualifier, levels, x.tpe.stripTypeVar)) - case _ => None - } - case _ => None - } - } - - object While extends WhileExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { - case Trees.Block((ddef: tpd.DefDef) :: Nil, expr) if expr.symbol.is(Flags.Label) && expr.symbol.name == nme.WHILE_PREFIX => - val Trees.If(cond, Trees.Block(bodyStats, _), _) = ddef.rhs - Some((cond, loopBody(bodyStats))) - case _ => None - } - } - - object DoWhile extends DoWhileExtractor { - def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { - case Trees.Block((ddef: tpd.DefDef) :: Nil, expr) if expr.symbol.is(Flags.Label) && expr.symbol.name == nme.DO_WHILE_PREFIX => - val Trees.Block(bodyStats, Trees.If(cond, _, _)) = ddef.rhs - Some((loopBody(bodyStats), cond)) - case _ => None - } - } - - private def loopBody(stats: List[tpd.Tree])(implicit ctx: Context): tpd.Tree = stats match { - case body :: Nil => body - case stats => tpd.Block(stats.init, stats.last) - } - } - - // ----- CaseDef -------------------------------------------------- - - type CaseDef = tpd.CaseDef - - def CaseDefDeco(caseDef: CaseDef): CaseDefAPI = new CaseDefAPI { - def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showCaseDef(caseDef) - def pattern(implicit ctx: Context): Pattern = caseDef.pat - def guard(implicit ctx: Context): Option[Term] = optional(caseDef.guard) - def rhs(implicit ctx: Context): Term = caseDef.body - } - - object CaseDef extends CaseDefExtractor { - def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = x match { - case x: tpd.CaseDef => - Some(x.pat, optional(x.guard), x.body) - case _ => None - } - } - - // ----- Patterns ------------------------------------------------- - - type Pattern = tpd.Tree - - def PatternDeco(pattern: Pattern): PatternAPI = new PatternAPI { - def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showPattern(pattern) - def pos(implicit ctx: Context): Position = pattern.pos - def tpe(implicit ctx: Context): Types.Type = pattern.tpe.stripTypeVar - } - - object Pattern extends PatternModule { - - object Value extends ValueExtractor { - def unapply(x: Pattern)(implicit ctx: Context): Option[Term] = x match { - case lit: tpd.Literal => Some(lit) - case ref: tpd.RefTree if ref.isTerm => Some(ref) - case ths: tpd.This => Some(ths) - case _ => None - } - } - - object Bind extends BindExtractor { - def unapply(x: Pattern)(implicit ctx: Context): Option[(String, Pattern)] = x match { - case x: tpd.Bind if x.name.isTermName => Some(x.name.toString, x.body) - case _ => None - } - } - - object Unapply extends UnapplyExtractor { - def unapply(x: Pattern)(implicit ctx: Context): Option[(Term, List[Term], List[Pattern])] = x match { - case Trees.UnApply(fun, implicits, patterns) => Some((fun, implicits, effectivePatterns(patterns))) - case Trees.Typed(Trees.UnApply(fun, implicits, patterns), _) => Some((fun, implicits, effectivePatterns(patterns))) - case _ => None - } - private def effectivePatterns(patterns: List[Pattern]): List[Pattern] = patterns match { - case patterns0 :+ Trees.SeqLiteral(elems, _) => patterns0 ::: elems - case _ => patterns - } - } - - object Alternative extends AlternativeExtractor { - def unapply(x: Pattern)(implicit ctx: Context): Option[List[Pattern]] = x match { - case x: tpd.Alternative => Some(x.trees) - case _ => None - } - } - - object TypeTest extends TypeTestExtractor { - def unapply(x: Pattern)(implicit ctx: Context): Option[TypeTree] = x match { - case Trees.Typed(Trees.UnApply(_, _, _), _) => None - case Trees.Typed(_, tpt) => Some(tpt) - case _ => None - } - } - - } - - - // ----- TypeOrBoundsTree ------------------------------------------------ - - type TypeOrBoundsTree = tpd.Tree - - def TypeOrBoundsTreeDeco(tpt: TypeOrBoundsTree): TypeOrBoundsTreeAPI = new TypeOrBoundsTreeAPI { - def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showTypeOrBoundsTree(tpt) - def tpe(implicit ctx: Context): Type = tpt.tpe.stripTypeVar - } - - // ----- TypeTrees ------------------------------------------------ - - type TypeTree = tpd.Tree - - def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI = new TypeTreeAPI { - def pos(implicit ctx: Context): Position = tpt.pos - def tpe(implicit ctx: Context): Types.Type = tpt.tpe.stripTypeVar - } - - object IsTypeTree extends IsTypeTreeExtractor { - def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] = - if (x.isType) Some(x) else None - def unapply(x: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[TypeTree] = - if (x.isType) Some(x) else None - } - - object TypeTree extends TypeTreeModule { - - object Synthetic extends SyntheticExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Boolean = x match { - case x @ Trees.TypeTree() => !x.tpe.isInstanceOf[Types.TypeBounds] - case _ => false - } - } - - object TypeIdent extends TypeIdentExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[String] = x match { - case x: tpd.Ident if x.isType => Some(x.name.toString) - case _ => None - } - } - - object TermSelect extends TermSelectExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(Term, String)] = x match { - case x: tpd.Select if x.isType && x.qualifier.isTerm => Some(x.qualifier, x.name.toString) - case _ => None - } - } - - object TypeSelect extends TypeSelectExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, String)] = x match { - case x: tpd.Select if x.isType && x.qualifier.isType => Some(x.qualifier, x.name.toString) - case _ => None - } - } - - object Singleton extends SingletonExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[Term] = x match { - case x: tpd.SingletonTypeTree => Some(x.ref) - case _ => None - } - } - - object Refined extends RefinedExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[Definition])] = x match { - case x: tpd.RefinedTypeTree => Some(x.tpt, x.refinements) - case _ => None - } - } - - object Applied extends AppliedExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])] = x match { - case x: tpd.AppliedTypeTree => Some(x.tpt, x.args) - case _ => None - } - } - - object Annotated extends AnnotatedExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, Term)] = x match { - case x: tpd.Annotated => Some(x.arg, x.annot) - case _ => None - } - } - - object And extends AndExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { - case x: tpd.AndTypeTree => Some(x.left, x.right) - case _ => None - } - } - - object Or extends OrExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { - case x: tpd.OrTypeTree => Some(x.left, x.right) - case _ => None - } - } - - object ByName extends ByNameExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[TypeTree] = x match { - case x: tpd.ByNameTypeTree => Some(x.result) - case _ => None - } - } - - object TypeLambdaTree extends TypeLambdaTreeExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(List[TypeDef], TypeOrBoundsTree)] = x match { - case Trees.LambdaTypeTree(tparams, body) => Some((tparams, body)) - case _ => None - } - } - - object Bind extends BindExtractor { - def unapply(x: TypeTree)(implicit ctx: Context): Option[(String, TypeBoundsTree)] = x match { - case x: tpd.Bind if x.name.isTypeName => Some((x.name.toString, x.body)) - case _ => None - } - } - } - - // ----- TypeBoundsTrees ------------------------------------------------ - - type TypeBoundsTree = tpd.Tree - - def TypeBoundsTreeDeco(bounds: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI { - def tpe(implicit ctx: Context): TypeBounds = bounds.tpe.asInstanceOf[Types.TypeBounds] - def low(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].lo - def hi(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].hi - } - - object IsTypeBoundsTree extends IsTypeBoundsTreeExtractor { - def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBoundsTree] = x match { - case x: tpd.TypeBoundsTree => Some(x) - case _ => None - } - } - - object TypeBoundsTree extends TypeBoundsTreeExtractor { - def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { - case x: tpd.TypeBoundsTree => Some(x.lo, x.hi) - case _ => None - } - } - - object SyntheticBounds extends SyntheticBoundsExtractor { - def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Boolean = x match { - case x @ Trees.TypeTree() => x.tpe.isInstanceOf[Types.TypeBounds] - case Trees.Ident(nme.WILDCARD) => x.tpe.isInstanceOf[Types.TypeBounds] - case _ => false - } - } - - // ===== Types ==================================================== - - type TypeOrBounds = Types.Type - - def TypeOrBoundsDeco(tpe: Types.Type): TypeOrBoundsAPI = new TypeOrBoundsAPI { - def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showTypeOrBounds(tpe) - } - - // ----- Types ---------------------------------------------------- - - type Type = Types.Type - - def TypeDeco(tpe: Type): TypeAPI = new TypeAPI { - def =:=(other: Type)(implicit ctx: Context): Boolean = tpe =:= other - def <:<(other: Type)(implicit ctx: Context): Boolean = tpe <:< other - } - - type RecursiveType = Types.RecType - type LambdaType[ParamInfo <: TypeOrBounds] = Types.LambdaType { type PInfo = ParamInfo } - type MethodType = Types.MethodType - type PolyType = Types.PolyType - type TypeLambda = Types.TypeLambda - - def MethodTypeDeco(tpe: MethodType): MethodTypeAPI = new MethodTypeAPI { - def isErased: Boolean = tpe.isErasedMethod - def isImplicit: Boolean = tpe.isImplicitMethod - def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) - def paramTypes(implicit ctx: Context): List[Type] = tpe.paramInfos - def resultTpe(implicit ctx: Context): Type = tpe.resType - } - - def PolyTypeDeco(tpe: Types.PolyType): PolyTypeAPI = new PolyTypeAPI { - def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) - def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos - def resultTpe(implicit ctx: Context): Type = tpe.resType - } - - def TypeLambdaDeco(tpe: Types.TypeLambda): TypeLambdaAPI = new TypeLambdaAPI { - def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) - def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos - def resultTpe(implicit ctx: Context): Type = tpe.resType - } - - object IsType extends IsTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { - case x: Types.TypeBounds => None - case x if x == Types.NoPrefix => None - case _ => Some(x) - } - } - - object Type extends TypeModule { - - object ConstantType extends ConstantTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Constant] = x match { - case Types.ConstantType(value) => Some(value) - case _ => None - } - } - - object SymRef extends SymRefExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Definition, TypeOrBounds /* Type | NoPrefix */)] = x match { - case tp: Types.NamedType => - tp.designator match { - case sym: Symbol => Some((definitionFromSym(sym), tp.prefix)) - case _ => None - } - case _ => None - } - } - - object TermRef extends TermRefExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] = x match { - case tp: Types.NamedType => - tp.designator match { - case name: Names.TermName => Some(name.toString, tp.prefix) - case _ => None - } - case _ => None - } - } - - object TypeRef extends TypeRefExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] = x match { - case tp: Types.NamedType => - tp.designator match { - case name: Names.TypeName => Some(name.toString, tp.prefix) - case _ => None - } - case _ => None - } - } - - object SuperType extends SuperTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { - case Types.SuperType(thistpe, supertpe) => Some(thistpe, supertpe) - case _ => None - } - } - - object Refinement extends RefinementExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, String, TypeOrBounds /* Type | TypeBounds */)] = x match { - case Types.RefinedType(parent, name, info) => Some(parent, name.toString, info) - case _ => None - } - } - - object AppliedType extends AppliedTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, List[TypeOrBounds /* Type | TypeBounds */])] = x match { - case Types.AppliedType(tycon, args) => Some((tycon.stripTypeVar, args.map(_.stripTypeVar))) - case _ => None - } - } - - object AnnotatedType extends AnnotatedTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Term)] = x match { - case Types.AnnotatedType(underlying, annot) => Some((underlying.stripTypeVar, annot.tree)) - case _ => None - } - } - - object AndType extends AndTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { - case Types.AndType(left, right) => Some(left.stripTypeVar, right.stripTypeVar) - case _ => None - } - } - - object OrType extends OrTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { - case Types.OrType(left, right) => Some(left.stripTypeVar, right.stripTypeVar) - case _ => None - } - } - - object ByNameType extends ByNameTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { - case Types.ExprType(resType) => Some(resType.stripTypeVar) - case _ => None - } - } - - object ParamRef extends ParamRefExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(LambdaType[TypeOrBounds], Int)] = x match { - case Types.TypeParamRef(binder, idx) => - Some(( - binder.asInstanceOf[LambdaType[TypeOrBounds]], // Cast to tpd - idx)) - case Types.TermParamRef(binder, idx) => Some((binder, idx)) - case _ => None - } - } - - object ThisType extends ThisTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { - case Types.ThisType(tp) => Some(tp) - case _ => None - } - } - - object RecursiveThis extends RecursiveThisExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[RecursiveType] = x match { - case Types.RecThis(binder) => Some(binder) - case _ => None - } - } - - object RecursiveType extends RecursiveTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { - case tp: Types.RecType => Some(tp.underlying.stripTypeVar) - case _ => None - } - } - - object MethodType extends MethodTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[Type], Type)] = x match { - case x: MethodType => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType) - case _ => None - } - } - - object PolyType extends PolyTypeExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = x match { - case x: PolyType => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType) - case _ => None - } - } - - object TypeLambda extends TypeLambdaExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = x match { - case x: TypeLambda => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType) - case _ => None - } - } - - } - - // ----- TypeBounds ------------------------------------------------ - - type TypeBounds = Types.TypeBounds - - object IsTypeBounds extends IsTypeBoundsExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[TypeBounds] = x match { - case x: Types.TypeBounds => Some(x) - case _ => None - } - } - - object TypeBounds extends TypeBoundsExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { - case x: Types.TypeBounds => Some(x.lo, x.hi) - case _ => None - } - } - - def TypeBoundsDeco(tpe: TypeBounds): TypeBoundsAPI = new TypeBoundsAPI { - def low(implicit ctx: Context): Type = tpe.lo - def hi(implicit ctx: Context): Type = tpe.hi - } - - // ----- NoPrefix -------------------------------------------------- - - type NoPrefix = Types.NoPrefix.type - - object NoPrefix extends NoPrefixExtractor { - def unapply(x: TypeOrBounds)(implicit ctx: Context): Boolean = x == Types.NoPrefix - } - - // ===== Constants ================================================ - - type Constant = Constants.Constant - - def ConstantDeco(const: Constant): ConstantAPI = new ConstantAPI { - def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showConstant(const) - def value: Any = const.value - } - - object Constant extends ConstantModule { - - object Unit extends UnitExtractor { - def unapply(x: Constant): Boolean = x match { - case x: Constants.Constant => x.tag == Constants.UnitTag - case _ => false - } - } - - object Null extends NullExtractor { - def unapply(x: Constant): Boolean = x match { - case x: Constants.Constant => x.tag == Constants.NullTag - case _ => false - } - } - - object Boolean extends BooleanExtractor { - def unapply(x: Constant): Option[Boolean] = x match { - case x: Constants.Constant if x.tag == Constants.BooleanTag => Some(x.booleanValue) - case _ => None - } - } - - object Byte extends ByteExtractor { - def unapply(x: Constant): Option[Byte] = x match { - case x: Constants.Constant if x.tag == Constants.ByteTag => Some(x.byteValue) - case _ => None - } - } - - object Short extends ShortExtractor { - def unapply(x: Constant): Option[Short] = x match { - case x: Constants.Constant if x.tag == Constants.ShortTag => Some(x.shortValue) - case _ => None - } - } - - object Char extends CharExtractor { - def unapply(x: Constant): Option[Char] = x match { - case x: Constants.Constant if x.tag == Constants.CharTag => Some(x.charValue) - case _ => None - } - } - - object Int extends IntExtractor { - def unapply(x: Constant): Option[Int] = x match { - case x: Constants.Constant if x.tag == Constants.IntTag => Some(x.intValue) - case _ => None - } - } - - object Long extends LongExtractor { - def unapply(x: Constant): Option[Long] = x match { - case x: Constants.Constant if x.tag == Constants.LongTag => Some(x.longValue) - case _ => None - } - } - - object Float extends FloatExtractor { - def unapply(x: Constant): Option[Float] = x match { - case x: Constants.Constant if x.tag == Constants.FloatTag => Some(x.floatValue) - case _ => None - } - } - - object Double extends DoubleExtractor { - def unapply(x: Constant): Option[Double] = x match { - case x: Constants.Constant if x.tag == Constants.DoubleTag => Some(x.doubleValue) - case _ => None - } - } - - object String extends StringExtractor { - def unapply(x: Constant): Option[String] = x match { - case x: Constants.Constant if x.tag == Constants.StringTag => Some(x.stringValue) - case _ => None - } - } - - object ClassTag extends ClassTagExtractor { - def unapply(x: Constant): Option[Type] = x match { - case x: Constants.Constant if x.tag == Constants.ClazzTag => Some(x.typeValue) - case _ => None - } - } - - object Symbol extends SymbolExtractor { - def unapply(x: Constant): Option[scala.Symbol] = x match { - case x: Constants.Constant if x.tag == Constants.ScalaSymbolTag => Some(x.scalaSymbolValue) - case _ => None - } - } - } - - // ===== Signature ================================================ - - type Signature = core.Signature - - object Signature extends SignatureExtractor { - def unapply(x: Signature)(implicit ctx: Context): Option[(List[String], String)] = { - Some((x.paramsSig.map(_.toString), x.resSig.toString)) - } - } - - def SignatureDeco(sig: Signature): SignatureAPI = new SignatureAPI { - def paramSigs: List[String] = sig.paramsSig.map(_.toString) - def resultSig: String = sig.resSig.toString - } - - // ===== Positions ================================================ - - type Position = SourcePosition - - def PositionDeco(pos: Position): PositionAPI = new PositionAPI { - def start = pos.start - def end = pos.end - - def sourceFile = pos.source.file.jpath - - def startLine = pos.startLine - def endLine = pos.endLine - - def startColumn = pos.startColumn - def endColumn = pos.endColumn - } - - // ===== Helpers ================================================== - - private def optional[T <: Trees.Tree[_]](tree: T): Option[tree.type] = - if (tree.isEmpty) None else Some(tree) - -} +class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty with TastyCoreImpl with CaseDefOpsImpl with ConstantOpsImpl with ContextOpsImpl with IdOpsImpl with ImportSelectorOpsImpl with QuotedOpsImpl with PatternOpsImpl with PositionOpsImpl with PrintersImpl with SignatureOpsImpl with StandardDefinitions with TreeOpsImpl with TypeOrBoundsTreesOpsImpl with TypeOrBoundsOpsImpl diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala new file mode 100644 index 000000000000..7ff0fe7d86f7 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala @@ -0,0 +1,429 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.ast.{Trees, tpd, untpd} +import dotty.tools.dotc.core +import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.StdNames.nme +import dotty.tools.dotc.core._ +import dotty.tools.dotc.reporting.Reporter +import dotty.tools.dotc.reporting.diagnostic.MessageContainer +import dotty.tools.dotc.tastyreflect.FromSymbol.{definitionFromSym, packageDefFromSym} + +trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with TastyCoreImpl with Helpers { + + def TreeDeco(tree: Tree): TreeAPI = new TreeAPI { + def pos(implicit ctx: Context): Position = tree.pos + } + + object IsPackageClause extends IsPackageClauseExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[PackageClause] = tree match { + case x: tpd.PackageDef => Some(x) + case _ => None + } + } + + object PackageClause extends PackageClauseExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Tree])] = tree match { + case x: tpd.PackageDef => Some((x.pid, x.stats)) + case _ => None + } + } + + def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI { + def definition(implicit ctx: Context): Definition = packageDefFromSym(pack.symbol) + } + + // ----- Statements ----------------------------------------------- + + object Import extends ImportExtractor { + def unapply(x: Tree)(implicit ctx: Context): Option[(Term, List[ImportSelector])] = x match { + case x: tpd.Import => Some((x.expr, x.selectors)) + case _ => None + } + } + + def ImportDeco(imp: Import): ImportAPI = new ImportAPI { + def expr(implicit ctx: Context): Tree = imp.expr + def selector(implicit ctx: Context): List[ImportSelector] = imp.selectors + } + + // ----- Definitions ---------------------------------------------- + + object IsDefinition extends IsDefinitionExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[Definition] = tree match { + case tree: tpd.MemberDef => Some(tree) + case tree: PackageDefinition => Some(tree) + case _ => None + } + } + + def DefinitionDeco(definition: Definition): DefinitionAPI = new DefinitionAPI { + + def name(implicit ctx: Context): String = definition.symbol.name.toString + + def owner(implicit ctx: Context): Definition = definitionFromSym(definition.symbol.owner) + + def flags(implicit ctx: Context): FlagSet = + new FlagSet(definition.symbol.flags) + + def privateWithin(implicit ctx: Context): Option[Type] = { + val within = definition.symbol.privateWithin + if (within.exists && !definition.symbol.is(core.Flags.Protected)) Some(within.typeRef) + else None + } + + def protectedWithin(implicit ctx: Context): Option[Type] = { + val within = definition.symbol.privateWithin + if (within.exists && definition.symbol.is(core.Flags.Protected)) Some(within.typeRef) + else None + } + + def annots(implicit ctx: Context): List[Term] = { + definition.symbol.annotations.flatMap { + case _: core.Annotations.LazyBodyAnnotation => Nil + case annot => annot.tree :: Nil + } + } + + def localContext(implicit ctx: Context): Context = + if (definition.hasType && definition.symbol.exists) ctx.withOwner(definition.symbol) + else ctx + } + + // ClassDef + + object IsClassDef extends IsClassDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[ClassDef] = tree match { + case x: tpd.TypeDef if x.isClassDef => Some(x) + case _ => None + } + } + + object ClassDef extends ClassDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, DefDef, List[Parent], Option[ValDef], List[Statement])] = tree match { + case Trees.TypeDef(name, impl: tpd.Template) => + Some((name.toString, impl.constr, impl.parents, optional(impl.self), impl.body)) + case _ => None + } + } + + def ClassDefDeco(cdef: ClassDef): ClassDefAPI = new ClassDefAPI { + private def rhs = cdef.rhs.asInstanceOf[tpd.Template] + def constructor(implicit ctx: Context): DefDef = rhs.constr + def parents(implicit ctx: Context): List[tpd.Tree] = rhs.parents + def self(implicit ctx: Context): Option[tpd.ValDef] = optional(rhs.self) + def body(implicit ctx: Context): List[tpd.Tree] = rhs.body + } + + // DefDef + + object IsDefDef extends IsDefDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[DefDef] = tree match { + case x: tpd.DefDef => Some(x) + case _ => None + } + } + + object DefDef extends DefDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] = tree match { + case x: tpd.DefDef => + Some((x.name.toString, x.tparams, x.vparamss, x.tpt, optional(x.rhs))) + case _ => None + } + } + + def DefDefDeco(ddef: DefDef): DefDefAPI = new DefDefAPI { + def typeParams(implicit ctx: Context): List[TypeDef] = ddef.tparams + def paramss(implicit ctx: Context): List[List[ValDef]] = ddef.vparamss + def returnTpt(implicit ctx: Context): TypeTree = ddef.tpt + def rhs(implicit ctx: Context): Option[Tree] = optional(ddef.rhs) + } + + // ValDef + + object IsValDef extends IsValDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[ValDef] = tree match { + case x: tpd.ValDef => Some(x) + case _ => None + } + } + + object ValDef extends ValDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] = tree match { + case x: tpd.ValDef => + Some((x.name.toString, x.tpt, optional(x.rhs))) + case _ => None + } + } + + def ValDefDeco(vdef: ValDef): ValDefAPI = new ValDefAPI { + def tpt(implicit ctx: Context): TypeTree = vdef.tpt + def rhs(implicit ctx: Context): Option[Tree] = optional(vdef.rhs) + } + + // TypeDef + + object IsTypeDef extends IsTypeDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[TypeDef] = tree match { + case x: tpd.TypeDef if !x.symbol.isClass => Some(x) + case _ => None + } + } + + object TypeDef extends TypeDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree /* TypeTree | TypeBoundsTree */)] = tree match { + case x: tpd.TypeDef if !x.symbol.isClass => Some((x.name.toString, x.rhs)) + case _ => None + } + } + + def TypeDefDeco(tdef: TypeDef): TypeDefAPI = new TypeDefAPI { + def rhs(implicit ctx: Context): TypeOrBoundsTree = tdef.rhs + } + + // PackageDef + + def PackageDefDeco(pdef: PackageDef): PackageDefAPI = new PackageDefAPI { + + def owner(implicit ctx: Context): PackageDefinition = packageDefFromSym(pdef.symbol.owner) + + def members(implicit ctx: Context): List[Statement] = { + if (pdef.symbol.is(core.Flags.JavaDefined)) Nil // FIXME should also support java packages + else pdef.symbol.info.decls.iterator.map(definitionFromSym).toList + } + } + + object IsPackageDef extends IsPackageDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[PackageDef] = tree match { + case x: PackageDefinition => Some(x) + case _ => None + } + } + + object PackageDef extends PackageDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, PackageDef)] = tree match { + case x: PackageDefinition => + Some((x.symbol.name.toString, packageDefFromSym(x.symbol.owner))) + case _ => None + } + } + + // ----- Terms ---------------------------------------------------- + + def TermDeco(term: Term): TermAPI = new TermAPI { + def pos(implicit ctx: Context): Position = term.pos + def tpe(implicit ctx: Context): Types.Type = term.tpe + } + + object IsTerm extends IsTermExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[Term] = + if (tree.isTerm) Some(tree) else None + def unapply(parent: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[Term] = + if (parent.isTerm) Some(parent) else None + } + + object Term extends TermModule { + + object Ident extends IdentExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[String] = x match { + case x: tpd.Ident if x.isTerm => Some(x.name.show) + case _ => None + } + } + + object Select extends SelectExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, String, Option[Signature])] = x match { + case x: tpd.Select if x.isTerm => + val sig = + if (x.symbol.signature == core.Signature.NotAMethod) None + else Some(x.symbol.signature) + Some((x.qualifier, x.name.toString, sig)) + case _ => None + } + } + + object Literal extends LiteralExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[Constant] = x match { + case Trees.Literal(const) => Some(const) + case _ => None + } + } + + object This extends ThisExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[Option[Id]] = x match { + case Trees.This(qual) => Some(optional(qual)) + case _ => None + } + } + + object New extends NewExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[TypeTree] = x match { + case x: tpd.New => Some(x.tpt) + case _ => None + } + } + + object NamedArg extends NamedArgExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(String, Term)] = x match { + case x: tpd.NamedArg if x.name.isInstanceOf[Names.TermName] => Some((x.name.toString, x.arg)) + case _ => None + } + } + + object Apply extends ApplyExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[Term])] = x match { + case x: tpd.Apply => Some((x.fun, x.args)) + case _ => None + } + } + + object TypeApply extends TypeApplyExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[TypeTree])] = x match { + case x: tpd.TypeApply => Some((x.fun, x.args)) + case _ => None + } + } + + object Super extends SuperExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Option[Id])] = x match { + case x: tpd.Super => Some((x.qual, if (x.mix.isEmpty) None else Some(x.mix))) + case _ => None + } + } + + object Typed extends TypedExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, TypeTree)] = x match { + case x: tpd.Typed => Some((x.expr, x.tpt)) + case _ => None + } + } + + object Assign extends AssignExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { + case x: tpd.Assign => Some((x.lhs, x.rhs)) + case _ => None + } + } + + object Block extends BlockExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(List[Statement], Term)] = normalizedLoops(x) match { + case Trees.Block(_, expr) if expr.symbol.is(Flags.Label) => None // while or doWhile loops + case Trees.Block(stats, expr) => Some((stats, expr)) + case _ => None + } + /** Normalizes non Blocks. + * i) Put `while` and `doWhile` loops in their own blocks: `{ def while$() = ...; while$() }` + * ii) Put closures in their own blocks: `{ def anon$() = ...; closure(anon$, ...) }` + */ + private def normalizedLoops(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match { + case block: tpd.Block if block.stats.size > 1 => + def normalizeInnerLoops(stats: List[tpd.Tree]): List[tpd.Tree] = stats match { + case (x: tpd.DefDef) :: y :: xs if needsNormalization(y) => + tpd.Block(x :: Nil, y) :: normalizeInnerLoops(xs) + case x :: xs => x :: normalizeInnerLoops(xs) + case Nil => Nil + } + if (needsNormalization(block.expr)) { + val stats1 = normalizeInnerLoops(block.stats.init) + val normalLoop = tpd.Block(block.stats.last :: Nil, block.expr) + tpd.Block(stats1, normalLoop) + } else { + val stats1 = normalizeInnerLoops(block.stats) + tpd.cpy.Block(block)(stats1, block.expr) + } + case _ => tree + } + + /** If it is the second statement of a loop or a closure. See: `normalizedLoops` */ + private def needsNormalization(tree: tpd.Tree)(implicit ctx: Context): Boolean = tree match { + case _: tpd.Closure => true + case _ => tree.symbol.is(Flags.Label) + } + } + + object Inlined extends InlinedExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Option[Term], List[Statement], Term)] = x match { + case x: tpd.Inlined => + Some((optional(x.call), x.bindings, x.expansion)) + case _ => None + } + } + + object Lambda extends LambdaExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Option[TypeTree])] = x match { + case x: tpd.Closure => Some((x.meth, optional(x.tpt))) + case _ => None + } + } + + object If extends IfExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term, Term)] = x match { + case x: tpd.If => Some((x.cond, x.thenp, x.elsep)) + case _ => None + } + } + + object Match extends MatchExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[CaseDef])] = x match { + case x: tpd.Match => Some((x.selector, x.cases)) + case _ => None + } + } + + object Try extends TryExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[CaseDef], Option[Term])] = x match { + case x: tpd.Try => Some((x.expr, x.cases, optional(x.finalizer))) + case _ => None + } + } + + object Return extends ReturnExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[Term] = x match { + case x: tpd.Return => Some(x.expr) + case _ => None + } + } + + object Repeated extends RepeatedExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[List[Term]] = x match { + case x: tpd.SeqLiteral => Some(x.elems) + case _ => None + } + } + + object SelectOuter extends SelectOuterExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Int, Type)] = x match { + case x: tpd.Select => + x.name match { + case NameKinds.OuterSelectName(_, levels) => Some((x.qualifier, levels, x.tpe.stripTypeVar)) + case _ => None + } + case _ => None + } + } + + object While extends WhileExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { + case Trees.Block((ddef: tpd.DefDef) :: Nil, expr) if expr.symbol.is(Flags.Label) && expr.symbol.name == nme.WHILE_PREFIX => + val Trees.If(cond, Trees.Block(bodyStats, _), _) = ddef.rhs + Some((cond, loopBody(bodyStats))) + case _ => None + } + } + + object DoWhile extends DoWhileExtractor { + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { + case Trees.Block((ddef: tpd.DefDef) :: Nil, expr) if expr.symbol.is(Flags.Label) && expr.symbol.name == nme.DO_WHILE_PREFIX => + val Trees.Block(bodyStats, Trees.If(cond, _, _)) = ddef.rhs + Some((loopBody(bodyStats), cond)) + case _ => None + } + } + + private def loopBody(stats: List[tpd.Tree])(implicit ctx: Context): tpd.Tree = stats match { + case body :: Nil => body + case stats => tpd.Block(stats.init, stats.last) + } + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsOpsImpl.scala new file mode 100644 index 000000000000..de9f1b6ce934 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsOpsImpl.scala @@ -0,0 +1,217 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.core.Symbols.Symbol +import dotty.tools.dotc.core.{Names, Types} +import dotty.tools.dotc.tastyreflect.FromSymbol.definitionFromSym + +trait TypeOrBoundsOpsImpl extends scala.tasty.reflect.TypeOrBoundsOps with TastyCoreImpl { + + // ===== Types ==================================================== + + def TypeDeco(tpe: Type): TypeAPI = new TypeAPI { + def =:=(other: Type)(implicit ctx: Context): Boolean = tpe =:= other + def <:<(other: Type)(implicit ctx: Context): Boolean = tpe <:< other + } + + def MethodTypeDeco(tpe: MethodType): MethodTypeAPI = new MethodTypeAPI { + def isErased: Boolean = tpe.isErasedMethod + def isImplicit: Boolean = tpe.isImplicitMethod + def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) + def paramTypes(implicit ctx: Context): List[Type] = tpe.paramInfos + def resultTpe(implicit ctx: Context): Type = tpe.resType + } + + def PolyTypeDeco(tpe: Types.PolyType): PolyTypeAPI = new PolyTypeAPI { + def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) + def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos + def resultTpe(implicit ctx: Context): Type = tpe.resType + } + + def TypeLambdaDeco(tpe: Types.TypeLambda): TypeLambdaAPI = new TypeLambdaAPI { + def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) + def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos + def resultTpe(implicit ctx: Context): Type = tpe.resType + } + + object IsType extends IsTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { + case x: Types.TypeBounds => None + case x if x == Types.NoPrefix => None + case _ => Some(x) + } + } + + object Type extends TypeModule { + + object ConstantType extends ConstantTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Constant] = x match { + case Types.ConstantType(value) => Some(value) + case _ => None + } + } + + object SymRef extends SymRefExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Definition, TypeOrBounds /* Type | NoPrefix */)] = x match { + case tp: Types.NamedType => + tp.designator match { + case sym: Symbol => Some((definitionFromSym(sym), tp.prefix)) + case _ => None + } + case _ => None + } + } + + object TermRef extends TermRefExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] = x match { + case tp: Types.NamedType => + tp.designator match { + case name: Names.TermName => Some(name.toString, tp.prefix) + case _ => None + } + case _ => None + } + } + + object TypeRef extends TypeRefExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] = x match { + case tp: Types.NamedType => + tp.designator match { + case name: Names.TypeName => Some(name.toString, tp.prefix) + case _ => None + } + case _ => None + } + } + + object SuperType extends SuperTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { + case Types.SuperType(thistpe, supertpe) => Some(thistpe, supertpe) + case _ => None + } + } + + object Refinement extends RefinementExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, String, TypeOrBounds /* Type | TypeBounds */)] = x match { + case Types.RefinedType(parent, name, info) => Some(parent, name.toString, info) + case _ => None + } + } + + object AppliedType extends AppliedTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, List[TypeOrBounds /* Type | TypeBounds */])] = x match { + case Types.AppliedType(tycon, args) => Some((tycon.stripTypeVar, args.map(_.stripTypeVar))) + case _ => None + } + } + + object AnnotatedType extends AnnotatedTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Term)] = x match { + case Types.AnnotatedType(underlying, annot) => Some((underlying.stripTypeVar, annot.tree)) + case _ => None + } + } + + object AndType extends AndTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { + case Types.AndType(left, right) => Some(left.stripTypeVar, right.stripTypeVar) + case _ => None + } + } + + object OrType extends OrTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { + case Types.OrType(left, right) => Some(left.stripTypeVar, right.stripTypeVar) + case _ => None + } + } + + object ByNameType extends ByNameTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { + case Types.ExprType(resType) => Some(resType.stripTypeVar) + case _ => None + } + } + + object ParamRef extends ParamRefExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(LambdaType[TypeOrBounds], Int)] = x match { + case Types.TypeParamRef(binder, idx) => + Some(( + binder.asInstanceOf[LambdaType[TypeOrBounds]], // Cast to tpd + idx)) + case Types.TermParamRef(binder, idx) => Some((binder, idx)) + case _ => None + } + } + + object ThisType extends ThisTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { + case Types.ThisType(tp) => Some(tp) + case _ => None + } + } + + object RecursiveThis extends RecursiveThisExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[RecursiveType] = x match { + case Types.RecThis(binder) => Some(binder) + case _ => None + } + } + + object RecursiveType extends RecursiveTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match { + case tp: Types.RecType => Some(tp.underlying.stripTypeVar) + case _ => None + } + } + + object MethodType extends MethodTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[Type], Type)] = x match { + case x: MethodType => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType) + case _ => None + } + } + + object PolyType extends PolyTypeExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = x match { + case x: PolyType => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType) + case _ => None + } + } + + object TypeLambda extends TypeLambdaExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = x match { + case x: TypeLambda => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType) + case _ => None + } + } + + } + + // ----- TypeBounds ------------------------------------------------ + + object IsTypeBounds extends IsTypeBoundsExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[TypeBounds] = x match { + case x: Types.TypeBounds => Some(x) + case _ => None + } + } + + object TypeBounds extends TypeBoundsExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] = x match { + case x: Types.TypeBounds => Some(x.lo, x.hi) + case _ => None + } + } + + def TypeBoundsDeco(tpe: TypeBounds): TypeBoundsAPI = new TypeBoundsAPI { + def low(implicit ctx: Context): Type = tpe.lo + def hi(implicit ctx: Context): Type = tpe.hi + } + + // ----- NoPrefix -------------------------------------------------- + + object NoPrefix extends NoPrefixExtractor { + def unapply(x: TypeOrBounds)(implicit ctx: Context): Boolean = x == Types.NoPrefix + } + +} diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala new file mode 100644 index 000000000000..c6189eaf606d --- /dev/null +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala @@ -0,0 +1,156 @@ +package dotty.tools.dotc.tastyreflect + +import dotty.tools.dotc.ast.{Trees, tpd} +import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.StdNames.nme +import dotty.tools.dotc.core.Types + +import scala.tasty.util.Show + +trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps with TastyCoreImpl { + + // ----- TypeOrBoundsTree ------------------------------------------------ + + def TypeOrBoundsTreeDeco(tpt: TypeOrBoundsTree): TypeOrBoundsTreeAPI = new TypeOrBoundsTreeAPI { + def tpe(implicit ctx: Context): Type = tpt.tpe.stripTypeVar + } + + // ----- TypeTrees ------------------------------------------------ + + def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI = new TypeTreeAPI { + def pos(implicit ctx: Context): Position = tpt.pos + def tpe(implicit ctx: Context): Types.Type = tpt.tpe.stripTypeVar + } + + object IsTypeTree extends IsTypeTreeExtractor { + def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] = + if (x.isType) Some(x) else None + def unapply(x: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[TypeTree] = + if (x.isType) Some(x) else None + } + + object TypeTree extends TypeTreeModule { + + object Synthetic extends SyntheticExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Boolean = x match { + case x @ Trees.TypeTree() => !x.tpe.isInstanceOf[Types.TypeBounds] + case _ => false + } + } + + object TypeIdent extends TypeIdentExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[String] = x match { + case x: tpd.Ident if x.isType => Some(x.name.toString) + case _ => None + } + } + + object TermSelect extends TermSelectExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(Term, String)] = x match { + case x: tpd.Select if x.isType && x.qualifier.isTerm => Some(x.qualifier, x.name.toString) + case _ => None + } + } + + object TypeSelect extends TypeSelectExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, String)] = x match { + case x: tpd.Select if x.isType && x.qualifier.isType => Some(x.qualifier, x.name.toString) + case _ => None + } + } + + object Singleton extends SingletonExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[Term] = x match { + case x: tpd.SingletonTypeTree => Some(x.ref) + case _ => None + } + } + + object Refined extends RefinedExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[Definition])] = x match { + case x: tpd.RefinedTypeTree => Some(x.tpt, x.refinements) + case _ => None + } + } + + object Applied extends AppliedExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])] = x match { + case x: tpd.AppliedTypeTree => Some(x.tpt, x.args) + case _ => None + } + } + + object Annotated extends AnnotatedExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, Term)] = x match { + case x: tpd.Annotated => Some(x.arg, x.annot) + case _ => None + } + } + + object And extends AndExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { + case x: tpd.AndTypeTree => Some(x.left, x.right) + case _ => None + } + } + + object Or extends OrExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { + case x: tpd.OrTypeTree => Some(x.left, x.right) + case _ => None + } + } + + object ByName extends ByNameExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[TypeTree] = x match { + case x: tpd.ByNameTypeTree => Some(x.result) + case _ => None + } + } + + object TypeLambdaTree extends TypeLambdaTreeExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(List[TypeDef], TypeOrBoundsTree)] = x match { + case Trees.LambdaTypeTree(tparams, body) => Some((tparams, body)) + case _ => None + } + } + + object Bind extends BindExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(String, TypeBoundsTree)] = x match { + case x: tpd.Bind if x.name.isTypeName => Some((x.name.toString, x.body)) + case _ => None + } + } + } + + // ----- TypeBoundsTrees ------------------------------------------------ + + def TypeBoundsTreeDeco(bounds: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI { + def tpe(implicit ctx: Context): TypeBounds = bounds.tpe.asInstanceOf[Types.TypeBounds] + def low(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].lo + def hi(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].hi + } + + object IsTypeBoundsTree extends IsTypeBoundsTreeExtractor { + def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBoundsTree] = x match { + case x: tpd.TypeBoundsTree => Some(x) + case _ => None + } + } + + object TypeBoundsTree extends TypeBoundsTreeExtractor { + def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { + case x: tpd.TypeBoundsTree => Some(x.lo, x.hi) + case _ => None + } + } + + object SyntheticBounds extends SyntheticBoundsExtractor { + def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Boolean = x match { + case x @ Trees.TypeTree() => x.tpe.isInstanceOf[Types.TypeBounds] + case Trees.Ident(nme.WILDCARD) => x.tpe.isInstanceOf[Types.TypeBounds] + case _ => false + } + } + +} diff --git a/library/src/scala/tasty/Tasty.scala b/library/src/scala/tasty/Tasty.scala index a85bf4c4bc7d..44da7b06be38 100644 --- a/library/src/scala/tasty/Tasty.scala +++ b/library/src/scala/tasty/Tasty.scala @@ -1,889 +1,5 @@ package scala.tasty -import scala.tasty.reflect.StandardDefinitions -import scala.tasty.util.Show +import scala.tasty.reflect._ -abstract class Tasty extends StandardDefinitions { tasty => - - // ===== Quotes =================================================== - - trait QuotedExprAPI { - def toTasty(implicit ctx: Context): Term - } - implicit def QuotedExprDeco[T](expr: quoted.Expr[T]): QuotedExprAPI - - trait QuotedTypeAPI { - def toTasty(implicit ctx: Context): TypeTree - } - implicit def QuotedTypeDeco[T](tpe: quoted.Type[T]): QuotedTypeAPI - - // ===== Show ===================================================== - - implicit def defaultShow: Show[tasty.type] - - def showExtractors: Show[tasty.type] - - def showSourceCode: Show[tasty.type] - - // ===== Contexts ================================================= - - type Context - - trait ContextAPI { - def owner: Definition - - /** Returns the source file being compiled. The path is relative to the current working directory. */ - def source: java.nio.file.Path - } - implicit def ContextDeco(ctx: Context): ContextAPI - - implicit def rootContext: Context - - /** Root position of this tasty context. For macros it corresponds to the expansion site. */ - def rootPosition: Position - - // ===== Id ======================================================= - - type Id - - trait IdAPI extends Positioned { - def name(implicit ctx: Context): String - } - implicit def IdDeco(id: Id): IdAPI - - val Id: IdExtractor - abstract class IdExtractor { - def unapply(id: Id): Option[String] - } - - // ===== Trees ==================================================== - - type Tree - - trait TreeAPI extends Positioned { - def show(implicit ctx: Context, s: Show[tasty.type]): String - } - implicit def TreeDeco(tree: Tree): TreeAPI - - type PackageClause <: Tree - - val IsPackageClause: IsPackageClauseExtractor - abstract class IsPackageClauseExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[PackageClause] - } - - val PackageClause: PackageClauseExtractor - abstract class PackageClauseExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Tree])] - } - - trait PackageClauseAPI { - def definition(implicit ctx: Context): Definition - } - implicit def PackageClauseDeco(pack: PackageClause): PackageClauseAPI - - // ----- Statements ----------------------------------------------- - - type Statement <: Tree - - type Import <: Statement - - val Import: ImportExtractor - abstract class ImportExtractor { - def unapply(imp: Tree)(implicit ctx: Context): Option[(Term, List[ImportSelector])] - } - - trait ImportAPI { - def expr(implicit ctx: Context): Term - def selector(implicit ctx: Context): List[ImportSelector] - } - implicit def ImportDeco(imp: Import): ImportAPI - - type ImportSelector - - val SimpleSelector: SimpleSelectorExtractor - abstract class SimpleSelectorExtractor { - def unapply(importSelector: ImportSelector)(implicit ctx: Context): Option[Id] - } - - val RenameSelector: RenameSelectorExtractor - abstract class RenameSelectorExtractor { - def unapply(importSelector: ImportSelector)(implicit ctx: Context): Option[(Id, Id)] - } - - val OmitSelector: OmitSelectorExtractor - abstract class OmitSelectorExtractor { - def unapply(importSelector: ImportSelector)(implicit ctx: Context): Option[Id] - } - - // ----- Definitions ---------------------------------------------- - - type Definition <: Statement - - val IsDefinition: IsDefinitionExtractor - abstract class IsDefinitionExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[Definition] - } - - trait DefinitionAPI { - def name(implicit ctx: Context): String - def flags(implicit ctx: Context): FlagSet - def privateWithin(implicit ctx: Context): Option[Type] - def protectedWithin(implicit ctx: Context): Option[Type] - def annots(implicit ctx: Context): List[Term] - def owner(implicit ctx: Context): Definition - def localContext(implicit ctx: Context): Context - } - implicit def DefinitionDeco(definition: Definition): DefinitionAPI - - // ClassDef - - type ClassDef <: Definition - - val IsClassDef: IsClassDefExtractor - abstract class IsClassDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[ClassDef] - } - - val ClassDef: ClassDefExtractor - abstract class ClassDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, DefDef, List[Parent], Option[ValDef], List[Statement])] - } - - trait ClassDefAPI { - def constructor(implicit ctx: Context): DefDef - def parents(implicit ctx: Context): List[Parent] - def self(implicit ctx: Context): Option[ValDef] - def body(implicit ctx: Context): List[Statement] - } - implicit def ClassDefDeco(cdef: ClassDef): ClassDefAPI - - // DefDef - - type DefDef <: Definition - - val IsDefDef: IsDefDefExtractor - abstract class IsDefDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[DefDef] - } - - val DefDef: DefDefExtractor - abstract class DefDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] - } - - trait DefDefAPI { - def typeParams(implicit ctx: Context): List[TypeDef] - def paramss(implicit ctx: Context): List[List[ValDef]] - def returnTpt(implicit ctx: Context): TypeTree - def rhs(implicit ctx: Context): Option[Term] - } - implicit def DefDefDeco(ddef: DefDef): DefDefAPI - - // ValDef - - type ValDef <: Definition - - val IsValDef: IsValDefExtractor - abstract class IsValDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[ValDef] - } - - val ValDef: ValDefExtractor - abstract class ValDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] - } - - trait ValDefAPI { - def tpt(implicit ctx: Context): TypeTree - def rhs(implicit ctx: Context): Option[Term] - } - implicit def ValDefDeco(vdef: ValDef): ValDefAPI - - // TypeDef - - type TypeDef <: Definition - - val IsTypeDef: IsTypeDefExtractor - abstract class IsTypeDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[TypeDef] - } - - val TypeDef: TypeDefExtractor - abstract class TypeDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree /* TypeTree | TypeBoundsTree */)] - } - - trait TypeDefAPI { - def rhs(implicit ctx: Context): TypeOrBoundsTree - } - implicit def TypeDefDeco(tdef: TypeDef): TypeDefAPI - - // PackageDef - - type PackageDef <: Definition - - val IsPackageDef: IsPackageDefExtractor - abstract class IsPackageDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[PackageDef] - } - - trait PackageDefAPI { - def owner(implicit ctx: Context): PackageDef - def members(implicit ctx: Context): List[Statement] - } - implicit def PackageDefDeco(pdef: PackageDef): PackageDefAPI - - val PackageDef: PackageDefExtractor - abstract class PackageDefExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, PackageDef)] - } - - // ----- Parents -------------------------------------------------- - - type Parent /* Term | TypeTree */ - - // ----- Terms ---------------------------------------------------- - - type Term <: Statement with Parent - - trait TermAPI extends Typed with Positioned { - def toExpr[T: quoted.Type](implicit ctx: Context): quoted.Expr[T] - } - implicit def TermDeco(term: Term): TermAPI - - val IsTerm: IsTermExtractor - abstract class IsTermExtractor { - /** Matches any term */ - def unapply(tree: Tree)(implicit ctx: Context): Option[Term] - /** Matches any term */ - def unapply(parent: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[Term] - } - - /** Scala term. Any tree that can go in expression position. */ - val Term: TermModule - abstract class TermModule { - - /** Scala term identifier */ - val Ident: IdentExtractor - abstract class IdentExtractor { - /** Matches a term identifier and returns its name */ - def unapply(tree: Tree)(implicit ctx: Context): Option[String] - } - - /** Scala term selection */ - val Select: SelectExtractor - abstract class SelectExtractor { - /** Matches `.: ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, String, Option[Signature])] - } - - /** Scala literal constant */ - val Literal: LiteralExtractor - abstract class LiteralExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[Constant] - } - - /** Scala `this` or `this[id]` */ - val This: ThisExtractor - abstract class ThisExtractor { - /** Matches new `this[` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[Option[Id]] - } - - /** Scala `new` */ - val New: NewExtractor - abstract class NewExtractor { - /** Matches new `new ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[TypeTree] - } - - /** Scala named argument `x = y` in argument position */ - val NamedArg: NamedArgExtractor - abstract class NamedArgExtractor { - /** Matches ` = ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(String, Term)] - } - - /** Scala parameter application */ - val Apply: ApplyExtractor - abstract class ApplyExtractor { - /** Matches function application `()` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Term])] - } - - /** Scala type parameter application */ - val TypeApply: TypeApplyExtractor - abstract class TypeApplyExtractor { - /** Matches function type application `[]` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[TypeTree])] - } - - /** Scala `x.super` or `x.super[id]` */ - val Super: SuperExtractor - abstract class SuperExtractor { - /** Matches new `.super[` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Option[Id])] - } - - /** Scala ascription `x: T` */ - val Typed: TypedExtractor - abstract class TypedExtractor { - /** Matches `: ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, TypeTree)] - } - - /** Scala assign `x = y` */ - val Assign: AssignExtractor - abstract class AssignExtractor { - /** Matches ` = ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] - } - - /** Scala code block `{ stat0; ...; statN; expr }` term */ - val Block: BlockExtractor - abstract class BlockExtractor { - /** Matches `{ ; }` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(List[Statement], Term)] - } - - val Lambda: LambdaExtractor - abstract class LambdaExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Option[TypeTree])] - } - - /** Scala `if`/`else` term */ - val If: IfExtractor - abstract class IfExtractor { - /** Matches `if () else ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term, Term)] - } - - /** Scala `match` term */ - val Match: MatchExtractor - abstract class MatchExtractor { - /** Matches ` match { }` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[CaseDef])] - } - - /** Scala `try`/`catch`/`finally` term */ - val Try: TryExtractor - abstract class TryExtractor { - /** Matches `try catch { } finally ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[CaseDef], Option[Term])] - } - - /** Scala local `return` */ - val Return: ReturnExtractor - abstract class ReturnExtractor { - /** Matches `return ` */ - def unapply(tree: Tree)(implicit ctx: Context): Option[Term] - } - - val Repeated: RepeatedExtractor - abstract class RepeatedExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[List[Term]] - } - - val Inlined: InlinedExtractor - abstract class InlinedExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Option[Term], List[Definition], Term)] - } - - val SelectOuter: SelectOuterExtractor - abstract class SelectOuterExtractor { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Int, Type)] - } - - val While: WhileExtractor - abstract class WhileExtractor { - /** Extractor for while loops. Matches `while () ` and returns (, ) */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] - } - - val DoWhile: DoWhileExtractor - abstract class DoWhileExtractor { - /** Extractor for do while loops. Matches `do while ()` and returns (, ) */ - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] - } - } - - // ----- CaseDef -------------------------------------------------- - - type CaseDef - - trait CaseDefAPI { - def show(implicit ctx: Context, s: Show[tasty.type]): String - def pattern(implicit ctx: Context): Pattern - def guard(implicit ctx: Context): Option[Term] - def rhs(implicit ctx: Context): Term - } - implicit def CaseDefDeco(caseDef: CaseDef): CaseDefAPI - - val CaseDef: CaseDefExtractor - abstract class CaseDefExtractor { - def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] - } - - // ----- Patterns ------------------------------------------------- - - type Pattern - - trait PatternAPI extends Typed with Positioned { - def show(implicit ctx: Context, s: Show[tasty.type]): String - - } - implicit def PatternDeco(pattern: Pattern): PatternAPI - - val Pattern: PatternModule - abstract class PatternModule { - - val Value: ValueExtractor - abstract class ValueExtractor { - def unapply(pattern: Pattern)(implicit ctx: Context): Option[Term] - } - - val Bind: BindExtractor - abstract class BindExtractor { - def unapply(pattern: Pattern)(implicit ctx: Context): Option[(String, Pattern)] - } - - val Unapply: UnapplyExtractor - abstract class UnapplyExtractor { - def unapply(pattern: Pattern)(implicit ctx: Context): Option[(Term, List[Term], List[Pattern])] - } - - val Alternative: AlternativeExtractor - abstract class AlternativeExtractor { - def unapply(pattern: Pattern)(implicit ctx: Context): Option[List[Pattern]] - } - - val TypeTest: TypeTestExtractor - abstract class TypeTestExtractor { - def unapply(pattern: Pattern)(implicit ctx: Context): Option[TypeTree] - } - - } - - // ----- TypeTrees ------------------------------------------------ - - type TypeOrBoundsTree - - trait TypeOrBoundsTreeAPI { - def show(implicit ctx: Context, s: Show[tasty.type]): String - def tpe(implicit ctx: Context): TypeOrBounds - } - implicit def TypeOrBoundsTreeDeco(tpt: TypeOrBoundsTree): TypeOrBoundsTreeAPI - - - // ----- TypeTrees ------------------------------------------------ - - type TypeTree <: TypeOrBoundsTree - - trait TypeTreeAPI extends Typed with Positioned - implicit def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI - - val IsTypeTree: IsTypeTreeExtractor - abstract class IsTypeTreeExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] - def unapply(parent: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[TypeTree] - } - - val TypeTree: TypeTreeModule - abstract class TypeTreeModule { - - /** TypeTree containing an inferred type */ - val Synthetic: SyntheticExtractor - abstract class SyntheticExtractor { - /** Matches a TypeTree containing an inferred type */ - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Boolean - } - - val TypeIdent: TypeIdentExtractor - abstract class TypeIdentExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[String] - } - - val TermSelect: TermSelectExtractor - abstract class TermSelectExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(Term, String)] - } - - val TypeSelect: TypeSelectExtractor - abstract class TypeSelectExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, String)] - } - - val Singleton: SingletonExtractor - abstract class SingletonExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[Term] - } - - val Refined: RefinedExtractor - abstract class RefinedExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, List[Definition])] - } - - val Applied: AppliedExtractor - abstract class AppliedExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])] - } - - val Annotated: AnnotatedExtractor - abstract class AnnotatedExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, Term)] - } - - val And: AndExtractor - abstract class AndExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] - } - - val Or: OrExtractor - abstract class OrExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] - } - - val ByName: ByNameExtractor - abstract class ByNameExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] - } - - val TypeLambdaTree: TypeLambdaTreeExtractor - abstract class TypeLambdaTreeExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(List[TypeDef], TypeOrBoundsTree)] - } - - val Bind: BindExtractor - abstract class BindExtractor{ - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(String, TypeBoundsTree)] - } - } - - // ----- TypeBoundsTrees ------------------------------------------------ - - type TypeBoundsTree <: TypeOrBoundsTree - - trait TypeBoundsTreeAPI { - def tpe(implicit ctx: Context): TypeBounds - def low(implicit ctx: Context): TypeTree - def hi(implicit ctx: Context): TypeTree - } - implicit def TypeBoundsTreeDeco(tpt: TypeBoundsTree): TypeBoundsTreeAPI - - val IsTypeBoundsTree: IsTypeBoundsTreeExtractor - abstract class IsTypeBoundsTreeExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBoundsTree] - } - - val TypeBoundsTree: TypeBoundsTreeExtractor - abstract class TypeBoundsTreeExtractor { - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] - } - - /** TypeBoundsTree containing an inferred type bounds */ - val SyntheticBounds: SyntheticBoundsExtractor - abstract class SyntheticBoundsExtractor { - /** Matches a TypeBoundsTree containing inferred type bounds */ - def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Boolean - } - - // ===== Types ==================================================== - - type TypeOrBounds - - trait Typed { - def tpe(implicit ctx: Context): Type - } - - trait TypeOrBoundsAPI { - def show(implicit ctx: Context, s: Show[tasty.type]): String - } - implicit def TypeOrBoundsDeco(tpe: TypeOrBounds): TypeOrBoundsAPI - - // ----- Types ---------------------------------------------------- - - type Type <: TypeOrBounds - - trait TypeAPI { - def =:=(other: Type)(implicit ctx: Context): Boolean - def <:<(other: Type)(implicit ctx: Context): Boolean - } - implicit def TypeDeco(tpe: Type): TypeAPI - - type RecursiveType <: Type - - type LambdaType[ParamInfo <: TypeOrBounds] <: Type - type MethodType <: LambdaType[Type] - type PolyType <: LambdaType[TypeBounds] - type TypeLambda <: LambdaType[TypeBounds] - - trait MethodTypeAPI { - def isImplicit: Boolean - def isErased: Boolean - def paramNames(implicit ctx: Context): List[String] - def paramTypes(implicit ctx: Context): List[Type] - def resultTpe(implicit ctx: Context): Type - } - implicit def MethodTypeDeco(tpt: MethodType): MethodTypeAPI - - trait PolyTypeAPI { - def paramNames(implicit ctx: Context): List[String] - def paramTypes(implicit ctx: Context): List[TypeBounds] - def resultTpe(implicit ctx: Context): Type - } - implicit def PolyTypeDeco(tpt: PolyType): PolyTypeAPI - - trait TypeLambdaAPI { - def paramNames(implicit ctx: Context): List[String] - def paramTypes(implicit ctx: Context): List[TypeBounds] - def resultTpe(implicit ctx: Context): Type - } - implicit def TypeLambdaDeco(tpt: TypeLambda): TypeLambdaAPI - - val IsType: IsTypeExtractor - abstract class IsTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] - } - - val Type: TypeModule - abstract class TypeModule { - - val ConstantType: ConstantTypeExtractor - abstract class ConstantTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Constant] - } - - val SymRef: SymRefExtractor - abstract class SymRefExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Definition, TypeOrBounds /* Type | NoPrefix */)] - } - - val TermRef: TermRefExtractor - abstract class TermRefExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] - } - - val TypeRef: TypeRefExtractor - abstract class TypeRefExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] - } - - val SuperType: SuperTypeExtractor - abstract class SuperTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] - } - - val Refinement: RefinementExtractor - abstract class RefinementExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, String, TypeOrBounds /* Type | TypeBounds */)] - } - - val AppliedType: AppliedTypeExtractor - abstract class AppliedTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, List[TypeOrBounds /* Type | TypeBounds */])] - } - - val AnnotatedType: AnnotatedTypeExtractor - abstract class AnnotatedTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Term)] - } - - val AndType: AndTypeExtractor - abstract class AndTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] - } - - val OrType: OrTypeExtractor - abstract class OrTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] - } - - val ByNameType: ByNameTypeExtractor - abstract class ByNameTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] - } - - val ParamRef: ParamRefExtractor - abstract class ParamRefExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(LambdaType[TypeOrBounds], Int)] - } - - val ThisType: ThisTypeExtractor - abstract class ThisTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] - } - - val RecursiveThis: RecursiveThisExtractor - abstract class RecursiveThisExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[RecursiveType] - } - - val RecursiveType: RecursiveTypeExtractor - abstract class RecursiveTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] - } - - val MethodType: MethodTypeExtractor - abstract class MethodTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[Type], Type)] - } - - val PolyType: PolyTypeExtractor - abstract class PolyTypeExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] - } - - val TypeLambda: TypeLambdaExtractor - abstract class TypeLambdaExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] - } - - } - - // ----- TypeBounds ----------------------------------------------- - - type TypeBounds <: TypeOrBounds - - val IsTypeBounds: IsTypeBoundsExtractor - abstract class IsTypeBoundsExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[TypeBounds] - } - - val TypeBounds: TypeBoundsExtractor - abstract class TypeBoundsExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] - } - - trait TypeBoundsAPI { - def low(implicit ctx: Context): Type - def hi(implicit ctx: Context): Type - } - implicit def TypeBoundsDeco(bounds: TypeBounds): TypeBoundsAPI - - // ----- NoPrefix ------------------------------------------------- - - type NoPrefix <: TypeOrBounds - - val NoPrefix: NoPrefixExtractor - abstract class NoPrefixExtractor { - def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Boolean - } - - // ===== Constants ================================================ - - type Constant - trait ConstantAPI { - def show(implicit ctx: Context, s: Show[tasty.type]): String - def value: Any - } - implicit def ConstantDeco(const: Constant): ConstantAPI - - val Constant: ConstantModule - abstract class ConstantModule { - - val Unit: UnitExtractor - abstract class UnitExtractor { - def unapply(constant: Constant): Boolean - } - - val Null: NullExtractor - abstract class NullExtractor { - def unapply(constant: Constant): Boolean - } - - val Boolean: BooleanExtractor - abstract class BooleanExtractor { - def unapply(constant: Constant): Option[Boolean] - } - - val Byte: ByteExtractor - abstract class ByteExtractor { - def unapply(constant: Constant): Option[Byte] - } - - val Short: ShortExtractor - abstract class ShortExtractor { - def unapply(constant: Constant): Option[Short] - } - - val Char: CharExtractor - abstract class CharExtractor { - def unapply(constant: Constant): Option[Char] - } - - val Int: IntExtractor - abstract class IntExtractor { - def unapply(constant: Constant): Option[Int] - } - - val Long: LongExtractor - abstract class LongExtractor { - def unapply(constant: Constant): Option[Long] - } - - val Float: FloatExtractor - abstract class FloatExtractor { - def unapply(constant: Constant): Option[Float] - } - - val Double: DoubleExtractor - abstract class DoubleExtractor { - def unapply(constant: Constant): Option[Double] - } - - val String: StringExtractor - abstract class StringExtractor { - def unapply(constant: Constant): Option[String] - } - - val ClassTag: ClassTagExtractor - abstract class ClassTagExtractor { - def unapply(constant: Constant): Option[Type] - } - - /** Extractor for scala.Symbol literals */ - val Symbol: SymbolExtractor - /** Extractor for scala.Symbol literals */ - abstract class SymbolExtractor { - def unapply(constant: Constant): Option[scala.Symbol] - } - } - - // ===== Signature ================================================ - - type Signature - - val Signature: SignatureExtractor - abstract class SignatureExtractor { - def unapply(sig: Signature)(implicit ctx: Context): Option[(List[String], String)] - } - - trait SignatureAPI { - def paramSigs: List[String] - def resultSig: String - } - implicit def SignatureDeco(sig: Signature): SignatureAPI - - // ===== Positions ================================================ - - type Position - - trait PositionAPI { - def start: Int - def end: Int - - def sourceFile: java.nio.file.Path - - def startLine: Int - def startColumn: Int - def endLine: Int - def endColumn: Int - } - implicit def PositionDeco(pos: Position): PositionAPI - - trait Positioned { - def pos(implicit ctx: Context): Position - } - -} +abstract class Tasty extends TastyCore with CaseDefOps with ConstantOps with ContextOps with IdOps with ImportSelectorOps with QuotedOps with PatternOps with PositionOps with Printers with SignatureOps with StandardDefinitions with TreeOps with TypeOrBoundsTreeOps with TypeOrBoundsOps diff --git a/library/src/scala/tasty/reflect/CaseDefOps.scala b/library/src/scala/tasty/reflect/CaseDefOps.scala new file mode 100644 index 000000000000..29be9898d3ce --- /dev/null +++ b/library/src/scala/tasty/reflect/CaseDefOps.scala @@ -0,0 +1,19 @@ +package scala.tasty +package reflect + +/** Tasty reflect case definition */ +trait CaseDefOps extends TastyCore { + + trait CaseDefAPI { + def pattern(implicit ctx: Context): Pattern + def guard(implicit ctx: Context): Option[Term] + def rhs(implicit ctx: Context): Term + } + implicit def CaseDefDeco(caseDef: CaseDef): CaseDefAPI + + val CaseDef: CaseDefExtractor + abstract class CaseDefExtractor { + def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] + } + +} diff --git a/library/src/scala/tasty/reflect/ConstantOps.scala b/library/src/scala/tasty/reflect/ConstantOps.scala new file mode 100644 index 000000000000..8bb58cf0c976 --- /dev/null +++ b/library/src/scala/tasty/reflect/ConstantOps.scala @@ -0,0 +1,81 @@ +package scala.tasty +package reflect + +trait ConstantOps extends TastyCore { + + trait ConstantAPI { + def value: Any + } + implicit def ConstantDeco(const: Constant): ConstantAPI + + val Constant: ConstantModule + abstract class ConstantModule { + + val Unit: UnitExtractor + abstract class UnitExtractor { + def unapply(constant: Constant): Boolean + } + + val Null: NullExtractor + abstract class NullExtractor { + def unapply(constant: Constant): Boolean + } + + val Boolean: BooleanExtractor + abstract class BooleanExtractor { + def unapply(constant: Constant): Option[Boolean] + } + + val Byte: ByteExtractor + abstract class ByteExtractor { + def unapply(constant: Constant): Option[Byte] + } + + val Short: ShortExtractor + abstract class ShortExtractor { + def unapply(constant: Constant): Option[Short] + } + + val Char: CharExtractor + abstract class CharExtractor { + def unapply(constant: Constant): Option[Char] + } + + val Int: IntExtractor + abstract class IntExtractor { + def unapply(constant: Constant): Option[Int] + } + + val Long: LongExtractor + abstract class LongExtractor { + def unapply(constant: Constant): Option[Long] + } + + val Float: FloatExtractor + abstract class FloatExtractor { + def unapply(constant: Constant): Option[Float] + } + + val Double: DoubleExtractor + abstract class DoubleExtractor { + def unapply(constant: Constant): Option[Double] + } + + val String: StringExtractor + abstract class StringExtractor { + def unapply(constant: Constant): Option[String] + } + + val ClassTag: ClassTagExtractor + abstract class ClassTagExtractor { + def unapply(constant: Constant): Option[Type] + } + + /** Extractor for scala.Symbol literals */ + val Symbol: SymbolExtractor + /** Extractor for scala.Symbol literals */ + abstract class SymbolExtractor { + def unapply(constant: Constant): Option[scala.Symbol] + } + } +} diff --git a/library/src/scala/tasty/reflect/ContextOps.scala b/library/src/scala/tasty/reflect/ContextOps.scala new file mode 100644 index 000000000000..255a2473a37e --- /dev/null +++ b/library/src/scala/tasty/reflect/ContextOps.scala @@ -0,0 +1,19 @@ +package scala.tasty +package reflect + +trait ContextOps extends TastyCore { + + trait ContextAPI { + def owner: Definition + + /** Returns the source file being compiled. The path is relative to the current working directory. */ + def source: java.nio.file.Path + } + implicit def ContextDeco(ctx: Context): ContextAPI + + implicit def rootContext: Context + + /** Root position of this tasty context. For macros it corresponds to the expansion site. */ + def rootPosition: Position + +} diff --git a/library/src/scala/tasty/FlagSet.scala b/library/src/scala/tasty/reflect/FlagSet.scala similarity index 98% rename from library/src/scala/tasty/FlagSet.scala rename to library/src/scala/tasty/reflect/FlagSet.scala index 0acfffa3bfc6..4ef2f838bc44 100644 --- a/library/src/scala/tasty/FlagSet.scala +++ b/library/src/scala/tasty/reflect/FlagSet.scala @@ -1,4 +1,4 @@ -package scala.tasty +package scala.tasty.reflect trait FlagSet { def isProtected: Boolean diff --git a/library/src/scala/tasty/reflect/IdOps.scala b/library/src/scala/tasty/reflect/IdOps.scala new file mode 100644 index 000000000000..a42945cba95b --- /dev/null +++ b/library/src/scala/tasty/reflect/IdOps.scala @@ -0,0 +1,17 @@ +package scala.tasty +package reflect + +trait IdOps extends TastyCore { + + trait IdAPI { + def pos(implicit ctx: Context): Position + def name(implicit ctx: Context): String + } + implicit def IdDeco(id: Id): IdAPI + + val Id: IdExtractor + abstract class IdExtractor { + def unapply(id: Id): Option[String] + } + +} diff --git a/library/src/scala/tasty/reflect/ImportSelectorOps.scala b/library/src/scala/tasty/reflect/ImportSelectorOps.scala new file mode 100644 index 000000000000..7ecde2ace1bb --- /dev/null +++ b/library/src/scala/tasty/reflect/ImportSelectorOps.scala @@ -0,0 +1,21 @@ +package scala.tasty +package reflect + +trait ImportSelectorOps extends TastyCore { + + val SimpleSelector: SimpleSelectorExtractor + abstract class SimpleSelectorExtractor { + def unapply(importSelector: ImportSelector)(implicit ctx: Context): Option[Id] + } + + val RenameSelector: RenameSelectorExtractor + abstract class RenameSelectorExtractor { + def unapply(importSelector: ImportSelector)(implicit ctx: Context): Option[(Id, Id)] + } + + val OmitSelector: OmitSelectorExtractor + abstract class OmitSelectorExtractor { + def unapply(importSelector: ImportSelector)(implicit ctx: Context): Option[Id] + } + +} diff --git a/library/src/scala/tasty/reflect/PatternOps.scala b/library/src/scala/tasty/reflect/PatternOps.scala new file mode 100644 index 000000000000..3881b34c315e --- /dev/null +++ b/library/src/scala/tasty/reflect/PatternOps.scala @@ -0,0 +1,41 @@ +package scala.tasty +package reflect + +trait PatternOps extends TastyCore { + + trait PatternAPI { + def tpe(implicit ctx: Context): Type + def pos(implicit ctx: Context): Position + } + implicit def PatternDeco(pattern: Pattern): PatternAPI + + val Pattern: PatternModule + abstract class PatternModule { + + val Value: ValueExtractor + abstract class ValueExtractor { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Term] + } + + val Bind: BindExtractor + abstract class BindExtractor { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[(String, Pattern)] + } + + val Unapply: UnapplyExtractor + abstract class UnapplyExtractor { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[(Term, List[Term], List[Pattern])] + } + + val Alternative: AlternativeExtractor + abstract class AlternativeExtractor { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[List[Pattern]] + } + + val TypeTest: TypeTestExtractor + abstract class TypeTestExtractor { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[TypeTree] + } + } + +} diff --git a/library/src/scala/tasty/reflect/PositionOps.scala b/library/src/scala/tasty/reflect/PositionOps.scala new file mode 100644 index 000000000000..2630b1188073 --- /dev/null +++ b/library/src/scala/tasty/reflect/PositionOps.scala @@ -0,0 +1,18 @@ +package scala.tasty.reflect + +trait PositionOps extends TastyCore { + + trait PositionAPI { + def start: Int + def end: Int + + def sourceFile: java.nio.file.Path + + def startLine: Int + def startColumn: Int + def endLine: Int + def endColumn: Int + } + implicit def PositionDeco(pos: Position): PositionAPI + +} diff --git a/library/src/scala/tasty/reflect/Printers.scala b/library/src/scala/tasty/reflect/Printers.scala new file mode 100644 index 000000000000..cdbf5c31d278 --- /dev/null +++ b/library/src/scala/tasty/reflect/Printers.scala @@ -0,0 +1,42 @@ +package scala.tasty +package reflect + +import scala.tasty.util.Show + +trait Printers { tasty: Tasty => + // TASTy 🎂 needed to for the path dependency `tasty.type` to make sure the + // implicit printers of different instances of Tasty are not used. + + /** Printer that prints the tree as extractors (enabled by default) */ + implicit def showExtractors: Show[tasty.type] + + /** Printer that prints the tree as source code */ + def showSourceCode: Show[tasty.type] + + /** Adds `show` as an extension method of a `Tree` */ + implicit def TreeShowDeco(tree: Tree): ShowAPI + + /** Adds `show` as an extension method of a `TypeOrBoundsTree` */ + implicit def TypeOrBoundsTreeShowDeco(tpt: TypeOrBoundsTree): ShowAPI + + /** Adds `show` as an extension method of a `TypeOrBounds` */ + implicit def TypeOrBoundsShowDeco(tpt: TypeOrBounds): ShowAPI + + /** Adds `show` as an extension method of a `CaseDef` */ + implicit def CaseDefShowDeco(caseDef: CaseDef): ShowAPI + + /** Adds `show` as an extension method of a `Pattern` */ + implicit def PatternShowDeco(pattern: Pattern): ShowAPI + + /** Adds `show` as an extension method of a `Constant` */ + implicit def ConstantShowDeco(const: Constant): ShowAPI + + /** Define `show` as method */ + trait ShowAPI { + /** Shows the string representation based on an implicit instance of `Show[tasty.type]` + * See: `showExtractors` and `showSourceCode` + */ + def show(implicit ctx: Context, s: Show[tasty.type]): String + } + +} diff --git a/library/src/scala/tasty/reflect/QuotedOps.scala b/library/src/scala/tasty/reflect/QuotedOps.scala new file mode 100644 index 000000000000..e5d5214b3082 --- /dev/null +++ b/library/src/scala/tasty/reflect/QuotedOps.scala @@ -0,0 +1,21 @@ +package scala.tasty.reflect + +/** Extension methods on scala.quoted.{Expr|Type} to convert to scala.tasty.Tasty objects */ +trait QuotedOps extends TastyCore { + + trait QuotedExprAPI { + def toTasty(implicit ctx: Context): Term + } + implicit def QuotedExprDeco[T](expr: quoted.Expr[T]): QuotedExprAPI + + trait QuotedTypeAPI { + def toTasty(implicit ctx: Context): TypeTree + } + implicit def QuotedTypeDeco[T](tpe: quoted.Type[T]): QuotedTypeAPI + + trait TermToQuotedAPI { + def toExpr[T: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[T] + } + implicit def TermToQuoteDeco(term: Term): TermToQuotedAPI + +} diff --git a/library/src/scala/tasty/reflect/SignatureOps.scala b/library/src/scala/tasty/reflect/SignatureOps.scala new file mode 100644 index 000000000000..34884cccc8df --- /dev/null +++ b/library/src/scala/tasty/reflect/SignatureOps.scala @@ -0,0 +1,16 @@ +package scala.tasty.reflect + +trait SignatureOps extends TastyCore { + + val Signature: SignatureExtractor + abstract class SignatureExtractor { + def unapply(sig: Signature)(implicit ctx: Context): Option[(List[String], String)] + } + + trait SignatureAPI { + def paramSigs: List[String] + def resultSig: String + } + implicit def SignatureDeco(sig: Signature): SignatureAPI + +} diff --git a/library/src/scala/tasty/reflect/StandardDefinitions.scala b/library/src/scala/tasty/reflect/StandardDefinitions.scala index 5c45a34a74ba..3254b634ad96 100644 --- a/library/src/scala/tasty/reflect/StandardDefinitions.scala +++ b/library/src/scala/tasty/reflect/StandardDefinitions.scala @@ -1,8 +1,7 @@ package scala.tasty package reflect -trait StandardDefinitions { - self: Tasty => +trait StandardDefinitions extends TastyCore { /** A value containing all standard definitions in [[DefinitionsApi]] * @group Definitions diff --git a/library/src/scala/tasty/reflect/TastyCore.scala b/library/src/scala/tasty/reflect/TastyCore.scala new file mode 100644 index 000000000000..7cecaf235e77 --- /dev/null +++ b/library/src/scala/tasty/reflect/TastyCore.scala @@ -0,0 +1,161 @@ +package scala.tasty.reflect + +/** Tasty reflect abstract types + * + * ```none + * + * +- Tree -+- PackageClause + * +- Import + * +- Statement -+- Definition --+- ClassDef + * | +- TypeDef + * | +- DefDef + * | +- ValDef + * | +- PackageDef + * | + * +- Term --------+- Ident + * / +- Select + * / +- Literal + * / +- This + * / +- New + * / +- NamedArg + * / +- Apply + * / +- TypeApply + * / +- Super + * / +- Typed + * / +- Assign + * / +- Block + * +- Parent ----+ +- Lambda + * \ +- If + * \ +- Match + * \ +- Try + * \ +- Return + * \ +- Repeated + * \ +- Inlined + * \ +- SelectOuter + * \ +- While + * \ +- DoWhile + * \ + * \ + * +- TypeTree ----+- Synthetic + * | +- TypeIdent + * | +- TermSelect + * | +- TypeSelect + * | +- Singleton + * +- TypeOrBoundsTree ---+ +- Refined + * | +- Applied + * | +- Annotated + * | +- And + * | +- Or + * | +- ByName + * | +- TypeLambdaTree + * | +- Bind + * | + * +- TypeBoundsTree + * +- SyntheticBounds + * + * +- CaseDef + * + * +- Pattern --+- Value + * +- Bind + * +- Unapply + * +- Alternative + * +- TypeTest + * + * + * +- NoPrefix + * +- TypeOrBounds -+- TypeBounds + * | + * +- Type -------+- ConstantType + * +- SymRef + * +- TermRef + * +- TypeRef + * +- SuperType + * +- Refinement + * +- AppliedType + * +- AnnotatedType + * +- AndType + * +- OrType + * +- ByNameType + * +- ParamRef + * +- ThisType + * +- RecursiveThis + * +- RecursiveType + * +- LambdaType[ParamInfo <: TypeOrBounds] -+- MethodType + * +- PolyType + * +- TypeLambda + * + * +- ImportSelector -+- SimpleSelector + * +- RenameSelector + * +- OmitSelector + * + * +- Id + * + * +- Signature + * + * +- Position + * + * +- Constant + * + * ``` + */ +trait TastyCore { + + /** Compilation context */ + type Context + + // TODO: When bootstrapped, remove and use `Term | TypeTree` type directly in other files + /** Workaround missing `|` types in Scala 2 to represent `Term | TypeTree` */ + type Parent /* Term | TypeTree */ + + /** Tree representing executable code written in the source */ + type Tree + type PackageClause <: Tree + type Statement <: Tree + type Import <: Statement + type Definition <: Statement + type ClassDef <: Definition + type TypeDef <: Definition + type DefDef <: Definition + type ValDef <: Definition + type PackageDef <: Definition + type Term <: Statement with Parent // TODO: When bootstrapped, remove `Parent` + + /** Branch of a pattern match or catch clause */ + type CaseDef + + /** Pattern tree of the pattern part of a CaseDef */ + type Pattern + + /** Tree representing a type written in the source */ + type TypeOrBoundsTree + type TypeTree <: TypeOrBoundsTree with Parent // TODO: When bootstrapped, remove `Parent` + type TypeBoundsTree <: TypeOrBoundsTree + + type TypeOrBounds + type NoPrefix <: TypeOrBounds + type TypeBounds <: TypeOrBounds + type Type <: TypeOrBounds + type RecursiveType <: Type + // TODO can we add the bound back without an cake? + // TODO is LambdaType really needed? ParamRefExtractor could be split into more precise extractors + type LambdaType[ParamInfo /*<: TypeOrBounds*/] <: Type + type MethodType <: LambdaType[Type] + type PolyType <: LambdaType[TypeBounds] + type TypeLambda <: LambdaType[TypeBounds] + + + type ImportSelector + + /** Untyped identifier */ + type Id + + /** JVM signature of a method */ + type Signature + + /** Source position */ + type Position + + /** Constant value represented as the constant itself */ + type Constant + +} diff --git a/library/src/scala/tasty/reflect/TreeOps.scala b/library/src/scala/tasty/reflect/TreeOps.scala new file mode 100644 index 000000000000..28668323cfe5 --- /dev/null +++ b/library/src/scala/tasty/reflect/TreeOps.scala @@ -0,0 +1,314 @@ +package scala.tasty +package reflect + +trait TreeOps extends TastyCore { + + trait TreeAPI { + def pos(implicit ctx: Context): Position + } + implicit def TreeDeco(tree: Tree): TreeAPI + + val IsPackageClause: IsPackageClauseExtractor + abstract class IsPackageClauseExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[PackageClause] + } + + val PackageClause: PackageClauseExtractor + abstract class PackageClauseExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Tree])] + } + + trait PackageClauseAPI { + def definition(implicit ctx: Context): Definition + } + implicit def PackageClauseDeco(pack: PackageClause): PackageClauseAPI + + // ----- Statements ----------------------------------------------- + + val Import: ImportExtractor + abstract class ImportExtractor { + def unapply(imp: Tree)(implicit ctx: Context): Option[(Term, List[ImportSelector])] + } + + trait ImportAPI { + def expr(implicit ctx: Context): Term + def selector(implicit ctx: Context): List[ImportSelector] + } + implicit def ImportDeco(imp: Import): ImportAPI + + // ----- Definitions ---------------------------------------------- + + val IsDefinition: IsDefinitionExtractor + abstract class IsDefinitionExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[Definition] + } + + trait DefinitionAPI { + def name(implicit ctx: Context): String + def flags(implicit ctx: Context): FlagSet + def privateWithin(implicit ctx: Context): Option[Type] + def protectedWithin(implicit ctx: Context): Option[Type] + def annots(implicit ctx: Context): List[Term] + def owner(implicit ctx: Context): Definition + def localContext(implicit ctx: Context): Context + } + implicit def DefinitionDeco(definition: Definition): DefinitionAPI + + // ClassDef + + val IsClassDef: IsClassDefExtractor + abstract class IsClassDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[ClassDef] + } + + val ClassDef: ClassDefExtractor + abstract class ClassDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, DefDef, List[Parent], Option[ValDef], List[Statement])] + } + + trait ClassDefAPI { + def constructor(implicit ctx: Context): DefDef + def parents(implicit ctx: Context): List[Parent] + def self(implicit ctx: Context): Option[ValDef] + def body(implicit ctx: Context): List[Statement] + } + implicit def ClassDefDeco(cdef: ClassDef): ClassDefAPI + + // DefDef + + val IsDefDef: IsDefDefExtractor + abstract class IsDefDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[DefDef] + } + + val DefDef: DefDefExtractor + abstract class DefDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] + } + + trait DefDefAPI { + def typeParams(implicit ctx: Context): List[TypeDef] + def paramss(implicit ctx: Context): List[List[ValDef]] + def returnTpt(implicit ctx: Context): TypeTree + def rhs(implicit ctx: Context): Option[Term] + } + implicit def DefDefDeco(ddef: DefDef): DefDefAPI + + // ValDef + + val IsValDef: IsValDefExtractor + abstract class IsValDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[ValDef] + } + + val ValDef: ValDefExtractor + abstract class ValDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] + } + + trait ValDefAPI { + def tpt(implicit ctx: Context): TypeTree + def rhs(implicit ctx: Context): Option[Term] + } + implicit def ValDefDeco(vdef: ValDef): ValDefAPI + + // TypeDef + + val IsTypeDef: IsTypeDefExtractor + abstract class IsTypeDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[TypeDef] + } + + val TypeDef: TypeDefExtractor + abstract class TypeDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree /* TypeTree | TypeBoundsTree */)] + } + + trait TypeDefAPI { + def rhs(implicit ctx: Context): TypeOrBoundsTree + } + implicit def TypeDefDeco(tdef: TypeDef): TypeDefAPI + + // PackageDef + + val IsPackageDef: IsPackageDefExtractor + abstract class IsPackageDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[PackageDef] + } + + trait PackageDefAPI { + def owner(implicit ctx: Context): PackageDef + def members(implicit ctx: Context): List[Statement] + } + implicit def PackageDefDeco(pdef: PackageDef): PackageDefAPI + + val PackageDef: PackageDefExtractor + abstract class PackageDefExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, PackageDef)] + } + + // ----- Terms ---------------------------------------------------- + + trait TermAPI { + def tpe(implicit ctx: Context): Type + def pos(implicit ctx: Context): Position + } + implicit def TermDeco(term: Term): TermAPI + + val IsTerm: IsTermExtractor + abstract class IsTermExtractor { + /** Matches any term */ + def unapply(tree: Tree)(implicit ctx: Context): Option[Term] + /** Matches any term */ + def unapply(parent: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[Term] + } + + /** Scala term. Any tree that can go in expression position. */ + val Term: TermModule + abstract class TermModule { + + /** Scala term identifier */ + val Ident: IdentExtractor + abstract class IdentExtractor { + /** Matches a term identifier and returns its name */ + def unapply(tree: Tree)(implicit ctx: Context): Option[String] + } + + /** Scala term selection */ + val Select: SelectExtractor + abstract class SelectExtractor { + /** Matches `.: ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, String, Option[Signature])] + } + + /** Scala literal constant */ + val Literal: LiteralExtractor + abstract class LiteralExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[Constant] + } + + /** Scala `this` or `this[id]` */ + val This: ThisExtractor + abstract class ThisExtractor { + /** Matches new `this[` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[Option[Id]] + } + + /** Scala `new` */ + val New: NewExtractor + abstract class NewExtractor { + /** Matches new `new ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[TypeTree] + } + + /** Scala named argument `x = y` in argument position */ + val NamedArg: NamedArgExtractor + abstract class NamedArgExtractor { + /** Matches ` = ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, Term)] + } + + /** Scala parameter application */ + val Apply: ApplyExtractor + abstract class ApplyExtractor { + /** Matches function application `()` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Term])] + } + + /** Scala type parameter application */ + val TypeApply: TypeApplyExtractor + abstract class TypeApplyExtractor { + /** Matches function type application `[]` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[TypeTree])] + } + + /** Scala `x.super` or `x.super[id]` */ + val Super: SuperExtractor + abstract class SuperExtractor { + /** Matches new `.super[` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Option[Id])] + } + + /** Scala ascription `x: T` */ + val Typed: TypedExtractor + abstract class TypedExtractor { + /** Matches `: ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, TypeTree)] + } + + /** Scala assign `x = y` */ + val Assign: AssignExtractor + abstract class AssignExtractor { + /** Matches ` = ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] + } + + /** Scala code block `{ stat0; ...; statN; expr }` term */ + val Block: BlockExtractor + abstract class BlockExtractor { + /** Matches `{ ; }` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(List[Statement], Term)] + } + + val Lambda: LambdaExtractor + abstract class LambdaExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Option[TypeTree])] + } + + /** Scala `if`/`else` term */ + val If: IfExtractor + abstract class IfExtractor { + /** Matches `if () else ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term, Term)] + } + + /** Scala `match` term */ + val Match: MatchExtractor + abstract class MatchExtractor { + /** Matches ` match { }` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[CaseDef])] + } + + /** Scala `try`/`catch`/`finally` term */ + val Try: TryExtractor + abstract class TryExtractor { + /** Matches `try catch { } finally ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[CaseDef], Option[Term])] + } + + /** Scala local `return` */ + val Return: ReturnExtractor + abstract class ReturnExtractor { + /** Matches `return ` */ + def unapply(tree: Tree)(implicit ctx: Context): Option[Term] + } + + val Repeated: RepeatedExtractor + abstract class RepeatedExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[List[Term]] + } + + val Inlined: InlinedExtractor + abstract class InlinedExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(Option[Term], List[Definition], Term)] + } + + val SelectOuter: SelectOuterExtractor + abstract class SelectOuterExtractor { + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Int, Type)] + } + + val While: WhileExtractor + abstract class WhileExtractor { + /** Extractor for while loops. Matches `while () ` and returns (, ) */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] + } + + val DoWhile: DoWhileExtractor + abstract class DoWhileExtractor { + /** Extractor for do while loops. Matches `do while ()` and returns (, ) */ + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] + } + } + +} diff --git a/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala b/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala new file mode 100644 index 000000000000..166a6210a47b --- /dev/null +++ b/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala @@ -0,0 +1,162 @@ +package scala.tasty +package reflect + +trait TypeOrBoundsOps extends TastyCore { + + // ----- Types ---------------------------------------------------- + + trait TypeAPI { + def =:=(other: Type)(implicit ctx: Context): Boolean + def <:<(other: Type)(implicit ctx: Context): Boolean + } + implicit def TypeDeco(tpe: Type): TypeAPI + + trait MethodTypeAPI { + def isImplicit: Boolean + def isErased: Boolean + def paramNames(implicit ctx: Context): List[String] + def paramTypes(implicit ctx: Context): List[Type] + def resultTpe(implicit ctx: Context): Type + } + implicit def MethodTypeDeco(tpt: MethodType): MethodTypeAPI + + trait PolyTypeAPI { + def paramNames(implicit ctx: Context): List[String] + def paramTypes(implicit ctx: Context): List[TypeBounds] + def resultTpe(implicit ctx: Context): Type + } + implicit def PolyTypeDeco(tpt: PolyType): PolyTypeAPI + + trait TypeLambdaAPI { + def paramNames(implicit ctx: Context): List[String] + def paramTypes(implicit ctx: Context): List[TypeBounds] + def resultTpe(implicit ctx: Context): Type + } + implicit def TypeLambdaDeco(tpt: TypeLambda): TypeLambdaAPI + + val IsType: IsTypeExtractor + abstract class IsTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] + } + + val Type: TypeModule + abstract class TypeModule { + + val ConstantType: ConstantTypeExtractor + abstract class ConstantTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Constant] + } + + val SymRef: SymRefExtractor + abstract class SymRefExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Definition, TypeOrBounds /* Type | NoPrefix */)] + } + + val TermRef: TermRefExtractor + abstract class TermRefExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] + } + + val TypeRef: TypeRefExtractor + abstract class TypeRefExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(String, TypeOrBounds /* Type | NoPrefix */)] + } + + val SuperType: SuperTypeExtractor + abstract class SuperTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] + } + + val Refinement: RefinementExtractor + abstract class RefinementExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, String, TypeOrBounds /* Type | TypeBounds */)] + } + + val AppliedType: AppliedTypeExtractor + abstract class AppliedTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, List[TypeOrBounds /* Type | TypeBounds */])] + } + + val AnnotatedType: AnnotatedTypeExtractor + abstract class AnnotatedTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Term)] + } + + val AndType: AndTypeExtractor + abstract class AndTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] + } + + val OrType: OrTypeExtractor + abstract class OrTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] + } + + val ByNameType: ByNameTypeExtractor + abstract class ByNameTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] + } + + val ParamRef: ParamRefExtractor + abstract class ParamRefExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(LambdaType[TypeOrBounds], Int)] + } + + val ThisType: ThisTypeExtractor + abstract class ThisTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] + } + + val RecursiveThis: RecursiveThisExtractor + abstract class RecursiveThisExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[RecursiveType] + } + + val RecursiveType: RecursiveTypeExtractor + abstract class RecursiveTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type] + } + + val MethodType: MethodTypeExtractor + abstract class MethodTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[Type], Type)] + } + + val PolyType: PolyTypeExtractor + abstract class PolyTypeExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] + } + + val TypeLambda: TypeLambdaExtractor + abstract class TypeLambdaExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] + } + + } + + // ----- TypeBounds ----------------------------------------------- + + val IsTypeBounds: IsTypeBoundsExtractor + abstract class IsTypeBoundsExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[TypeBounds] + } + + val TypeBounds: TypeBoundsExtractor + abstract class TypeBoundsExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)] + } + + trait TypeBoundsAPI { + def low(implicit ctx: Context): Type + def hi(implicit ctx: Context): Type + } + implicit def TypeBoundsDeco(bounds: TypeBounds): TypeBoundsAPI + + // ----- NoPrefix ------------------------------------------------- + + val NoPrefix: NoPrefixExtractor + abstract class NoPrefixExtractor { + def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Boolean + } + +} diff --git a/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala b/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala new file mode 100644 index 000000000000..b23aa7623e77 --- /dev/null +++ b/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala @@ -0,0 +1,122 @@ +package scala.tasty +package reflect + +trait TypeOrBoundsTreeOps extends TastyCore { + + trait TypeOrBoundsTreeAPI { + def tpe(implicit ctx: Context): TypeOrBounds + } + implicit def TypeOrBoundsTreeDeco(tpt: TypeOrBoundsTree): TypeOrBoundsTreeAPI + + // ----- TypeTrees ------------------------------------------------ + + trait TypeTreeAPI { + def pos(implicit ctx: Context): Position + def tpe(implicit ctx: Context): Type + } + implicit def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI + + val IsTypeTree: IsTypeTreeExtractor + abstract class IsTypeTreeExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] + def unapply(parent: Parent)(implicit ctx: Context, dummy: DummyImplicit): Option[TypeTree] + } + + val TypeTree: TypeTreeModule + abstract class TypeTreeModule { + + /** TypeTree containing an inferred type */ + val Synthetic: SyntheticExtractor + abstract class SyntheticExtractor { + /** Matches a TypeTree containing an inferred type */ + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Boolean + } + + val TypeIdent: TypeIdentExtractor + abstract class TypeIdentExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[String] + } + + val TermSelect: TermSelectExtractor + abstract class TermSelectExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(Term, String)] + } + + val TypeSelect: TypeSelectExtractor + abstract class TypeSelectExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, String)] + } + + val Singleton: SingletonExtractor + abstract class SingletonExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[Term] + } + + val Refined: RefinedExtractor + abstract class RefinedExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, List[Definition])] + } + + val Applied: AppliedExtractor + abstract class AppliedExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])] + } + + val Annotated: AnnotatedExtractor + abstract class AnnotatedExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, Term)] + } + + val And: AndExtractor + abstract class AndExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] + } + + val Or: OrExtractor + abstract class OrExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] + } + + val ByName: ByNameExtractor + abstract class ByNameExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] + } + + val TypeLambdaTree: TypeLambdaTreeExtractor + abstract class TypeLambdaTreeExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(List[TypeDef], TypeOrBoundsTree)] + } + + val Bind: BindExtractor + abstract class BindExtractor{ + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(String, TypeBoundsTree)] + } + } + + // ----- TypeBoundsTrees ------------------------------------------------ + + trait TypeBoundsTreeAPI { + def tpe(implicit ctx: Context): TypeBounds + def low(implicit ctx: Context): TypeTree + def hi(implicit ctx: Context): TypeTree + } + implicit def TypeBoundsTreeDeco(tpt: TypeBoundsTree): TypeBoundsTreeAPI + + val IsTypeBoundsTree: IsTypeBoundsTreeExtractor + abstract class IsTypeBoundsTreeExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBoundsTree] + } + + val TypeBoundsTree: TypeBoundsTreeExtractor + abstract class TypeBoundsTreeExtractor { + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] + } + + /** TypeBoundsTree containing an inferred type bounds */ + val SyntheticBounds: SyntheticBoundsExtractor + abstract class SyntheticBoundsExtractor { + /** Matches a TypeBoundsTree containing inferred type bounds */ + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Boolean + } + +} diff --git a/library/src/scala/tasty/util/ShowExtractors.scala b/library/src/scala/tasty/util/ShowExtractors.scala index 2a55cc7ed8c4..532408a6fc99 100644 --- a/library/src/scala/tasty/util/ShowExtractors.scala +++ b/library/src/scala/tasty/util/ShowExtractors.scala @@ -187,7 +187,7 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty case Type.ByNameType(underlying) => this += "Type.ByNameType(" += underlying += ")" case Type.ParamRef(binder, idx) => - this += "Type.ParamRef(" += binder+= ", " += idx += ")" + this += "Type.ParamRef(" += binder += ", " += idx += ")" case Type.ThisType(tp) => this += "Type.ThisType(" += tp += ")" case Type.SuperType(thistpe, supertpe) =>