diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index f8f373ca6ba5..603e95af29ef 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -975,13 +975,13 @@ object Trees { * so that they selectively retype themselves. Retyping needs a context. */ abstract class TreeCopier { - def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] - def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] + protected def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] + protected def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] - def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) - def finalize(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] = postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) def Ident(tree: Tree)(name: Name): Ident = tree match { diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala index 20b591617420..60b566c9fae8 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala @@ -1,5 +1,6 @@ package dotty.tools.dotc.tastyreflect +import dotty.tools.dotc.ast.tpd trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with CoreImpl with Helpers { @@ -10,6 +11,12 @@ trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with CoreImpl with H } object CaseDef extends CaseDefModule { + def apply(pattern: Pattern, guard: Option[Term], body: Term)(implicit ctx: Context): CaseDef = + tpd.CaseDef(pattern, guard.getOrElse(tpd.EmptyTree), body) + + def copy(original: CaseDef)(pattern: Pattern, guard: Option[Term], body: Term)(implicit ctx: Context): CaseDef = + tpd.cpy.CaseDef(original)(pattern, guard.getOrElse(tpd.EmptyTree), body) + def unapply(x: CaseDef): Some[(Pattern, Option[Term], Term)] = Some(x.pat, optional(x.guard), x.body) } @@ -19,6 +26,12 @@ trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with CoreImpl with H } object TypeCaseDef extends TypeCaseDefModule { + def apply(pattern: TypeTree, body: TypeTree)(implicit ctx: Context): TypeCaseDef = + tpd.CaseDef(pattern, tpd.EmptyTree, body) + + def copy(original: TypeCaseDef)(pattern: TypeTree, body: TypeTree)(implicit ctx: Context): TypeCaseDef = + tpd.cpy.CaseDef(original)(pattern, tpd.EmptyTree, body) + def unapply(x: TypeCaseDef): Some[(TypeTree, TypeTree)] = Some((x.pat, x.body)) } } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/CoreImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/CoreImpl.scala index a21974b5e17d..3b89b42b7b1c 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/CoreImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/CoreImpl.scala @@ -26,8 +26,9 @@ trait CoreImpl extends scala.tasty.reflect.Core { type Term = tpd.Tree val Term: TermCoreModuleImpl trait TermCoreModuleImpl extends TermCoreModule { - type Ident = tpd.Ident - type Select = tpd.Select + type Ref = tpd.RefTree + type Ident = tpd.Ident + type Select = tpd.Select type Literal = tpd.Literal type This = tpd.This type New = tpd.New @@ -56,8 +57,8 @@ trait CoreImpl extends scala.tasty.reflect.Core { type Pattern = tpd.Tree type Value = tpd.Tree type Bind = tpd.Bind - type Unapply = tpd.Tree - type Alternative = tpd.Alternative + type Unapply = tpd.UnApply + type Alternatives = tpd.Alternative type TypeTest = tpd.Typed type TypeOrBoundsTree = tpd.Tree @@ -67,7 +68,7 @@ trait CoreImpl extends scala.tasty.reflect.Core { type Inferred = tpd.TypeTree type Ident = tpd.Ident type Select = tpd.Select - type Project = tpd.Select + type Projection = tpd.Select type Singleton = tpd.SingletonTypeTree type Refined = tpd.RefinedTypeTree type Applied = tpd.AppliedTypeTree @@ -77,8 +78,8 @@ trait CoreImpl extends scala.tasty.reflect.Core { type MatchType = tpd.MatchTypeTree type ByName = tpd.ByNameTypeTree type LambdaTypeTree = tpd.LambdaTypeTree - type Bind = tpd.Bind - type Block = tpd.Block + type TypeBind = tpd.Bind + type TypeBlock = tpd.Block } type TypeBoundsTree = tpd.TypeBoundsTree type WildcardType = tpd.TypeTree diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala index f9f9683c0038..af972be8b896 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala @@ -1,10 +1,36 @@ package dotty.tools.dotc.tastyreflect -import dotty.tools.dotc.ast.{Trees, tpd} +import dotty.tools.dotc.ast.{Trees, tpd, untpd} +import dotty.tools.dotc.core.Contexts import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.StdNames.nme trait PatternOpsImpl extends scala.tasty.reflect.PatternOps with CoreImpl { + def ValueDeco(value: Value): Pattern.ValueAPI = new Pattern.ValueAPI { + def value(implicit ctx: Context): Term = value + } + def BindDeco(bind: Bind): Pattern.BindAPI = new Pattern.BindAPI { + def name(implicit ctx: Context): String = bind.name.toString + def pattern(implicit ctx: Context): Pattern = bind.body + } + def UnapplyDeco(unapply: Unapply): Pattern.UnapplyAPI = new Pattern.UnapplyAPI { + def fun(implicit ctx: Context): Term = unapply.fun + def implicits(implicit ctx: Context): List[Term] = unapply.implicits + def patterns(implicit ctx: Context): List[Pattern] = effectivePatterns(unapply.patterns) + + private def effectivePatterns(patterns: List[Pattern]): List[Pattern] = patterns match { + case patterns0 :+ Trees.SeqLiteral(elems, _) => patterns0 ::: elems + case _ => patterns + } + } + def AlternativeDeco(alternatives: Alternatives): Pattern.AlternativesAPI = new Pattern.AlternativesAPI { + def patterns(implicit ctx: Context): List[Pattern] = alternatives.trees + } + def TypeTestDeco(typeTest: TypeTest): Pattern.TypeTestAPI = new Pattern.TypeTestAPI { + def tpt(implicit ctx: Context): TypeTree = typeTest.tpt + } + // ----- Patterns ------------------------------------------------- def PatternDeco(pattern: Pattern): PatternAPI = new PatternAPI { @@ -14,8 +40,8 @@ trait PatternOpsImpl extends scala.tasty.reflect.PatternOps with CoreImpl { object Pattern extends PatternModule { - object Value extends ValueModule { - def unapply(x: Pattern)(implicit ctx: Context): Option[Term] = x match { + object IsValue extends IsValueModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Value] = pattern match { case lit: tpd.Literal => Some(lit) case ref: tpd.RefTree if ref.isTerm => Some(ref) case ths: tpd.This => Some(ths) @@ -23,36 +49,95 @@ trait PatternOpsImpl extends scala.tasty.reflect.PatternOps with CoreImpl { } } + object Value extends ValueModule { + def apply(term: Term)(implicit ctx: Context): Value = term match { + case lit: tpd.Literal => lit + case ref: tpd.RefTree if ref.isTerm => ref + case ths: tpd.This => ths + } + def copy(original: Value)(term: Term)(implicit ctx: Context): Value = term match { + case lit: tpd.Literal => tpd.cpy.Literal(original)(lit.const) + case ref: tpd.RefTree if ref.isTerm => tpd.cpy.Ref(original.asInstanceOf[tpd.RefTree])(ref.name) + case ths: tpd.This => tpd.cpy.This(original)(ths.qual) + } + def unapply(x: Pattern)(implicit ctx: Context): Option[Term] = IsValue.unapply(x) + } + + object IsBind extends IsBindModule { + def unapply(x: Pattern)(implicit ctx: Context): Option[Bind] = x match { + case x: tpd.Bind if x.name.isTermName => Some(x) + case _ => None + } + } + object Bind extends BindModule { - 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) + + def copy(original: Bind)(name: String, pattern: Pattern)(implicit ctx: Context): Bind = + tpd.cpy.Bind(original)(name.toTermName, pattern) + + def unapply(pattern: Pattern)(implicit ctx: Context): Option[(String, Pattern)] = pattern match { + case IsBind(pattern) => Some((pattern.name.toString, pattern.body)) + case _ => None + } + } + + object IsUnapply extends IsUnapplyModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Unapply] = pattern match { + case pattern @ Trees.UnApply(_, _, _) => Some(pattern) + case Trees.Typed(pattern @ Trees.UnApply(_, _, _), _) => Some(pattern) case _ => None } } object Unapply extends UnapplyModule { + + def copy(original: Unapply)(fun: Term, implicits: List[Term], patterns: List[Pattern])(implicit ctx: Context): Unapply = + tpd.cpy.UnApply(original)(fun, implicits, patterns) + 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 IsUnapply(x) => Some((x.fun, x.implicits, UnapplyDeco(x).patterns)) case _ => None } - private def effectivePatterns(patterns: List[Pattern]): List[Pattern] = patterns match { - case patterns0 :+ Trees.SeqLiteral(elems, _) => patterns0 ::: elems - case _ => patterns + } + + object IsAlternatives extends IsAlternativesModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Alternatives] = pattern match { + case pattern: tpd.Alternative => Some(pattern) + case _ => None } } - object Alternative extends AlternativeModule { + object Alternatives extends AlternativesModule { + def apply(patterns: List[Pattern])(implicit ctx: Context): Alternatives = + tpd.Alternative(patterns) + + def copy(original: Alternatives)(patterns: List[Pattern])(implicit ctx: Context): Alternatives = + tpd.cpy.Alternative(original)(patterns) + def unapply(x: Pattern)(implicit ctx: Context): Option[List[Pattern]] = x match { case x: tpd.Alternative => Some(x.trees) case _ => None } } + object IsTypeTest extends IsTypeTestModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[TypeTest] = pattern match { + case Trees.Typed(_: tpd.UnApply, _) => None + case pattern: tpd.Typed => Some(pattern) + case _ => None + } + } + object TypeTest extends TypeTestModule { + def apply(tpt: TypeTree)(implicit ctx: Context): TypeTest = + tpd.Typed(untpd.Ident(nme.WILDCARD).withType(tpt.tpe), tpt) + + def copy(original: TypeTest)(tpt: TypeTree)(implicit ctx: Context): TypeTest = + tpd.cpy.Typed(original)(untpd.Ident(nme.WILDCARD).withType(tpt.tpe), tpt) + def unapply(x: Pattern)(implicit ctx: Context): Option[TypeTree] = x match { case Trees.Typed(Trees.UnApply(_, _, _), _) => None - case Trees.Typed(_, tpt) => Some(tpt) + case Trees.Typed(expr, tpt) => Some(tpt) case _ => None } } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala index ba5d979a7741..49b221a22947 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala @@ -3,6 +3,7 @@ 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.Symbols.NoSymbol import dotty.tools.dotc.core._ import dotty.tools.dotc.tastyreflect.FromSymbol.{definitionFromSym, packageDefFromSym} @@ -14,11 +15,13 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI { + def pid(implicit ctx: Context): Term.Ref = pack.pid + def stats(implicit ctx: Context): List[Tree] = pack.stats } def ImportDeco(imp: Import): ImportAPI = new ImportAPI { def expr(implicit ctx: Context): Tree = imp.expr - def selector(implicit ctx: Context): List[ImportSelector] = imp.selectors + def selectors(implicit ctx: Context): List[ImportSelector] = imp.selectors } def DefinitionDeco(definition: Definition): DefinitionAPI = new DefinitionAPI { @@ -157,6 +160,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers def RepeatedDeco(x: Term.Repeated): Term.RepeatedAPI = new Term.RepeatedAPI { def elems(implicit ctx: Context): List[Term] = x.elems + def elemtpt(implicit ctx: Context): TypeTree = x.elemtpt } def SelectOuterDeco(x: Term.SelectOuter): Term.SelectOuterAPI = new Term.SelectOuterAPI { @@ -183,21 +187,47 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } object PackageClause extends PackageClauseModule { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Tree])] = tree match { + def apply(pid: Term.Ref, stats: List[Tree])(implicit ctx: Context): PackageClause = + tpd.PackageDef(pid.asInstanceOf[tpd.RefTree], stats) + + def copy(original: PackageClause)(pid: Term.Ref, stats: List[Tree])(implicit ctx: Context): PackageClause = + tpd.cpy.PackageDef(original)(pid, stats) + + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term.Ref, List[Tree])] = tree match { case x: tpd.PackageDef => Some((x.pid, x.stats)) case _ => None } } - // ----- Statements ----------------------------------------------- + object IsImport extends IsImportModule { + override def unapply(tree: Tree)(implicit ctx: Contexts.Context): Option[Import] = tree match { + case tree: tpd.Import => Some(tree) + case _ => None + } + } object Import extends ImportModule { + def apply(expr: Term, selectors: List[ImportSelector])(implicit ctx: Context): Import = + tpd.Import(expr, selectors) + + def copy(original: Import)(expr: Term, selectors: List[ImportSelector])(implicit ctx: Context): Import = + tpd.cpy.Import(original)(expr, selectors) + def unapply(x: Tree)(implicit ctx: Context): Option[(Term, List[ImportSelector])] = x match { case x: tpd.Import => Some((x.expr, x.selectors)) case _ => None } } + object IsStatement extends IsStatementModule { + /** Matches any Statement and returns it */ + def unapply(tree: Tree)(implicit ctx: Context): Option[Statement] = tree match { + case IsDefinition(tree) => Some(tree) + case tree if tree.isTerm => Some(tree) + case _ => None + } + } + // ----- Definitions ---------------------------------------------- object IsDefinition extends IsDefinitionModule { @@ -219,6 +249,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } object ClassDef extends ClassDefModule { + + def copy(original: ClassDef)(name: String, constr: DefDef, parents: List[TermOrTypeTree], selfOpt: Option[ValDef], body: List[Statement])(implicit ctx: Context): ClassDef = { + val Trees.TypeDef(_, originalImpl: tpd.Template) = original + tpd.cpy.TypeDef(original)(name.toTypeName, tpd.cpy.Template(originalImpl)(constr, parents, selfOpt.getOrElse(tpd.EmptyValDef), body)) + } + def unapply(tree: Tree)(implicit ctx: Context): Option[(String, DefDef, List[TermOrTypeTree], 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)) @@ -237,6 +273,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } object DefDef extends DefDefModule { + def apply(symbol: DefSymbol, rhsFn: List[Type] => List[List[Term]] => Option[Term])(implicit ctx: Context): DefDef = + tpd.polyDefDef(symbol, tparams => vparamss => rhsFn(tparams)(vparamss).getOrElse(tpd.EmptyTree)) + + def copy(original: DefDef)(name: String, typeParams: List[TypeDef], paramss: List[List[ValDef]], tpt: TypeTree, rhs: Option[Term])(implicit ctx: Context): DefDef = + tpd.cpy.DefDef(original)(name.toTermName, typeParams, paramss, tpt, rhs.getOrElse(tpd.EmptyTree)) + 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))) @@ -255,6 +297,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } object ValDef extends ValDefModule { + def apply(symbol: ValSymbol, rhs: Option[Term])(implicit ctx: Context): ValDef = + tpd.ValDef(symbol, rhs.getOrElse(tpd.EmptyTree)) + + def copy(original: ValDef)(name: String, tpt: TypeTree, rhs: Option[Term])(implicit ctx: Context): ValDef = + tpd.cpy.ValDef(original)(name.toTermName, tpt, rhs.getOrElse(tpd.EmptyTree)) + 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))) @@ -273,6 +321,9 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } object TypeDef extends TypeDefModule { + def apply(symbol: TypeSymbol)(implicit ctx: Context): TypeDef = tpd.TypeDef(symbol) + def copy(original: TypeDef)(name: String, rhs: TypeOrBoundsTree)(implicit ctx: Context): TypeDef = + tpd.cpy.TypeDef(original)(name.toTypeName, rhs) 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 @@ -325,7 +376,14 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } + object Ref extends RefModule { + def apply(sym: Symbol)(implicit ctx: Context): Ref = tpd.ref(sym).asInstanceOf[tpd.RefTree] + } + object Ident extends IdentModule { + def copy(original: Tree)(name: String)(implicit ctx: Context): Ident = + tpd.cpy.Ident(original)(name.toTermName) + def unapply(x: Term)(implicit ctx: Context): Option[String] = x match { case x: tpd.Ident if x.isTerm => Some(x.name.show) case _ => None @@ -341,6 +399,9 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Select extends SelectModule { + def copy(original: Tree)(qualifier: Term, name: String)(implicit ctx: Context): Select = + tpd.cpy.Select(original)(qualifier, name.toTermName) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, String)] = x match { case x: tpd.Select if x.isTerm => Some((x.qualifier, x.name.toString)) case _ => None @@ -357,6 +418,13 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Literal extends LiteralModule { + + def apply(constant: Constant)(implicit ctx: Context): Literal = + tpd.Literal(constant) + + def copy(original: Tree)(constant: Constant)(implicit ctx: Context): Literal = + tpd.cpy.Literal(original)(constant) + def unapply(x: Term)(implicit ctx: Context): Option[Constant] = x match { case Trees.Literal(const) => Some(const) case _ => None @@ -372,6 +440,13 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object This extends ThisModule { + + def apply(cls: ClassSymbol)(implicit ctx: Context): This = + tpd.This(cls) + + def copy(original: Tree)(qual: Option[Id]): This = + tpd.cpy.This(original)(qual.getOrElse(untpd.EmptyTypeIdent)) + def unapply(x: Term)(implicit ctx: Context): Option[Option[Id]] = x match { case Trees.This(qual) => Some(optional(qual)) case _ => None @@ -385,15 +460,24 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } } + object New extends NewModule { + + def apply(tpt: TypeTree)(implicit ctx: Context): New = tpd.New(tpt) + def copy(original: Tree)(tpt: TypeTree)(implicit ctx: Context): New = + tpd.cpy.New(original)(tpt) - object New extends NewModule { def unapply(x: Term)(implicit ctx: Context): Option[TypeTree] = x match { case x: tpd.New => Some(x.tpt) case _ => None } } + def NamedArgDeco(x: Term.NamedArg): Term.NamedArgAPI = new Term.NamedArgAPI { + def name(implicit ctx: Context): String = x.name.toString + def value(implicit ctx: Context): Term = x.arg + } + object IsNamedArg extends IsNamedArgModule { def unapply(x: Term)(implicit ctx: Context): Option[NamedArg] = x match { case x: tpd.NamedArg if x.name.isInstanceOf[Names.TermName] => Some(x) // TODO: Now, the name should alwas be a term name @@ -401,8 +485,14 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers } } - object NamedArg extends NamedArgModule { + + def apply(name: String, arg: Term)(implicit ctx: Context): NamedArg = + tpd.NamedArg(name.toTermName, arg) + + def copy(tree: NamedArg)(name: String, arg: Term)(implicit ctx: Context): NamedArg = + tpd.cpy.NamedArg(tree)(name.toTermName, arg) + 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 @@ -418,6 +508,13 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Apply extends ApplyModule { + + def apply(fn: Term, args: List[Term])(implicit ctx: Context): Apply = + tpd.Apply(fn, args) + + def copy(original: Tree)(fun: Term, args: List[Term])(implicit ctx: Context): Apply = + tpd.cpy.Apply(original)(fun, args) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[Term])] = x match { case x: tpd.Apply => Some((x.fun, x.args)) case _ => None @@ -433,6 +530,13 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object TypeApply extends TypeApplyModule { + + def apply(fn: Term, args: List[TypeTree])(implicit ctx: Context): TypeApply = + tpd.TypeApply(fn, args) + + def copy(original: Tree)(fun: Term, args: List[TypeTree])(implicit ctx: Context): TypeApply = + tpd.cpy.TypeApply(original)(fun, args) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[TypeTree])] = x match { case x: tpd.TypeApply => Some((x.fun, x.args)) case _ => None @@ -448,6 +552,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Super extends SuperModule { + def apply(qual: Term, mix: Option[Id])(implicit ctx: Context): Super = + tpd.Super(qual, mix.getOrElse(untpd.EmptyTypeIdent), false, NoSymbol) + + def copy(original: Tree)(qual: Term, mix: Option[Id]): Super = + tpd.cpy.Super(original)(qual, mix.getOrElse(untpd.EmptyTypeIdent)) + 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 @@ -463,6 +573,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Typed extends TypedModule { + def apply(expr: Term, tpt: TypeTree)(implicit ctx: Context): Typed = + tpd.Typed(expr, tpt) + + def copy(original: Tree)(expr: Term, tpt: TypeTree)(implicit ctx: Context): Typed = + tpd.cpy.Typed(original)(expr, tpt) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, TypeTree)] = x match { case x: tpd.Typed => Some((x.expr, x.tpt)) case _ => None @@ -478,6 +594,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Assign extends AssignModule { + def apply(lhs: Term, rhs: Term)(implicit ctx: Context): Assign = + tpd.Assign(lhs, rhs) + + def copy(original: Tree)(lhs: Term, rhs: Term)(implicit ctx: Context): Assign = + tpd.cpy.Assign(original)(lhs, rhs) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { case x: tpd.Assign => Some((x.lhs, x.rhs)) case _ => None @@ -522,6 +644,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Block extends BlockModule { + def apply(stats: List[Statement], expr: Term)(implicit ctx: Context): Block = + tpd.Block(stats, expr) + + def copy(original: Tree)(stats: List[Statement], expr: Term)(implicit ctx: Context): Block = + tpd.cpy.Block(original)(stats, expr) + def unapply(x: Term)(implicit ctx: Context): Option[(List[Statement], Term)] = x match { case IsBlock(x) => Some((x.stats, x.expr)) case _ => None @@ -537,6 +665,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Inlined extends InlinedModule { + def apply(call: Option[TermOrTypeTree], bindings: List[Definition], expansion: Term)(implicit ctx: Context): Inlined = + tpd.Inlined(call.getOrElse(tpd.EmptyTree), bindings.map { case b: tpd.MemberDef => b }, expansion) + + def copy(original: Tree)(call: Option[TermOrTypeTree], bindings: List[Definition], expansion: Term)(implicit ctx: Context): Inlined = + tpd.cpy.Inlined(original)(call.getOrElse(tpd.EmptyTree), bindings.asInstanceOf[List[tpd.MemberDef]], expansion) + def unapply(x: Term)(implicit ctx: Context): Option[(Option[TermOrTypeTree], List[Statement], Term)] = x match { case x: tpd.Inlined => Some((optional(x.call), x.bindings, x.expansion)) @@ -553,6 +687,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Lambda extends LambdaModule { + def apply(meth: Term, tpt: Option[TypeTree])(implicit ctx: Context): Lambda = + tpd.Closure(Nil, meth, tpt.getOrElse(tpd.EmptyTree)) + + def copy(original: Tree)(meth: Tree, tpt: Option[TypeTree])(implicit ctx: Context): Lambda = + tpd.cpy.Closure(original)(Nil, meth, tpt.getOrElse(tpd.EmptyTree)) + 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 @@ -568,6 +708,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object If extends IfModule { + def apply(cond: Term, thenp: Term, elsep: Term)(implicit ctx: Context): If = + tpd.If(cond, thenp, elsep) + + def copy(original: Tree)(cond: Term, thenp: Term, elsep: Term)(implicit ctx: Context): If = + tpd.cpy.If(original)(cond, thenp, elsep) + 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 @@ -583,6 +729,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Match extends MatchModule { + def apply(selector: Term, cases: List[CaseDef])(implicit ctx: Context): Match = + tpd.Match(selector, cases) + + def copy(original: Tree)(selector: Term, cases: List[CaseDef])(implicit ctx: Context): Match = + tpd.cpy.Match(original)(selector, cases) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[CaseDef])] = x match { case x: tpd.Match => Some((x.selector, x.cases)) case _ => None @@ -598,6 +750,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Try extends TryModule { + def apply(expr: Term, cases: List[CaseDef], finalizer: Option[Term])(implicit ctx: Context): Try = + tpd.Try(expr, cases, finalizer.getOrElse(tpd.EmptyTree)) + + def copy(original: Tree)(expr: Term, cases: List[CaseDef], finalizer: Option[Term])(implicit ctx: Context): Try = + tpd.cpy.Try(original)(expr, cases, finalizer.getOrElse(tpd.EmptyTree)) + 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 @@ -613,6 +771,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Return extends ReturnModule { + def apply(expr: Term)(implicit ctx: Context): Return = + tpd.Return(expr, ctx.owner) + + def copy(original: Tree)(expr: Term)(implicit ctx: Context): Return = + tpd.cpy.Return(original)(expr, tpd.EmptyTree) + def unapply(x: Term)(implicit ctx: Context): Option[Term] = x match { case x: tpd.Return => Some(x.expr) case _ => None @@ -628,8 +792,14 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object Repeated extends RepeatedModule { - def unapply(x: Term)(implicit ctx: Context): Option[List[Term]] = x match { - case x: tpd.SeqLiteral => Some(x.elems) + def apply(elems: List[Term], elemtpt: TypeTree)(implicit ctx: Context): Repeated = + tpd.SeqLiteral(elems, elemtpt) + + def copy(original: Tree)(elems: List[Term], elemtpt: TypeTree)(implicit ctx: Context): Repeated = + tpd.cpy.SeqLiteral(original)(elems, elemtpt) + + def unapply(x: Tree)(implicit ctx: Context): Option[(List[Term], TypeTree)] = x match { + case x: tpd.SeqLiteral => Some((x.elems, x.elemtpt)) case _ => None } } @@ -647,6 +817,13 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object SelectOuter extends SelectOuterModule { + + def apply(qualifier: Term, name: String, levels: Int)(implicit ctx: Context): SelectOuter = + tpd.Select(qualifier, NameKinds.OuterSelectName(name.toTermName, levels)) + + def copy(original: Tree)(qualifier: Term, name: String, levels: Int)(implicit ctx: Context): SelectOuter = + tpd.cpy.Select(original)(qualifier, NameKinds.OuterSelectName(name.toTermName, levels)) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Int, Type)] = x match { case x: tpd.Select => x.name match { @@ -666,6 +843,12 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers object While extends WhileModule { + def apply(cond: Term, body: Term)(implicit ctx: Context): While = + tpd.WhileDo(cond, body) + + def copy(original: Tree)(cond: Term, body: Term)(implicit ctx: Context): While = + tpd.cpy.WhileDo(original)(cond, body) + def unapply(x: Term)(implicit ctx: Context): Option[(Term, Term)] = x match { case x: tpd.WhileDo => Some((x.cond, x.body)) case _ => None diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala index ce26313a04ed..2bf439ba3d28 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala @@ -26,7 +26,7 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w def name(implicit ctx: Contexts.Context): String = x.name.toString } - def ProjectDeco(x: TypeTree.Project): TypeTree.ProjectAPI = new TypeTree.ProjectAPI { + def ProjectionDeco(x: TypeTree.Projection): TypeTree.ProjectionAPI = new TypeTree.ProjectionAPI { def qualifier(implicit ctx: Contexts.Context): TypeTree = x.qualifier def name(implicit ctx: Contexts.Context): String = x.name.toString } @@ -75,12 +75,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w def body(implicit ctx: Contexts.Context): TypeOrBoundsTree = x.body } - def BindDeco(x: Bind): TypeTree.BindAPI = new TypeTree.BindAPI { + def TypeBindDeco(x: TypeTree.TypeBind): TypeTree.TypeBindAPI = new TypeTree.TypeBindAPI { def name(implicit ctx: Contexts.Context): String = x.name.toString def body(implicit ctx: Contexts.Context): TypeOrBoundsTree = x.body } - def TypeBlockDeco(x: TypeTree.Block): TypeTree.BlockAPI = new TypeTree.BlockAPI { + def TypeBlockDeco(x: TypeTree.TypeBlock): TypeTree.TypeBlockAPI = new TypeTree.TypeBlockAPI { def aliases(implicit ctx: Contexts.Context): List[TypeDef] = x.stats.map { case alias: TypeDef => alias } def tpt(implicit ctx: Contexts.Context): TypeTree = x.expr } @@ -94,10 +94,15 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w // ----- TypeTrees ------------------------------------------------ object IsTypeTree extends IsTypeTreeModule { - def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] = - if (x.isType) Some(x) else None - def unapply(termOrTypeTree: TermOrTypeTree)(implicit ctx: Context, dummy: DummyImplicit): Option[TypeTree] = - if (termOrTypeTree.isType) Some(termOrTypeTree) else None + def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] = x match { + case x: tpd.TypeBoundsTree => None + case _ => if (x.isType) Some(x) else None + } + + def unapply(termOrTypeTree: TermOrTypeTree)(implicit ctx: Context, dummy: DummyImplicit): Option[TypeTree] = termOrTypeTree match { + case _: tpd.TypeBoundsTree => None + case _ => if (termOrTypeTree.isType) Some(termOrTypeTree) else None + } } object TypeTree extends TypeTreeModule with TypeTreeCoreModuleImpl { @@ -110,6 +115,8 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Inferred extends InferredModule { + def apply(tpe: Type)(implicit ctx: Context): Inferred = tpd.TypeTree(tpe) + def unapply(x: TypeTree)(implicit ctx: Context): Boolean = x match { case x @ Trees.TypeTree() => !x.tpe.isInstanceOf[Types.TypeBounds] case _ => false @@ -124,6 +131,8 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Ident extends IdentModule { + def copy(original: Ident)(name: String)(implicit ctx: Context): Ident = + tpd.cpy.Ident(original)(name.toTypeName) def unapply(x: TypeTree)(implicit ctx: Context): Option[String] = x match { case x: tpd.Ident if x.isType => Some(x.name.toString) case _ => None @@ -138,20 +147,29 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Select extends SelectModule { + def apply(qualifier: Term, name: String)(implicit ctx: Context): Select = + tpd.Select(qualifier, name.toTypeName) + + def copy(original: Select)(qualifier: Term, name: String)(implicit ctx: Context): Select = + tpd.cpy.Select(original)(qualifier, name.toTypeName) + 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 IsProject extends IsProjectModule { - def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Project] = tpt match { + object IsProjection extends IsProjectionModule { + def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Projection] = tpt match { case tpt: tpd.Select if tpt.isType && tpt.qualifier.isType => Some(tpt) case _ => None } } - object Project extends ProjectModule { + object Projection extends ProjectionModule { + def copy(original: Projection)(qualifier: TypeTree, name: String)(implicit ctx: Context): Projection = + tpd.cpy.Select(original)(qualifier, name.toTypeName) + 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 @@ -166,6 +184,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Singleton extends SingletonModule { + def apply(ref: Term)(implicit ctx: Context): Singleton = + tpd.SingletonTypeTree(ref) + + def copy(original: Singleton)(ref: Term)(implicit ctx: Context): Singleton = + tpd.cpy.SingletonTypeTree(original)(ref) + def unapply(x: TypeTree)(implicit ctx: Context): Option[Term] = x match { case x: tpd.SingletonTypeTree => Some(x.ref) case _ => None @@ -180,6 +204,9 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Refined extends RefinedModule { + def copy(original: Refined)(tpt: TypeTree, refinements: List[Definition])(implicit ctx: Context): Refined = + tpd.cpy.RefinedTypeTree(original)(tpt, refinements) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[Definition])] = x match { case x: tpd.RefinedTypeTree => Some(x.tpt, x.refinements) case _ => None @@ -194,6 +221,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Applied extends AppliedModule { + def apply(tpt: TypeTree, args: List[TypeOrBoundsTree])(implicit ctx: Context): Applied = + tpd.AppliedTypeTree(tpt, args) + + def copy(original: Applied)(tpt: TypeTree, args: List[TypeOrBoundsTree])(implicit ctx: Context): Applied = + tpd.cpy.AppliedTypeTree(original)(tpt, args) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])] = x match { case x: tpd.AppliedTypeTree => Some(x.tpt, x.args) case _ => None @@ -208,6 +241,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Annotated extends AnnotatedModule { + def apply(arg: TypeTree, annotation: Term)(implicit ctx: Context): Annotated = + tpd.Annotated(arg, annotation) + + def copy(original: Annotated)(arg: TypeTree, annotation: Term)(implicit ctx: Context): Annotated = + tpd.cpy.Annotated(original)(arg, annotation) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, Term)] = x match { case x: tpd.Annotated => Some(x.arg, x.annot) case _ => None @@ -222,6 +261,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object And extends AndModule { + def apply(left: TypeTree, right: TypeTree)(implicit ctx: Context): And = + tpd.AndTypeTree(left, right) + + def copy(original: And)(left: TypeTree, right: TypeTree)(implicit ctx: Context): And = + tpd.cpy.AndTypeTree(original)(left, right) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { case x: tpd.AndTypeTree => Some(x.left, x.right) case _ => None @@ -236,6 +281,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object Or extends OrModule { + def apply(left: TypeTree, right: TypeTree)(implicit ctx: Context): Or = + tpd.OrTypeTree(left, right) + + def copy(original: Or)(left: TypeTree, right: TypeTree)(implicit ctx: Context): Or = + tpd.cpy.OrTypeTree(original)(left, right) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match { case x: tpd.OrTypeTree => Some(x.left, x.right) case _ => None @@ -250,6 +301,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object MatchType extends MatchTypeModule { + def apply(bound: Option[TypeTree], selector: TypeTree, cases: List[TypeCaseDef])(implicit ctx: Context): MatchType = + tpd.MatchTypeTree(bound.getOrElse(tpd.EmptyTree), selector, cases) + + def copy(original: MatchType)(bound: Option[TypeTree], selector: TypeTree, cases: List[TypeCaseDef])(implicit ctx: Context): MatchType = + tpd.cpy.MatchTypeTree(original)(bound.getOrElse(tpd.EmptyTree), selector, cases) + def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[(Option[TypeTree], TypeTree, List[CaseDef])] = x match { case x: tpd.MatchTypeTree => Some((if (x.bound == tpd.EmptyTree) None else Some(x.bound), x.selector, x.cases)) case _ => None @@ -264,6 +321,12 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object ByName extends ByNameModule { + def apply(result: TypeTree)(implicit ctx: Context): ByName = + tpd.ByNameTypeTree(result) + + def copy(original: ByName)(result: TypeTree)(implicit ctx: Context): ByName = + tpd.cpy.ByNameTypeTree(original)(result) + def unapply(x: TypeTree)(implicit ctx: Context): Option[TypeTree] = x match { case x: tpd.ByNameTypeTree => Some(x.result) case _ => None @@ -278,35 +341,50 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w } object LambdaTypeTree extends LambdaTypeTreeModule { + def apply(tparams: List[TypeDef], body: TypeOrBoundsTree)(implicit ctx: Context): LambdaTypeTree = + tpd.LambdaTypeTree(tparams, body) + + def copy(original: LambdaTypeTree)(tparams: List[TypeDef], body: TypeOrBoundsTree)(implicit ctx: Context): LambdaTypeTree = + tpd.cpy.LambdaTypeTree(original)(tparams, body) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(List[TypeDef], TypeOrBoundsTree)] = x match { case Trees.LambdaTypeTree(tparams, body) => Some((tparams, body)) case _ => None } } - object IsBind extends IsBindModule { - def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Bind] = tpt match { + object IsTypeBind extends IsTypeBindModule { + def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBind] = tpt match { case tpt: tpd.Bind if tpt.name.isTypeName => Some(tpt) case _ => None } } - object Bind extends BindModule { + object TypeBind extends TypeBindModule { + def copy(original: TypeBind)(name: String, tpt: TypeOrBoundsTree)(implicit ctx: Context): TypeBind = + tpd.cpy.Bind(original)(name.toTypeName, tpt) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree)] = x match { case x: tpd.Bind if x.name.isTypeName => Some((x.name.toString, x.body)) case _ => None } } - object IsBlock extends IsBlockModule { - def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Block] = tpt match { + object IsTypeBlock extends IsTypeBlockModule { + def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBlock] = tpt match { case tpt: tpd.Block => Some(tpt) case _ => None } } - object Block extends BlockModule { + object TypeBlock extends TypeBlockModule { + def apply(aliases: List[TypeDef], tpt: TypeTree)(implicit ctx: Context): TypeBlock = + tpd.Block(aliases, tpt) + + def copy(original: TypeBlock)(aliases: List[TypeDef], tpt: TypeTree)(implicit ctx: Context): TypeBlock = + tpd.cpy.Block(original)(aliases, tpt) + def unapply(x: TypeTree)(implicit ctx: Context): Option[(List[TypeDef], TypeTree)] = x match { case x: tpd.Block => Some((x.stats.map { case alias: TypeDef => alias }, x.expr)) case _ => None diff --git a/library/src/scala/tasty/reflect/CaseDefOps.scala b/library/src/scala/tasty/reflect/CaseDefOps.scala index 4f4d901c3175..866179aa8c3f 100644 --- a/library/src/scala/tasty/reflect/CaseDefOps.scala +++ b/library/src/scala/tasty/reflect/CaseDefOps.scala @@ -13,6 +13,11 @@ trait CaseDefOps extends Core { val CaseDef: CaseDefModule abstract class CaseDefModule { + + def apply(pattern: Pattern, guard: Option[Term], body: Term)(implicit ctx: Context): CaseDef + + def copy(original: CaseDef)(pattern: Pattern, guard: Option[Term], body: Term)(implicit ctx: Context): CaseDef + def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] } @@ -25,6 +30,10 @@ trait CaseDefOps extends Core { val TypeCaseDef: TypeCaseDefModule abstract class TypeCaseDefModule { + def apply(pattern: TypeTree, body: TypeTree)(implicit ctx: Context): TypeCaseDef + + def copy(original: TypeCaseDef)(pattern: TypeTree, body: TypeTree)(implicit ctx: Context): TypeCaseDef + def unapply(x: TypeCaseDef): Option[(TypeTree, TypeTree)] } } diff --git a/library/src/scala/tasty/reflect/Core.scala b/library/src/scala/tasty/reflect/Core.scala index 3d37b5b617aa..5b14d3a92320 100644 --- a/library/src/scala/tasty/reflect/Core.scala +++ b/library/src/scala/tasty/reflect/Core.scala @@ -13,8 +13,9 @@ package scala.tasty.reflect * | +- DefDef * | +- ValDef * | - * +- Term --------+- Ident - * +- Select + * +- Term --------+- Ref -+- Ident + * | +- Select + * | * +- Literal * +- This * +- New @@ -49,8 +50,8 @@ package scala.tasty.reflect * | +- MatchType * | +- ByName * | +- LambdaTypeTree - * | +- Bind - * | +- Block + * | +- TypeBind + * | +- TypeBlock * | * +- TypeBoundsTree * +- WildcardTypeTree @@ -61,7 +62,7 @@ package scala.tasty.reflect * +- Pattern --+- Value * +- Bind * +- Unapply - * +- Alternative + * +- Alternatives * +- TypeTest * * @@ -164,11 +165,14 @@ trait Core { /** Trees representing an expression in the source code */ trait TermCoreModule { - /** Tree representing a reference to definition with a given name */ - type Ident <: Term + /** Tree representing a reference to definition */ + type Ref <: Term - /** Tree representing a selection of definition with a given name on a given prefix */ - type Select <: Term + /** Tree representing a reference to definition with a given name */ + type Ident <: Ref + + /** Tree representing a selection of definition with a given name on a given prefix */ + type Select <: Ref /** Tree representing a literal value in the source code */ type Literal <: Term @@ -248,7 +252,7 @@ trait Core { type Unapply <: Pattern /** Pattern representing `X | Y | ...` alternatives. */ - type Alternative <: Pattern + type Alternatives <: Pattern /** Pattern representing a `x: Y` type test. */ type TypeTest <: Pattern @@ -275,7 +279,7 @@ trait Core { type Select <: TypeTree /** Type tree representing a selection of definition with a given name on a given type prefix */ - type Project <: TypeTree + type Projection <: TypeTree /** Type tree representing a singleton type */ type Singleton <: TypeTree @@ -305,10 +309,10 @@ trait Core { type LambdaTypeTree <: TypeTree /** Type tree representing a type binding */ - type Bind <: TypeTree + type TypeBind <: TypeTree /** Type tree within a block with aliases `{ type U1 = ... ; T[U1, U2] }` */ - type Block <: TypeTree + type TypeBlock <: TypeTree } @@ -316,7 +320,7 @@ trait Core { type TypeBoundsTree <: TypeOrBoundsTree /** Type tree representing wildcard type bounds written in the source. - * The wildcard type `_` (for example in in `List[_]`) will be a type tree that + * The wildcard type `_` (for example in in `List[_]`) will be a type tree that * represents a type but has `TypeBound`a inside. */ type WildcardType <: TypeOrBoundsTree diff --git a/library/src/scala/tasty/reflect/PatternOps.scala b/library/src/scala/tasty/reflect/PatternOps.scala index aa4e095a2bfa..0ad4d7307dd0 100644 --- a/library/src/scala/tasty/reflect/PatternOps.scala +++ b/library/src/scala/tasty/reflect/PatternOps.scala @@ -3,6 +3,12 @@ package reflect trait PatternOps extends Core { + implicit def ValueDeco(value: Value): Pattern.ValueAPI + implicit def BindDeco(bind: Bind): Pattern.BindAPI + implicit def UnapplyDeco(unapply: Unapply): Pattern.UnapplyAPI + implicit def AlternativeDeco(alternatives: Alternatives): Pattern.AlternativesAPI + implicit def TypeTestDeco(typeTest: TypeTest): Pattern.TypeTestAPI + trait PatternAPI { /** Position in the source code */ def pos(implicit ctx: Context): Position @@ -14,30 +20,89 @@ trait PatternOps extends Core { val Pattern: PatternModule abstract class PatternModule { + val IsValue: IsValueModule + abstract class IsValueModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Value] + } + val Value: ValueModule abstract class ValueModule { + def apply(tpt: Term)(implicit ctx: Context): Value + def copy(original: Value)(tpt: Term)(implicit ctx: Context): Value def unapply(pattern: Pattern)(implicit ctx: Context): Option[Term] } + trait ValueAPI { + def value(implicit ctx: Context): Term + } + + val IsBind: IsBindModule + abstract class IsBindModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Bind] + } + val Bind: BindModule abstract class BindModule { + // TODO def apply(name: String, pattern: Pattern)(implicit ctx: Context): Bind + def copy(original: Bind)(name: String, pattern: Pattern)(implicit ctx: Context): Bind def unapply(pattern: Pattern)(implicit ctx: Context): Option[(String, Pattern)] } + trait BindAPI { + def name(implicit ctx: Context): String + def pattern(implicit ctx: Context): Pattern + } + + val IsUnapply: IsUnapplyModule + abstract class IsUnapplyModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Unapply] + } + val Unapply: UnapplyModule abstract class UnapplyModule { + // TODO def apply(fun: Term, implicits: List[Term], patterns: List[Pattern])(implicit ctx: Context): Unapply + def copy(original: Unapply)(fun: Term, implicits: List[Term], patterns: List[Pattern])(implicit ctx: Context): Unapply def unapply(pattern: Pattern)(implicit ctx: Context): Option[(Term, List[Term], List[Pattern])] } - val Alternative: AlternativeModule - abstract class AlternativeModule { + trait UnapplyAPI { + def fun(implicit ctx: Context): Term + def implicits(implicit ctx: Context): List[Term] + def patterns(implicit ctx: Context): List[Pattern] + } + + val IsAlternatives: IsAlternativesModule + abstract class IsAlternativesModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[Alternatives] + } + + val Alternatives: AlternativesModule + abstract class AlternativesModule { + def apply(patterns: List[Pattern])(implicit ctx: Context): Alternatives + def copy(original: Alternatives)(patterns: List[Pattern])(implicit ctx: Context): Alternatives def unapply(pattern: Pattern)(implicit ctx: Context): Option[List[Pattern]] } + trait AlternativesAPI { + def patterns(implicit ctx: Context): List[Pattern] + } + + val IsTypeTest: IsTypeTestModule + abstract class IsTypeTestModule { + def unapply(pattern: Pattern)(implicit ctx: Context): Option[TypeTest] + } + val TypeTest: TypeTestModule abstract class TypeTestModule { + def apply(tpt: TypeTree)(implicit ctx: Context): TypeTest + def copy(original: TypeTest)(tpt: TypeTree)(implicit ctx: Context): TypeTest def unapply(pattern: Pattern)(implicit ctx: Context): Option[TypeTree] } + + trait TypeTestAPI { + def tpt(implicit ctx: Context): TypeTree + } + } } diff --git a/library/src/scala/tasty/reflect/Printers.scala b/library/src/scala/tasty/reflect/Printers.scala index ddc97b4e2cd7..07d8a04173d8 100644 --- a/library/src/scala/tasty/reflect/Printers.scala +++ b/library/src/scala/tasty/reflect/Printers.scala @@ -135,8 +135,8 @@ trait Printers this += "Term.While(" += cond += ", " += body += ")" case Term.Try(block, handlers, finalizer) => this += "Term.Try(" += block += ", " ++= handlers += ", " += finalizer += ")" - case Term.Repeated(elems) => - this += "Term.Repeated(" ++= elems += ")" + case Term.Repeated(elems, elemtpt) => + this += "Term.Repeated(" ++= elems += ", " += elemtpt += ")" case Term.Inlined(call, bindings, expansion) => this += "Term.Inlined(" visitOption(call, visitTermOrTypeTree) @@ -166,8 +166,8 @@ trait Printers this += "TypeTree.Ident(\"" += name += "\")" case TypeTree.Select(qualifier, name) => this += "TypeTree.Select(" += qualifier += ", \"" += name += "\")" - case TypeTree.Project(qualifier, name) => - this += "TypeTree.Project(" += qualifier += ", \"" += name += "\")" + case TypeTree.Projection(qualifier, name) => + this += "TypeTree.Projection(" += qualifier += ", \"" += name += "\")" case TypeTree.Singleton(ref) => this += "TypeTree.Singleton(" += ref += ")" case TypeTree.And(left, right) => @@ -184,10 +184,10 @@ trait Printers this += "TypeTree.Annotated(" += arg += ", " += annot += ")" case TypeTree.LambdaTypeTree(tparams, body) => this += "TypeTree.LambdaTypeTree(" ++= tparams += ", " += body += ")" - case TypeTree.Bind(name, bounds) => - this += "TypeTree.Bind(" += name += ", " += bounds += ")" - case TypeTree.Block(aliases, tpt) => - this += "TypeTree.Block(" ++= aliases += ", " += tpt += ")" + case TypeTree.TypeBind(name, bounds) => + this += "TypeTree.TypeBind(" += name += ", " += bounds += ")" + case TypeTree.TypeBlock(aliases, tpt) => + this += "TypeTree.TypeBlock(" ++= aliases += ", " += tpt += ")" case TypeBoundsTree(lo, hi) => this += "TypeBoundsTree(" += lo += ", " += hi += ")" case WildcardTypeTree() => @@ -213,7 +213,7 @@ trait Printers this += "Pattern.Bind(\"" += name += "\", " += body += ")" case Pattern.Unapply(fun, implicits, patterns) => this += "Pattern.Unapply(" += fun += ", " ++= implicits += ", " ++= patterns += ")" - case Pattern.Alternative(patterns) => + case Pattern.Alternatives(patterns) => this += "Pattern.Alternative(" ++= patterns += ")" case Pattern.TypeTest(tpt) => this += "Pattern.TypeTest(" += tpt += ")" @@ -725,7 +725,7 @@ trait Printers case _ => printTree(fn) } val args1 = args match { - case init :+ Term.Typed(Term.Repeated(Nil), _) => init // drop empty var args at the end + case init :+ Term.Typed(Term.Repeated(Nil, _), _) => init // drop empty var args at the end case _ => args } @@ -755,7 +755,7 @@ trait Printers tpt.tpe match { case Types.Repeated(_) => term match { - case Term.Repeated(_) => + case Term.Repeated(_, _) => printTree(term) case _ => printTree(term) @@ -830,7 +830,7 @@ trait Printers this += "return " printTree(expr) - case Term.Repeated(elems) => + case Term.Repeated(elems, _) => printTrees(elems, ", ") case _ => @@ -1203,7 +1203,7 @@ trait Printers } inParens(printPatterns(patterns, ", ")) - case Pattern.Alternative(trees) => + case Pattern.Alternatives(trees) => inParens(printPatterns(trees, " | ")) case Pattern.TypeTest(tpt) => @@ -1270,7 +1270,7 @@ trait Printers case TypeTree.Select(qual, name) => printTree(qual) += "." += highlightTypeDef(name, color) - case TypeTree.Project(qual, name) => + case TypeTree.Projection(qual, name) => printTypeTree(qual) += "#" += highlightTypeDef(name, color) case TypeTree.Singleton(ref) => @@ -1325,10 +1325,10 @@ trait Printers this += highlightTypeDef(" => ", color) printTypeOrBoundsTree(body) - case TypeTree.Bind(name, _) => + case TypeTree.TypeBind(name, _) => this += highlightTypeDef(name, color) - case TypeTree.Block(aliases, tpt) => + case TypeTree.TypeBlock(aliases, tpt) => inBlock { printTrees(aliases, lineBreak()) printTypeTree(tpt) diff --git a/library/src/scala/tasty/reflect/TreeOps.scala b/library/src/scala/tasty/reflect/TreeOps.scala index 7e321b41e7f3..be45b19e8f02 100644 --- a/library/src/scala/tasty/reflect/TreeOps.scala +++ b/library/src/scala/tasty/reflect/TreeOps.scala @@ -55,22 +55,37 @@ trait TreeOps extends Core { val PackageClause: PackageClauseModule abstract class PackageClauseModule { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Tree])] + def apply(pid: Term.Ref, stats: List[Tree])(implicit ctx: Context): PackageClause + def copy(original: PackageClause)(pid: Term.Ref, stats: List[Tree])(implicit ctx: Context): PackageClause + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term.Ref, List[Tree])] } trait PackageClauseAPI { + def pid(implicit ctx: Context): Term.Ref + def stats(implicit ctx: Context): List[Tree] } - // ----- Statements ----------------------------------------------- + val IsImport: IsImportModule + abstract class IsImportModule { + def unapply(tree: Tree)(implicit ctx: Context): Option[Import] + } val Import: ImportModule abstract class ImportModule { + def apply(expr: Term, selectors: List[ImportSelector])(implicit ctx: Context): Import + def copy(original: Import)(expr: Term, selectors: List[ImportSelector])(implicit ctx: Context): Import 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] + def selectors(implicit ctx: Context): List[ImportSelector] + } + + val IsStatement: IsStatementModule + abstract class IsStatementModule { + /** Matches any Statement and returns it */ + def unapply(tree: Tree)(implicit ctx: Context): Option[Statement] } // ----- Definitions ---------------------------------------------- @@ -93,6 +108,8 @@ trait TreeOps extends Core { val ClassDef: ClassDefModule abstract class ClassDefModule { + // TODO def apply(name: String, constr: DefDef, parents: List[TermOrTypeTree], selfOpt: Option[ValDef], body: List[Statement])(implicit ctx: Context): ClassDef + def copy(original: ClassDef)(name: String, constr: DefDef, parents: List[TermOrTypeTree], selfOpt: Option[ValDef], body: List[Statement])(implicit ctx: Context): ClassDef def unapply(tree: Tree)(implicit ctx: Context): Option[(String, DefDef, List[TermOrTypeTree], Option[ValDef], List[Statement])] } @@ -114,6 +131,8 @@ trait TreeOps extends Core { val DefDef: DefDefModule abstract class DefDefModule { + def apply(symbol: DefSymbol, rhsFn: List[Type] => List[List[Term]] => Option[Term])(implicit ctx: Context): DefDef + def copy(original: DefDef)(name: String, typeParams: List[TypeDef], paramss: List[List[ValDef]], tpt: TypeTree, rhs: Option[Term])(implicit ctx: Context): DefDef def unapply(tree: Tree)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] } @@ -135,6 +154,8 @@ trait TreeOps extends Core { val ValDef: ValDefModule abstract class ValDefModule { + def apply(sym: ValSymbol, rhs: Option[Term])(implicit ctx: Context): ValDef + def copy(original: ValDef)(name: String, tpt: TypeTree, rhs: Option[Term])(implicit ctx: Context): ValDef def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] } @@ -154,6 +175,8 @@ trait TreeOps extends Core { val TypeDef: TypeDefModule abstract class TypeDefModule { + def apply(symbol: TypeSymbol)(implicit ctx: Context): TypeDef + def copy(original: TypeDef)(name: String, rhs: TypeOrBoundsTree)(implicit ctx: Context): TypeDef def unapply(tree: Tree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree /* TypeTree | TypeBoundsTree */)] } @@ -211,11 +234,25 @@ trait TreeOps extends Core { def name(implicit ctx: Context): String } + val Ref: RefModule + abstract class RefModule { + + /** Create a reference tree */ + def apply(sym: Symbol)(implicit ctx: Context): Ref + + // TODO def copy(original: Tree)(name: String)(implicit ctx: Context): Ref + + } + /** Scala term identifier */ val Ident: IdentModule abstract class IdentModule { + + def copy(original: Tree)(name: String)(implicit ctx: Context): Ident + /** Matches a term identifier and returns its name */ def unapply(tree: Tree)(implicit ctx: Context): Option[String] + } val IsSelect: IsSelectModule @@ -233,6 +270,11 @@ trait TreeOps extends Core { /** Scala term selection */ val Select: SelectModule abstract class SelectModule { + + // TODO def apply(qualifier: Term, name: String, signature: Option[Signature])(implicit ctx: Context): Select + + def copy(original: Tree)(qualifier: Term, name: String)(implicit ctx: Context): Select + /** Matches `.` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, String)] } @@ -250,7 +292,15 @@ trait TreeOps extends Core { /** Scala literal constant */ val Literal: LiteralModule abstract class LiteralModule { + + /** Create a literal constant */ + def apply(constant: Constant)(implicit ctx: Context): Literal + + def copy(original: Tree)(constant: Constant)(implicit ctx: Context): Literal + + /** Matches a literal constant */ def unapply(tree: Tree)(implicit ctx: Context): Option[Constant] + } val IsThis: IsThisModule @@ -266,8 +316,15 @@ trait TreeOps extends Core { /** Scala `this` or `this[id]` */ val This: ThisModule abstract class ThisModule { - /** Matches new `this[` */ + + /** Create a `this[` */ + def apply(cls: ClassSymbol)(implicit ctx: Context): This + + def copy(original: Tree)(qual: Option[Id]): This + + /** Matches `this[` */ def unapply(tree: Tree)(implicit ctx: Context): Option[Option[Id]] + } val IsNew: IsNewModule @@ -283,8 +340,15 @@ trait TreeOps extends Core { /** Scala `new` */ val New: NewModule abstract class NewModule { - /** Matches new `new ` */ + + /** Create a `new ` */ + def apply(tpt: TypeTree)(implicit ctx: Context): New + + def copy(original: Tree)(tpt: TypeTree)(implicit ctx: Context): New + + /** Matches a `new ` */ def unapply(tree: Tree)(implicit ctx: Context): Option[TypeTree] + } val IsNamedArg: IsNamedArgModule @@ -301,8 +365,15 @@ trait TreeOps extends Core { /** Scala named argument `x = y` in argument position */ val NamedArg: NamedArgModule abstract class NamedArgModule { - /** Matches ` = ` */ + + /** Create a named argument ` = ` */ + def apply(name: String, arg: Term)(implicit ctx: Context): NamedArg + + def copy(tree: NamedArg)(name: String, arg: Term)(implicit ctx: Context): NamedArg + + /** Matches a named argument ` = ` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(String, Term)] + } val IsApply: IsApplyModule @@ -319,8 +390,15 @@ trait TreeOps extends Core { /** Scala parameter application */ val Apply: ApplyModule abstract class ApplyModule { - /** Matches function application `()` */ + + /** Create a function application `()` */ + def apply(fn: Term, args: List[Term])(implicit ctx: Context): Apply + + def copy(original: Tree)(fun: Term, args: List[Term])(implicit ctx: Context): Apply + + /** Matches a function application `()` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[Term])] + } val IsTypeApply: IsTypeApplyModule @@ -337,8 +415,15 @@ trait TreeOps extends Core { /** Scala type parameter application */ val TypeApply: TypeApplyModule abstract class TypeApplyModule { - /** Matches function type application `[]` */ + + /** Create a function type application `[]` */ + def apply(fn: Term, args: List[TypeTree])(implicit ctx: Context): TypeApply + + def copy(original: Tree)(fun: Term, args: List[TypeTree])(implicit ctx: Context): TypeApply + + /** Matches a function type application `[]` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[TypeTree])] + } val IsSuper: IsSuperModule @@ -355,8 +440,15 @@ trait TreeOps extends Core { /** Scala `x.super` or `x.super[id]` */ val Super: SuperModule abstract class SuperModule { - /** Matches new `.super[` */ + + /** Creates a `.super[` */ + def apply(qual: Term, mix: Option[Id])(implicit ctx: Context): Super + + def copy(original: Tree)(qual: Term, mix: Option[Id]): Super + + /** Matches a `.super[` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Option[Id])] + } val IsTyped: IsTypedModule @@ -373,8 +465,15 @@ trait TreeOps extends Core { /** Scala ascription `x: T` */ val Typed: TypedModule abstract class TypedModule { - /** Matches `: ` */ + + /** Create a type ascription `: ` */ + def apply(expr: Term, tpt: TypeTree)(implicit ctx: Context): Typed + + def copy(original: Tree)(expr: Term, tpt: TypeTree)(implicit ctx: Context): Typed + + /** Matches `: ` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, TypeTree)] + } val IsAssign: IsAssignModule @@ -391,8 +490,15 @@ trait TreeOps extends Core { /** Scala assign `x = y` */ val Assign: AssignModule abstract class AssignModule { - /** Matches ` = ` */ + + /** Create an assignment ` = ` */ + def apply(lhs: Term, rhs: Term)(implicit ctx: Context): Assign + + def copy(original: Tree)(lhs: Term, rhs: Term)(implicit ctx: Context): Assign + + /** Matches an assignment ` = ` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] + } val IsBlock: IsBlockModule @@ -409,8 +515,15 @@ trait TreeOps extends Core { /** Scala code block `{ stat0; ...; statN; expr }` term */ val Block: BlockModule abstract class BlockModule { - /** Matches `{ ; }` */ + + /** Creates a block `{ ; }` */ + def apply(stats: List[Statement], expr: Term)(implicit ctx: Context): Block + + def copy(original: Tree)(stats: List[Statement], expr: Term)(implicit ctx: Context): Block + + /** Matches a block `{ ; }` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(List[Statement], Term)] + } val IsLambda: IsLambdaModule @@ -426,7 +539,13 @@ trait TreeOps extends Core { val Lambda: LambdaModule abstract class LambdaModule { + + def apply(meth: Term, tpt: Option[TypeTree])(implicit ctx: Context): Lambda + + def copy(original: Tree)(meth: Tree, tpt: Option[TypeTree])(implicit ctx: Context): Lambda + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Option[TypeTree])] + } val IsIf: IsIfModule @@ -444,8 +563,15 @@ trait TreeOps extends Core { /** Scala `if`/`else` term */ val If: IfModule abstract class IfModule { - /** Matches `if () else ` */ + + /** Create an if/then/else `if () else ` */ + def apply(cond: Term, thenp: Term, elsep: Term)(implicit ctx: Context): If + + def copy(original: Tree)(cond: Term, thenp: Term, elsep: Term)(implicit ctx: Context): If + + /** Matches an if/then/else `if () else ` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term, Term)] + } val IsMatch: IsMatchModule @@ -462,8 +588,15 @@ trait TreeOps extends Core { /** Scala `match` term */ val Match: MatchModule abstract class MatchModule { - /** Matches ` match { }` */ + + /** Creates a pattern match ` match { }` */ + def apply(selector: Term, cases: List[CaseDef])(implicit ctx: Context): Match + + def copy(original: Tree)(selector: Term, cases: List[CaseDef])(implicit ctx: Context): Match + + /** Matches a pattern match ` match { }` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[CaseDef])] + } val IsTry: IsTryModule @@ -481,8 +614,15 @@ trait TreeOps extends Core { /** Scala `try`/`catch`/`finally` term */ val Try: TryModule abstract class TryModule { - /** Matches `try catch { } finally ` */ + + /** Create a try/catch `try catch { } finally ` */ + def apply(expr: Term, cases: List[CaseDef], finalizer: Option[Term])(implicit ctx: Context): Try + + def copy(original: Tree)(expr: Term, cases: List[CaseDef], finalizer: Option[Term])(implicit ctx: Context): Try + + /** Matches a try/catch `try catch { } finally ` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, List[CaseDef], Option[Term])] + } val IsReturn: IsReturnModule @@ -498,8 +638,15 @@ trait TreeOps extends Core { /** Scala local `return` */ val Return: ReturnModule abstract class ReturnModule { + + /** Creates `return ` */ + def apply(expr: Term)(implicit ctx: Context): Return + + def copy(original: Tree)(expr: Term)(implicit ctx: Context): Return + /** Matches `return ` */ def unapply(tree: Tree)(implicit ctx: Context): Option[Term] + } val IsRepeated: IsRepeatedModule @@ -510,11 +657,18 @@ trait TreeOps extends Core { trait RepeatedAPI { def elems(implicit ctx: Context): List[Term] + def elemtpt(implicit ctx: Context): TypeTree } val Repeated: RepeatedModule abstract class RepeatedModule { - def unapply(tree: Tree)(implicit ctx: Context): Option[List[Term]] + + def apply(elems: List[Term], tpt: TypeTree)(implicit ctx: Context): Repeated + + def copy(original: Tree)(elems: List[Term], tpt: TypeTree)(implicit ctx: Context): Repeated + + def unapply(tree: Tree)(implicit ctx: Context): Option[(List[Term], TypeTree)] + } val IsInlined: IsInlinedModule @@ -531,7 +685,13 @@ trait TreeOps extends Core { val Inlined: InlinedModule abstract class InlinedModule { + + def apply(call: Option[TermOrTypeTree], bindings: List[Definition], expansion: Term)(implicit ctx: Context): Inlined + + def copy(original: Tree)(call: Option[TermOrTypeTree], bindings: List[Definition], expansion: Term)(implicit ctx: Context): Inlined + def unapply(tree: Tree)(implicit ctx: Context): Option[(Option[TermOrTypeTree], List[Definition], Term)] + } val IsSelectOuter: IsSelectOuterModule @@ -548,7 +708,13 @@ trait TreeOps extends Core { val SelectOuter: SelectOuterModule abstract class SelectOuterModule { + + def apply(qualifier: Term, name: String, levels: Int)(implicit ctx: Context): SelectOuter + + def copy(original: Tree)(qualifier: Term, name: String, levels: Int)(implicit ctx: Context): SelectOuter + def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Int, Type)] + } val IsWhile: IsWhileModule @@ -564,8 +730,15 @@ trait TreeOps extends Core { val While: WhileModule abstract class WhileModule { + + /** Creates a while loop `while () ` and returns (, ) */ + def apply(cond: Term, body: Term)(implicit ctx: Context): While + + def copy(original: Tree)(cond: Term, body: Term)(implicit ctx: Context): While + /** Extractor for while loops. Matches `while () ` and returns (, ) */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Term)] + } } diff --git a/library/src/scala/tasty/reflect/TreeUtils.scala b/library/src/scala/tasty/reflect/TreeUtils.scala index a1338f4058df..5abd2bb78586 100644 --- a/library/src/scala/tasty/reflect/TreeUtils.scala +++ b/library/src/scala/tasty/reflect/TreeUtils.scala @@ -64,8 +64,8 @@ trait TreeUtils foldTree(x, expr) case Term.Try(block, handler, finalizer) => foldTrees(foldCaseDefs(foldTree(x, block), handler), finalizer) - case Term.Repeated(elems) => - foldTrees(x, elems) + case Term.Repeated(elems, elemtpt) => + foldTrees(foldTypeTree(x, elemtpt), elems) case Term.Inlined(call, bindings, expansion) => foldTree(foldTrees(x, bindings), expansion) case IsDefinition(vdef @ ValDef(_, tpt, rhs)) => @@ -91,7 +91,7 @@ trait TreeUtils case TypeTree.Inferred() => x case TypeTree.Ident(_) => x case TypeTree.Select(qualifier, _) => foldTree(x, qualifier) - case TypeTree.Project(qualifier, _) => foldTypeTree(x, qualifier) + case TypeTree.Projection(qualifier, _) => foldTypeTree(x, qualifier) case TypeTree.Singleton(ref) => foldTree(x, ref) case TypeTree.And(left, right) => foldTypeTree(foldTypeTree(x, left), right) case TypeTree.Or(left, right) => foldTypeTree(foldTypeTree(x, left), right) @@ -100,8 +100,8 @@ trait TreeUtils case TypeTree.ByName(result) => foldTypeTree(x, result) case TypeTree.Annotated(arg, annot) => foldTree(foldTypeTree(x, arg), annot) case TypeTree.LambdaTypeTree(typedefs, arg) => foldTypeTree(foldTrees(x, typedefs), arg) - case TypeTree.Bind(_, tbt) => foldTypeTree(x, tbt) - case TypeTree.Block(typedefs, tpt) => foldTypeTree(foldTrees(x, typedefs), tpt) + case TypeTree.TypeBind(_, tbt) => foldTypeTree(x, tbt) + case TypeTree.TypeBlock(typedefs, tpt) => foldTypeTree(foldTrees(x, typedefs), tpt) case TypeTree.MatchType(boundopt, selector, cases) => foldTypeCaseDefs(foldTypeTree(boundopt.fold(x)(foldTypeTree(x, _)), selector), cases) case WildcardTypeTree() => x @@ -120,7 +120,7 @@ trait TreeUtils case Pattern.Value(v) => foldTree(x, v) case Pattern.Bind(_, body) => foldPattern(x, body) case Pattern.Unapply(fun, implicits, patterns) => foldPatterns(foldTrees(foldTree(x, fun), implicits), patterns) - case Pattern.Alternative(patterns) => foldPatterns(x, patterns) + case Pattern.Alternatives(patterns) => foldPatterns(x, patterns) case Pattern.TypeTest(tpt) => foldTypeTree(x, tpt) } @@ -131,7 +131,7 @@ trait TreeUtils } - abstract class TreeTraverser extends TreeAccumulator[Unit] { + abstract class TreeTraverser extends TreeAccumulator[Unit] { def traverseTree(tree: Tree)(implicit ctx: Context): Unit = traverseTreeChildren(tree) def traverseTypeTree(tree: TypeOrBoundsTree)(implicit ctx: Context): Unit = traverseTypeTreeChildren(tree) @@ -153,4 +153,171 @@ trait TreeUtils } + abstract class TreeMap { self => + + def transformTree(tree: Tree)(implicit ctx: Context): Tree = { + tree match { + case IsPackageClause(tree) => + PackageClause.copy(tree)(transformTerm(tree.pid).asInstanceOf[Term.Ref], transformTrees(tree.stats)(tree.symbol.localContext)) + case IsImport(tree) => + Import.copy(tree)(transformTerm(tree.expr), tree.selectors) + case IsStatement(tree) => + transformStatement(tree) + } + } + + def transformStatement(tree: Statement)(implicit ctx: Context): Statement = { + def localCtx(definition: Definition): Context = definition.symbol.localContext + tree match { + case IsTerm(tree) => + transformTerm(tree) + case IsValDef(tree) => + implicit val ctx = localCtx(tree) + val tpt1 = transformTypeTree(tree.tpt) + val rhs1 = tree.rhs.map(x => transformTerm(x)) + ValDef.copy(tree)(tree.name, tpt1, rhs1) + case IsDefDef(tree) => + implicit val ctx = localCtx(tree) + DefDef.copy(tree)(tree.name, transformSubTrees(tree.typeParams), tree.paramss mapConserve (transformSubTrees(_)), transformTypeTree(tree.returnTpt), tree.rhs.map(x => transformTerm(x))) + case IsTypeDef(tree) => + implicit val ctx = localCtx(tree) + TypeDef.copy(tree)(tree.name, transformTypeOrBoundsTree(tree.rhs)) + case IsClassDef(tree) => + ClassDef.copy(tree)(tree.name, tree.constructor, tree.parents, tree.self, tree.body) + case IsImport(tree) => + Import.copy(tree)(transformTerm(tree.expr), tree.selectors) + } + } + + def transformTerm(tree: Term)(implicit ctx: Context): Term = { + tree match { + case Term.Ident(name) => + tree + case Term.Select(qualifier, name) => + Term.Select.copy(tree)(transformTerm(qualifier), name) + case Term.This(qual) => + tree + case Term.Super(qual, mix) => + Term.Super.copy(tree)(transformTerm(qual), mix) + case Term.Apply(fun, args) => + Term.Apply.copy(tree)(transformTerm(fun), transformTerms(args)) + case Term.TypeApply(fun, args) => + Term.TypeApply.copy(tree)(transformTerm(fun), transformTypeTrees(args)) + case Term.Literal(const) => + tree + case Term.New(tpt) => + Term.New.copy(tree)(transformTypeTree(tpt)) + case Term.Typed(expr, tpt) => + Term.Typed.copy(tree)(transformTerm(expr), transformTypeTree(tpt)) + case Term.IsNamedArg(tree) => + Term.NamedArg.copy(tree)(tree.name, transformTerm(tree.value)) + case Term.Assign(lhs, rhs) => + Term.Assign.copy(tree)(transformTerm(lhs), transformTerm(rhs)) + case Term.Block(stats, expr) => + Term.Block.copy(tree)(transformStats(stats), transformTerm(expr)) + case Term.If(cond, thenp, elsep) => + Term.If.copy(tree)(transformTerm(cond), transformTerm(thenp), transformTerm(elsep)) + case Term.Lambda(meth, tpt) => + Term.Lambda.copy(tree)(transformTerm(meth), tpt.map(x => transformTypeTree(x))) + case Term.Match(selector, cases) => + Term.Match.copy(tree)(transformTerm(selector), transformCaseDefs(cases)) + case Term.Return(expr) => + Term.Return.copy(tree)(transformTerm(expr)) + case Term.While(cond, body) => + Term.While.copy(tree)(transformTerm(cond), transformTerm(body)) + case Term.Try(block, cases, finalizer) => + Term.Try.copy(tree)(transformTerm(block), transformCaseDefs(cases), finalizer.map(x => transformTerm(x))) + case Term.Repeated(elems, elemtpt) => + Term.Repeated.copy(tree)(transformTerms(elems), transformTypeTree(elemtpt)) + case Term.Inlined(call, bindings, expansion) => + Term.Inlined.copy(tree)(call, transformSubTrees(bindings), transformTerm(expansion)/*()call.symbol.localContext)*/) + } + } + + def transformTypeOrBoundsTree(tree: TypeOrBoundsTree)(implicit ctx: Context): TypeOrBoundsTree = tree match { + case IsTypeTree(tree) => transformTypeTree(tree) + case IsTypeBoundsTree(tree) => tree // TODO traverse tree + } + + def transformTypeTree(tree: TypeTree)(implicit ctx: Context): TypeTree = tree match { + case TypeTree.Inferred() => tree + case TypeTree.IsIdent(tree) => tree + case TypeTree.IsSelect(tree) => + TypeTree.Select.copy(tree)(tree.qualifier, tree.name) + case TypeTree.IsProjection(tree) => + TypeTree.Projection.copy(tree)(tree.qualifier, tree.name) + case TypeTree.IsAnnotated(tree) => + TypeTree.Annotated.copy(tree)(tree.arg, tree.annotation) + case TypeTree.IsSingleton(tree) => + TypeTree.Singleton.copy(tree)(transformTerm(tree.ref)) + case TypeTree.IsRefined(tree) => + TypeTree.Refined.copy(tree)(transformTypeTree(tree.tpt), transformTrees(tree.refinements).asInstanceOf[List[Definition]]) + case TypeTree.IsApplied(tree) => + TypeTree.Applied.copy(tree)(transformTypeTree(tree.tpt), transformTypeOrBoundsTrees(tree.args)) + case TypeTree.IsAnd(tree) => + TypeTree.And.copy(tree)(transformTypeTree(tree.left), transformTypeTree(tree.right)) + case TypeTree.IsOr(tree) => + TypeTree.Or.copy(tree)(transformTypeTree(tree.left), transformTypeTree(tree.right)) + case TypeTree.IsMatchType(tree) => + TypeTree.MatchType.copy(tree)(tree.bound.map(b => transformTypeTree(b)), transformTypeTree(tree.selector), transformTypeCaseDefs(tree.cases)) + case TypeTree.IsByName(tree) => + TypeTree.ByName.copy(tree)(transformTypeTree(tree.result)) + case TypeTree.IsLambdaTypeTree(tree) => + TypeTree.LambdaTypeTree.copy(tree)(transformSubTrees(tree.tparams), transformTypeOrBoundsTree(tree.body))(tree.symbol.localContext) + case TypeTree.IsTypeBind(tree) => + TypeTree.TypeBind.copy(tree)(tree.name, tree.body) + case TypeTree.IsTypeBlock(tree) => + TypeTree.TypeBlock.copy(tree)(tree.aliases, tree.tpt) + } + + def transformCaseDef(tree: CaseDef)(implicit ctx: Context): CaseDef = { + CaseDef.copy(tree)(transformPattern(tree.pattern), tree.guard.map(transformTerm), transformTerm(tree.rhs)) + } + + def transformTypeCaseDef(tree: TypeCaseDef)(implicit ctx: Context): TypeCaseDef = { + TypeCaseDef.copy(tree)(transformTypeTree(tree.pattern), transformTypeTree(tree.rhs)) + } + + def transformPattern(pattern: Pattern)(implicit ctx: Context): Pattern = pattern match { + case Pattern.Value(_) => + pattern + case Pattern.IsTypeTest(pattern) => + Pattern.TypeTest.copy(pattern)(transformTypeTree(pattern.tpt)) + case Pattern.IsUnapply(pattern) => + Pattern.Unapply.copy(pattern)(transformTerm(pattern.fun), transformSubTrees(pattern.implicits), transformPatterns(pattern.patterns)) + case Pattern.IsAlternatives(pattern) => + Pattern.Alternatives.copy(pattern)(transformPatterns(pattern.patterns)) + case Pattern.IsBind(pattern) => + Pattern.Bind.copy(pattern)(pattern.name, transformPattern(pattern.pattern)) + } + + def transformStats(trees: List[Statement])(implicit ctx: Context): List[Statement] = + trees mapConserve (transformStatement(_)) + + def transformTrees(trees: List[Tree])(implicit ctx: Context): List[Tree] = + trees mapConserve (transformTree(_)) + + def transformTerms(trees: List[Term])(implicit ctx: Context): List[Term] = + trees mapConserve (transformTerm(_)) + + def transformTypeTrees(trees: List[TypeTree])(implicit ctx: Context): List[TypeTree] = + trees mapConserve (transformTypeTree(_)) + + def transformTypeOrBoundsTrees(trees: List[TypeOrBoundsTree])(implicit ctx: Context): List[TypeOrBoundsTree] = + trees mapConserve (transformTypeOrBoundsTree(_)) + + def transformCaseDefs(trees: List[CaseDef])(implicit ctx: Context): List[CaseDef] = + trees mapConserve (transformCaseDef(_)) + + def transformTypeCaseDefs(trees: List[TypeCaseDef])(implicit ctx: Context): List[TypeCaseDef] = + trees mapConserve (transformTypeCaseDef(_)) + + def transformPatterns(trees: List[Pattern])(implicit ctx: Context): List[Pattern] = + trees mapConserve (transformPattern(_)) + + def transformSubTrees[Tr <: Tree](trees: List[Tr])(implicit ctx: Context): List[Tr] = + transformTrees(trees).asInstanceOf[List[Tr]] + + } + } diff --git a/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala b/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala index 54a9dd94377e..2d69c48a8929 100644 --- a/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala +++ b/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala @@ -9,7 +9,7 @@ trait TypeOrBoundsTreeOps extends Core { implicit def InferredDeco(x: TypeTree.Inferred): TypeTree.InferredAPI implicit def TypeIdentDeco(x: TypeTree.Ident): TypeTree.IdentAPI implicit def TypeSelectDeco(x: TypeTree.Select): TypeTree.SelectAPI - implicit def ProjectDeco(x: TypeTree.Project): TypeTree.ProjectAPI + implicit def ProjectionDeco(x: TypeTree.Projection): TypeTree.ProjectionAPI implicit def SingletonDeco(x: TypeTree.Singleton): TypeTree.SingletonAPI implicit def RefinedDeco(x: TypeTree.Refined): TypeTree.RefinedAPI implicit def AppliedDeco(x: TypeTree.Applied): TypeTree.AppliedAPI @@ -19,8 +19,8 @@ trait TypeOrBoundsTreeOps extends Core { implicit def MatchTypeTreeDeco(x: TypeTree.MatchType): TypeTree.MatchTypeAPI implicit def ByNameDeco(x: TypeTree.ByName): TypeTree.ByNameAPI implicit def LambdaTypeTreeDeco(x: TypeTree.LambdaTypeTree): TypeTree.LambdaTypeTreeAPI - implicit def BindDeco(x: TypeTree.Bind): TypeTree.BindAPI - implicit def TypeBlockDeco(x: TypeTree.Block): TypeTree.BlockAPI + implicit def TypeBindDeco(x: TypeTree.TypeBind): TypeTree.TypeBindAPI + implicit def TypeBlockDeco(x: TypeTree.TypeBlock): TypeTree.TypeBlockAPI implicit def TypeBoundsTreeDeco(tpt: TypeBoundsTree): TypeBoundsTreeAPI @@ -61,6 +61,7 @@ trait TypeOrBoundsTreeOps extends Core { /** TypeTree containing an inferred type */ val Inferred: InferredModule abstract class InferredModule { + def apply(tpe: Type)(implicit ctx: Context): Inferred /** Matches a TypeTree containing an inferred type */ def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Boolean } @@ -77,6 +78,8 @@ trait TypeOrBoundsTreeOps extends Core { val Ident: IdentModule abstract class IdentModule { + // TODO def apply(name: String)(implicit ctx: Context): Ident + def copy(original: Ident)(name: String)(implicit ctx: Context): Ident def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[String] } @@ -93,22 +96,26 @@ trait TypeOrBoundsTreeOps extends Core { val Select: SelectModule abstract class SelectModule { + def apply(qualifier: Term, name: String)(implicit ctx: Context): Select + def copy(original: Select)(qualifier: Term, name: String)(implicit ctx: Context): Select def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(Term, String)] } - val IsProject: IsProjectModule - abstract class IsProjectModule { - /** Matches any Project and returns it */ - def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Project] + val IsProjection: IsProjectionModule + abstract class IsProjectionModule { + /** Matches any Projection and returns it */ + def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Projection] } - trait ProjectAPI { + trait ProjectionAPI { def qualifier(implicit ctx: Context): TypeTree def name(implicit ctx: Context): String } - val Project: ProjectModule - abstract class ProjectModule { + val Projection: ProjectionModule + abstract class ProjectionModule { + // TODO def apply(qualifier: TypeTree, name: String)(implicit ctx: Context): Project + def copy(original: Projection)(qualifier: TypeTree, name: String)(implicit ctx: Context): Projection def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, String)] } @@ -124,6 +131,8 @@ trait TypeOrBoundsTreeOps extends Core { val Singleton: SingletonModule abstract class SingletonModule { + def apply(ref: Term)(implicit ctx: Context): Singleton + def copy(original: Singleton)(ref: Term)(implicit ctx: Context): Singleton def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[Term] } @@ -140,6 +149,8 @@ trait TypeOrBoundsTreeOps extends Core { val Refined: RefinedModule abstract class RefinedModule { + // TODO def apply(tpt: TypeTree, refinements: List[Definition])(implicit ctx: Context): Refined + def copy(original: Refined)(tpt: TypeTree, refinements: List[Definition])(implicit ctx: Context): Refined def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, List[Definition])] } @@ -156,6 +167,8 @@ trait TypeOrBoundsTreeOps extends Core { val Applied: AppliedModule abstract class AppliedModule { + def apply(tpt: TypeTree, args: List[TypeOrBoundsTree])(implicit ctx: Context): Applied + def copy(original: Applied)(tpt: TypeTree, args: List[TypeOrBoundsTree])(implicit ctx: Context): Applied def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])] } @@ -172,6 +185,8 @@ trait TypeOrBoundsTreeOps extends Core { val Annotated: AnnotatedModule abstract class AnnotatedModule { + def apply(arg: TypeTree, annotation: Term)(implicit ctx: Context): Annotated + def copy(original: Annotated)(arg: TypeTree, annotation: Term)(implicit ctx: Context): Annotated def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, Term)] } @@ -188,6 +203,8 @@ trait TypeOrBoundsTreeOps extends Core { val And: AndModule abstract class AndModule { + def apply(left: TypeTree, right: TypeTree)(implicit ctx: Context): And + def copy(original: And)(left: TypeTree, right: TypeTree)(implicit ctx: Context): And def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] } @@ -204,6 +221,8 @@ trait TypeOrBoundsTreeOps extends Core { val Or: OrModule abstract class OrModule { + def apply(left: TypeTree, right: TypeTree)(implicit ctx: Context): Or + def copy(original: Or)(left: TypeTree, right: TypeTree)(implicit ctx: Context): Or def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] } @@ -221,6 +240,8 @@ trait TypeOrBoundsTreeOps extends Core { val MatchType: MatchTypeModule abstract class MatchTypeModule { + def apply(bound: Option[TypeTree], selector: TypeTree, cases: List[TypeCaseDef])(implicit ctx: Context): MatchType + def copy(original: MatchType)(bound: Option[TypeTree], selector: TypeTree, cases: List[TypeCaseDef])(implicit ctx: Context): MatchType def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(Option[TypeTree], TypeTree, List[TypeCaseDef])] } @@ -236,6 +257,8 @@ trait TypeOrBoundsTreeOps extends Core { val ByName: ByNameModule abstract class ByNameModule { + def apply(result: TypeTree)(implicit ctx: Context): ByName + def copy(original: ByName)(result: TypeTree)(implicit ctx: Context): ByName def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree] } @@ -252,38 +275,44 @@ trait TypeOrBoundsTreeOps extends Core { val LambdaTypeTree: LambdaTypeTreeModule abstract class LambdaTypeTreeModule { + def apply(tparams: List[TypeDef], body: TypeOrBoundsTree)(implicit ctx: Context): LambdaTypeTree + def copy(original: LambdaTypeTree)(tparams: List[TypeDef], body: TypeOrBoundsTree)(implicit ctx: Context): LambdaTypeTree def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(List[TypeDef], TypeOrBoundsTree)] } - val IsBind: IsBindModule - abstract class IsBindModule { - /** Matches any Bind and returns it */ - def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Bind] + val IsTypeBind: IsTypeBindModule + abstract class IsTypeBindModule { + /** Matches any TypeBind and returns it */ + def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBind] } - trait BindAPI { + trait TypeBindAPI { def name(implicit ctx: Context): String def body(implicit ctx: Context): TypeOrBoundsTree } - val Bind: BindModule - abstract class BindModule { + val TypeBind: TypeBindModule + abstract class TypeBindModule { + // TODO def apply(name: String, tpt: TypeOrBoundsTree)(implicit ctx: Context): TypeBind + def copy(original: TypeBind)(name: String, tpt: TypeOrBoundsTree)(implicit ctx: Context): TypeBind def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree)] } - val IsBlock: IsBlockModule - abstract class IsBlockModule { - /** Matches any Block and returns it */ - def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[Block] + val IsTypeBlock: IsTypeBlockModule + abstract class IsTypeBlockModule { + /** Matches any TypeBlock and returns it */ + def unapply(tpt: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBlock] } - trait BlockAPI { + trait TypeBlockAPI { def aliases(implicit ctx: Context): List[TypeDef] def tpt(implicit ctx: Context): TypeTree } - val Block: BlockModule - abstract class BlockModule { + val TypeBlock: TypeBlockModule + abstract class TypeBlockModule { + def apply(aliases: List[TypeDef], tpt: TypeTree)(implicit ctx: Context): TypeBlock + def copy(original: TypeBlock)(aliases: List[TypeDef], tpt: TypeTree)(implicit ctx: Context): TypeBlock def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(List[TypeDef], TypeTree)] } } diff --git a/tests/run/f-interpolation-1/FQuote_1.scala b/tests/run/f-interpolation-1/FQuote_1.scala index 330e61643432..c428ecfe0c0d 100644 --- a/tests/run/f-interpolation-1/FQuote_1.scala +++ b/tests/run/f-interpolation-1/FQuote_1.scala @@ -33,7 +33,7 @@ object FQuote { // FQuote.SCOps(StringContext.apply([p0, ...]: String*) val parts = receiver.unseal.underlyingArgument match { - case Term.Apply(conv, List(Term.Apply(fun, List(Term.Typed(Term.Repeated(values), _))))) + case Term.Apply(conv, List(Term.Apply(fun, List(Term.Typed(Term.Repeated(values, _), _))))) if isSCOpsConversion(conv) && isStringContextApply(fun) && values.forall(isStringConstant) => @@ -43,7 +43,7 @@ object FQuote { } // [a0, ...]: Any* - val Term.Typed(Term.Repeated(allArgs), _) = args.unseal.underlyingArgument + val Term.Typed(Term.Repeated(allArgs, _), _) = args.unseal.underlyingArgument for ((arg, part) <- allArgs.zip(parts.tail)) { if (part.startsWith("%d") && !(arg.tpe <:< definitions.IntType)) { diff --git a/tests/run/i5119.check b/tests/run/i5119.check index a20911c6dc82..d290fd4fda6a 100644 --- a/tests/run/i5119.check +++ b/tests/run/i5119.check @@ -1,2 +1,2 @@ -Term.Select(Term.Typed(Term.Apply(Term.Select(Term.New(TypeTree.Ident("StringContextOps")), ""), List(Term.Apply(Term.Select(Term.Select(Term.Select(Term.Ident("_root_"), "scala"), "StringContext"), "apply"), List(Term.Typed(Term.Repeated(List(Term.Literal(Constant.String("Hello World ")), Term.Literal(Constant.String("!")))), TypeTree.Inferred()))))), TypeTree.Ident("StringContextOps")), "inline$sc") -Term.Typed(Term.Repeated(List(Term.Literal(Constant.Int(1)))), TypeTree.Inferred()) +Term.Select(Term.Typed(Term.Apply(Term.Select(Term.New(TypeTree.Ident("StringContextOps")), ""), List(Term.Apply(Term.Select(Term.Select(Term.Select(Term.Ident("_root_"), "scala"), "StringContext"), "apply"), List(Term.Typed(Term.Repeated(List(Term.Literal(Constant.String("Hello World ")), Term.Literal(Constant.String("!"))), TypeTree.Inferred()), TypeTree.Inferred()))))), TypeTree.Ident("StringContextOps")), "inline$sc") +Term.Typed(Term.Repeated(List(Term.Literal(Constant.Int(1))), TypeTree.Inferred()), TypeTree.Inferred()) diff --git a/tests/run/tasty-extractors-1.check b/tests/run/tasty-extractors-1.check index 4e96a239229d..b04fa977ed07 100644 --- a/tests/run/tasty-extractors-1.check +++ b/tests/run/tasty-extractors-1.check @@ -112,7 +112,7 @@ Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymb Term.Inlined(None, Nil, Term.Block(List(DefDef("f7", List(TypeDef("T", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred()))), List(List(ValDef("x", TypeTree.Ident("T"), None))), TypeTree.Singleton(Term.Ident("x")), Some(Term.Ident("x")))), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) -Term.Inlined(None, Nil, Term.Block(List(DefDef("f8", Nil, List(List(ValDef("i", TypeTree.Annotated(TypeTree.Applied(TypeTree.Inferred(), List(TypeTree.Ident("Int"))), Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None))), TypeTree.Ident("Int"), Some(Term.Literal(Constant.Int(9))))), Term.Apply(Term.Ident("f8"), List(Term.Typed(Term.Repeated(List(Term.Literal(Constant.Int(1)), Term.Literal(Constant.Int(2)), Term.Literal(Constant.Int(3)))), TypeTree.Inferred()))))) +Term.Inlined(None, Nil, Term.Block(List(DefDef("f8", Nil, List(List(ValDef("i", TypeTree.Annotated(TypeTree.Applied(TypeTree.Inferred(), List(TypeTree.Ident("Int"))), Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None))), TypeTree.Ident("Int"), Some(Term.Literal(Constant.Int(9))))), Term.Apply(Term.Ident("f8"), List(Term.Typed(Term.Repeated(List(Term.Literal(Constant.Int(1)), Term.Literal(Constant.Int(2)), Term.Literal(Constant.Int(3))), TypeTree.Inferred()), TypeTree.Inferred()))))) Type.SymRef(IsClassSymbol(), Type.SymRef(IsPackageSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(<>), NoPrefix())))) Term.Inlined(None, Nil, Term.Block(List(DefDef("f9", Nil, List(List(ValDef("i", TypeTree.ByName(TypeTree.Ident("Int")), None))), TypeTree.Ident("Int"), Some(Term.Ident("i")))), Term.Literal(Constant.Unit()))) diff --git a/tests/run/tasty-interpolation-1/Macro.scala b/tests/run/tasty-interpolation-1/Macro.scala index c7db2734098c..2846a1030642 100644 --- a/tests/run/tasty-interpolation-1/Macro.scala +++ b/tests/run/tasty-interpolation-1/Macro.scala @@ -56,7 +56,7 @@ abstract class MacroStringInterpolator[T] { protected def getStaticStringContext(strCtxExpr: Expr[StringContext])(implicit reflect: Reflection): StringContext = { import reflect._ strCtxExpr.unseal.underlyingArgument match { - case Term.Select(Term.Typed(Term.Apply(_, List(Term.Apply(_, List(Term.Typed(Term.Repeated(strCtxArgTrees), TypeTree.Inferred()))))), _), _) => + case Term.Select(Term.Typed(Term.Apply(_, List(Term.Apply(_, List(Term.Typed(Term.Repeated(strCtxArgTrees, _), TypeTree.Inferred()))))), _), _) => val strCtxArgs = strCtxArgTrees.map { case Term.Literal(Constant.String(str)) => str case tree => throw new NotStaticlyKnownError("Expected statically known StringContext", tree.seal[Any]) @@ -70,7 +70,7 @@ abstract class MacroStringInterpolator[T] { protected def getArgsList(argsExpr: Expr[Seq[Any]])(implicit reflect: Reflection): List[Expr[Any]] = { import reflect._ argsExpr.unseal.underlyingArgument match { - case Term.Typed(Term.Repeated(args), _) => args.map(_.seal[Any]) + case Term.Typed(Term.Repeated(args, _), _) => args.map(_.seal[Any]) case tree => throw new NotStaticlyKnownError("Expected statically known argument list", tree.seal[Any]) } } diff --git a/tests/run/tasty-tree-map.check b/tests/run/tasty-tree-map.check new file mode 100644 index 000000000000..d98791e22f0e --- /dev/null +++ b/tests/run/tasty-tree-map.check @@ -0,0 +1,35 @@ +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 diff --git a/tests/run/tasty-tree-map/quoted_1.scala b/tests/run/tasty-tree-map/quoted_1.scala new file mode 100644 index 000000000000..ceb98beb1343 --- /dev/null +++ b/tests/run/tasty-tree-map/quoted_1.scala @@ -0,0 +1,15 @@ +import scala.quoted._ +import scala.tasty._ + +object Macros { + + implicit inline def identityMaped[T](x: => T): T = ~impl('(x)) + + def impl[T: Type](x: Expr[T])(implicit reflection: Reflection): Expr[T] = { + import reflection._ + val identityMap = new TreeMap { } + val transformed = identityMap.transformTerm(x.unseal).seal[T] + transformed + } + +} diff --git a/tests/run/tasty-tree-map/quoted_2.scala b/tests/run/tasty-tree-map/quoted_2.scala new file mode 100644 index 000000000000..6c64a07adf3c --- /dev/null +++ b/tests/run/tasty-tree-map/quoted_2.scala @@ -0,0 +1,54 @@ + +import Macros._ + +class Annot extends scala.annotation.Annotation + +abstract class Foo { + type T + def y: T +} + +object Test { + + def main(args: Array[String]): Unit = { + println(identityMaped(32)) + println(identityMaped(32 + 1)) + println(identityMaped({ val i = 34; i })) + println(identityMaped({ var i = 34; i += 1; i })) + println(identityMaped({ var i = 0; while (i < 36) i += 1; i })) + println(identityMaped({ var i = 0; do i += 1 while (i < 37); i })) + println(identityMaped(try 38 finally ())) + println(identityMaped(try 39 catch { case _: Error => })) + println(identityMaped(new java.lang.Integer(40))) + println(identityMaped(if (true: Boolean) 41 else -1)) + println(identityMaped(true match { case _ => 42 } )) + println(identityMaped({ def f = 43; f })) + println(identityMaped({ def f() = 44; f() })) + println(identityMaped({ def f[T] = 45; f[Int] })) + println(identityMaped({ def f: Int = return 46; f })) + println(identityMaped({ def f(a: Int): Int = a; f(a = 47) })) + println(identityMaped({ def f(a: Int*): Int = a.sum; f(47, 1) })) + println(identityMaped(((a: Int) => a)(49))) + println(identityMaped({ type A = Int; 50: A })) + println(identityMaped({ import scala.{Int => I}; 51: I })) + println(identityMaped(52 match { case x => x })) + println(identityMaped(53 match { case x: Int => x })) + println(identityMaped((0: Any) match { case _: Int | _: Double => 54 })) + println(identityMaped(0 match { case I55(x) => x })) + println(identityMaped({ val x: scala.Int = 56; val y: x.type = x; y })) + println(identityMaped({ val x: scala.Int @Annot = 57; x })) + println(identityMaped({ val x: List[Int] = 58 :: Nil; x.head })) + println(identityMaped({ val x: Int & Any = 59; x })) + println(identityMaped({ val x: Int | Any = 60; x })) + println(identityMaped({ def f(x: => Int): Int = x; f(61) })) + println(identityMaped({ type T[X] = X; val x: T[Int] = 62; x })) + println(identityMaped({ type T[X] = X match { case Int => String; case String => Int }; val x: T[String] = 63; x })) + println(identityMaped((Nil: List[Int]) match { case _: List[t] => 64 })) + println(identityMaped({ object F { type T = Int }; val x: F.T = 65; x })) + println(identityMaped({ val x: Foo { type T = Int } = new Foo { type T = Int; def y: Int = 66 }; x.y })) + } + + object I55 { + def unapply(arg: Any): Some[Int] = Some(55) + } +} diff --git a/tests/run/xml-interpolation-1/XmlQuote_1.scala b/tests/run/xml-interpolation-1/XmlQuote_1.scala index c7bffe36a590..56c9a624ae20 100644 --- a/tests/run/xml-interpolation-1/XmlQuote_1.scala +++ b/tests/run/xml-interpolation-1/XmlQuote_1.scala @@ -46,7 +46,7 @@ object XmlQuote { // XmlQuote.SCOps(StringContext.apply([p0, ...]: String*) val parts = receiver.unseal.underlyingArgument match { - case Apply(conv, List(Apply(fun, List(Typed(Repeated(values), _))))) + case Apply(conv, List(Apply(fun, List(Typed(Repeated(values, _), _))))) if isSCOpsConversion(conv) && isStringContextApply(fun) && values.forall(isStringConstant) => @@ -56,7 +56,7 @@ object XmlQuote { } // [a0, ...]: Any* - val Typed(Repeated(args0), _) = args.unseal.underlyingArgument + val Typed(Repeated(args0, _), _) = args.unseal.underlyingArgument val string = parts.mkString("??") '(new Xml(~string.toExpr, ~liftListOfAny(args0))) diff --git a/tests/run/xml-interpolation-2/XmlQuote_1.scala b/tests/run/xml-interpolation-2/XmlQuote_1.scala index 39e51aa50ddf..c51f145f9642 100644 --- a/tests/run/xml-interpolation-2/XmlQuote_1.scala +++ b/tests/run/xml-interpolation-2/XmlQuote_1.scala @@ -42,7 +42,7 @@ object XmlQuote { val parts: List[String] = stripTyped(receiver.unseal.underlying) match { case Apply(conv, List(ctx1)) if isSCOpsConversion(conv) => ctx1 match { - case Apply(fun, List(Typed(Repeated(values), _))) if isStringContextApply(fun) => + case Apply(fun, List(Typed(Repeated(values, _), _))) if isStringContextApply(fun) => values.iterator.map { case Literal(Constant.String(value)) => value case _ => QuoteError("Expected statically known String") @@ -55,7 +55,7 @@ object XmlQuote { // [a0, ...]: Any* val args2: Expr[List[Any]] = args.unseal.underlyingArgument match { - case Typed(Repeated(args0), _) => // statically known args, make list directly + case Typed(Repeated(args0, _), _) => // statically known args, make list directly args0.map(_.seal[Any]).toExprOfList case _ => '((~args).toList)