From a59c06def0ea60e931b4a4dd321980f47c871d7f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 27 Oct 2017 18:36:11 +0200 Subject: [PATCH 1/3] Fall back to previous implementation scheme for MegaPhase The new implementation is essentially a slightly cleaned-up version of the old one from TreeTransformers, which seemed to performed better. The main difference (besides renaming things) is that prepare operations still return contexts instead of TreeTransforms. --- compiler/src/dotty/tools/dotc/Compiler.scala | 4 +- .../tools/dotc/transform/LambdaLift.scala | 1 + .../tools/dotc/transform/MegaPhase.scala | 1035 +++++++++++------ 3 files changed, 679 insertions(+), 361 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 09e0741c7524..e318332826f6 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -97,9 +97,9 @@ class Compiler { List(new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to their implementations new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here - new ElimStaticThis), // Replace `this` references to static objects by global identifiers + new ElimStaticThis), // Replace `this` references to static objects by global identifiers List(new Flatten, // Lift all inner classes to package scope - new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group + new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group new RenameLifted, // Renames lifted classes to local numbering scheme new TransformWildcards, // Replace wildcards with default values new MoveStatics, // Move static methods to companion classes diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index 5573b8e080ec..13f58b483658 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -491,6 +491,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => val phaseName: String = "lambdaLift" override def relaxedTypingInGroup = true + // Because it adds free vars as additional proxy parameters override def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set(classOf[Constructors], classOf[HoistSuperArgs]) // Constructors has to happen before LambdaLift because the lambda lift logic diff --git a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala index 4c24eb0c6144..ede670d74e9f 100644 --- a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala +++ b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala @@ -132,12 +132,6 @@ object MegaPhase { override def run(implicit ctx: Context): Unit = singletonGroup.run } - - private type Transformer[-T, R] = (T, Context) => R - private type IndexedTransformer[-T, R] = MiniPhase => Transformer[T, R] - - private val idNodeTransformer: Transformer[AnyRef, AnyRef] = (t, ctx) => t - private val idContextTransformer: Transformer[AnyRef, Context] = (t, ctx) => ctx } import MegaPhase._ @@ -162,166 +156,213 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { private val cpy: TypedTreeCopier = cpyBetweenPhases /** Transform node using all phases in this group that have idxInGroup >= start */ - def transformNode(tree: Tree, start: Int)(implicit ctx: Context) = - nodeTransformer(tree.tag)(start)(tree, ctx) + def transformNode(tree: Tree, start: Int)(implicit ctx: Context) = { + def goNamed(tree: Tree, start: Int) = tree match { + case tree: Ident => goIdent(tree, start) + case tree: Select => goSelect(tree, start) + case tree: ValDef => goValDef(tree, start) + case tree: DefDef => goDefDef(tree, start) + case tree: TypeDef => goTypeDef(tree, start) + case tree: Bind => goBind(tree, start) + case _ => goOther(tree, start) + } + def goUnnamed(tree: Tree, start: Int) = tree match { + case tree: Apply => goApply(tree, start) + case tree: TypeTree => goTypeTree(tree, start) + case tree: This => goThis(tree, start) + case tree: Literal => goLiteral(tree, start) + case tree: Block => goBlock(tree, start) + case tree: TypeApply => goTypeApply(tree, start) + case tree: If => goIf(tree, start) + case tree: New => goNew(tree, start) + case tree: Typed => goTyped(tree, start) + case tree: CaseDef => goCaseDef(tree, start) + case tree: Closure => goClosure(tree, start) + case tree: Assign => goAssign(tree, start) + case tree: SeqLiteral => goSeqLiteral(tree, start) + case tree: Super => goSuper(tree, start) + case tree: Template => goTemplate(tree, start) + case tree: Match => goMatch(tree, start) + case tree: UnApply => goUnApply(tree, start) + case tree: PackageDef => goPackageDef(tree, start) + case tree: Try => goTry(tree, start) + case tree: Inlined => goInlined(tree, start) + case tree: Return => goReturn(tree, start) + case tree: Alternative => goAlternative(tree, start) + case tree => goOther(tree, start) + } + if (tree.isInstanceOf[NameTree]) goNamed(tree, start) else goUnnamed(tree, start) + } /** Transform full tree using all phases in this group that have idxInGroup >= start */ def transformTree(tree: Tree, start: Int)(implicit ctx: Context): Tree = { - val tag = tree.tag - val nestedCtx = contextTransformer(tag)(start)(tree, ctx) - val transformer = nodeTransformer(tag)(start) - - def trans(tree: Tree)(implicit ctx: Context) = transformer(tree, ctx) - def localContext(implicit ctx: Context) = { val sym = tree.symbol val owner = if (sym is PackageVal) sym.moduleClass else sym ctx.fresh.setOwner(owner) } - { implicit val ctx = nestedCtx - (tag: @switch) match { - case Tag.Select => - val tree1 = tree.asInstanceOf[Select] - val qual = transformTree(tree1.qualifier, start) - trans(cpy.Select(tree1)(qual, tree1.name)) - case Tag.Super => - val tree1 = tree.asInstanceOf[Super] - val qual = transformTree(tree1.qual, start) - trans(cpy.Super(tree1)(qual, tree1.mix)) - case Tag.Apply => - val tree1 = tree.asInstanceOf[Apply] - val fun = transformTree(tree1.fun, start) - val args = transformTrees(tree1.args, start) - trans(cpy.Apply(tree1)(fun, args)) - case Tag.TypeApply => - val tree1 = tree.asInstanceOf[TypeApply] - val fun = transformTree(tree1.fun, start) - val args = transformTrees(tree1.args, start) - trans(cpy.TypeApply(tree1)(fun, args)) - case Tag.New => - val tree1 = tree.asInstanceOf[New] - val tpt = transformTree(tree1.tpt, start) - trans(cpy.New(tree1)(tpt)) - case Tag.Typed => - val tree1 = tree.asInstanceOf[Typed] - val expr = transformTree(tree1.expr, start) - val tpt = transformTree(tree1.tpt, start) - trans(cpy.Typed(tree1)(expr, tpt)) - case Tag.Assign => - val tree1 = tree.asInstanceOf[Assign] - val lhs = transformTree(tree1.lhs, start) - val rhs = transformTree(tree1.rhs, start) - trans(cpy.Assign(tree1)(lhs, rhs)) - case Tag.Block => - val tree1 = tree.asInstanceOf[Block] - val stats = transformStats(tree1.stats, ctx.owner, start) - val expr = transformTree(tree1.expr, start) - trans(cpy.Block(tree1)(stats, expr)) - case Tag.If => - val tree1 = tree.asInstanceOf[If] - val cond = transformTree(tree1.cond, start) - val thenp = transformTree(tree1.thenp, start) - val elsep = transformTree(tree1.elsep, start) - trans(cpy.If(tree1)(cond, thenp, elsep)) - case Tag.Closure => - val tree1 = tree.asInstanceOf[Closure] - val env = transformTrees(tree1.env, start) - val meth = transformTree(tree1.meth, start) - val tpt = transformTree(tree1.tpt, start) - trans(cpy.Closure(tree1)(env, meth, tpt)) - case Tag.Match => - val tree1 = tree.asInstanceOf[Match] - val selector = transformTree(tree1.selector, start) - val cases = transformSpecificTrees(tree1.cases, start) - trans(cpy.Match(tree1)(selector, cases)) - case Tag.CaseDef => - val tree1 = tree.asInstanceOf[CaseDef] - val pat = transformTree(tree1.pat, start)(ctx.addMode(Mode.Pattern)) - val guard = transformTree(tree1.guard, start) - val body = transformTree(tree1.body, start) - trans(cpy.CaseDef(tree1)(pat, guard, body)) - case Tag.Return => - val tree1 = tree.asInstanceOf[Return] - val expr = transformTree(tree1.expr, start) - trans(cpy.Return(tree1)(expr, tree1.from)) - // don't transform `tree1.from`, as this is not a normal ident, but - // a pointer to the enclosing method. - case Tag.Try => - val tree1 = tree.asInstanceOf[Try] - val expr = transformTree(tree1.expr, start) - val cases = transformSpecificTrees(tree1.cases, start) - val finalizer = transformTree(tree1.finalizer, start) - trans(cpy.Try(tree1)(expr, cases, finalizer)) - case Tag.SeqLiteral => - val tree1 = tree.asInstanceOf[SeqLiteral] - val elems = transformTrees(tree1.elems, start) - val elemtpt = transformTree(tree1.elemtpt, start) - trans(cpy.SeqLiteral(tree1)(elems, elemtpt)) - case Tag.Inlined => - val tree1 = tree.asInstanceOf[Inlined] - val bindings = transformSpecificTrees(tree1.bindings, start) - val expansion = transformTree(tree1.expansion, start) - trans(cpy.Inlined(tree1)(tree1.call, bindings, expansion)) - case Tag.Bind => - val tree1 = tree.asInstanceOf[Bind] - val body = transformTree(tree1.body, start) - trans(cpy.Bind(tree1)(tree1.name, body)) - case Tag.Alternative => - val tree1 = tree.asInstanceOf[Alternative] - val trees = transformTrees(tree1.trees, start) - trans(cpy.Alternative(tree1)(trees)) - case Tag.UnApply => - val tree1 = tree.asInstanceOf[UnApply] - val fun = transformTree(tree1.fun, start) - val implicits = transformTrees(tree1.implicits, start) - val patterns = transformTrees(tree1.patterns, start) - trans(cpy.UnApply(tree1)(fun, implicits, patterns)) - case Tag.ValDef => - val tree1 = tree.asInstanceOf[ValDef] - def mapValDef(implicit ctx: Context) = { - val tpt = transformTree(tree1.tpt, start) - val rhs = transformTree(tree1.rhs, start) - cpy.ValDef(tree1)(tree1.name, tpt, rhs) - } - if (tree1.isEmpty) tree1 - else trans(mapValDef(if (tree.symbol.exists) localContext else ctx)) - case Tag.DefDef => - val tree1 = tree.asInstanceOf[DefDef] - def mapDefDef(implicit ctx: Context) = { - val tparams = transformSpecificTrees(tree1.tparams, start) - val vparamss = tree1.vparamss.mapConserve(transformSpecificTrees(_, start)) - val tpt = transformTree(tree1.tpt, start) - val rhs = transformTree(tree1.rhs, start) - cpy.DefDef(tree1)(tree1.name, tparams, vparamss, tpt, rhs) - } - trans(mapDefDef(localContext)) - case Tag.TypeDef => - val tree1 = tree.asInstanceOf[TypeDef] - val rhs = transformTree(tree1.rhs, start)(localContext) - trans(cpy.TypeDef(tree1)(tree1.name, rhs)) - case Tag.Template => - val tree1 = tree.asInstanceOf[Template] - val constr = transformSpecificTree(tree1.constr, start) - val parents = transformTrees(tree1.parents, start)(ctx.superCallContext) - val self = transformSpecificTree(tree1.self, start) - val body = transformStats(tree1.body, tree1.symbol, start) - trans(cpy.Template(tree1)(constr, parents, self, body)) - case Tag.PackageDef => - val tree1 = tree.asInstanceOf[PackageDef] - def mapPackage(implicit ctx: Context) = { - val pid = transformSpecificTree(tree1.pid, start) - val stats = transformStats(tree1.stats, tree.symbol, start) - cpy.PackageDef(tree1)(pid, stats) - } - trans(mapPackage(localContext)) - case Tag.Thicket => - val tree1 = tree.asInstanceOf[Thicket] - cpy.Thicket(tree1)(transformTrees(tree1.trees, start)) - case _ => - trans(tree) - } + def transformNamed(tree: Tree, start: Int, outerCtx: Context): Tree = tree match { + case tree: Ident => + implicit val ctx = prepIdent(tree, start)(outerCtx) + goIdent(tree, start) + case tree: Select => + implicit val ctx = prepSelect(tree, start)(outerCtx) + val qual = transformTree(tree.qualifier, start) + goSelect(cpy.Select(tree)(qual, tree.name), start) + case tree: ValDef => + implicit val ctx = prepValDef(tree, start)(outerCtx) + def mapValDef(implicit ctx: Context) = { + val tpt = transformTree(tree.tpt, start) + val rhs = transformTree(tree.rhs, start) + cpy.ValDef(tree)(tree.name, tpt, rhs) + } + if (tree.isEmpty) tree + else goValDef(mapValDef(if (tree.symbol.exists) localContext else ctx), start) + case tree: DefDef => + implicit val ctx = prepDefDef(tree, start)(outerCtx) + def mapDefDef(implicit ctx: Context) = { + val tparams = transformSpecificTrees(tree.tparams, start) + val vparamss = tree.vparamss.mapConserve(transformSpecificTrees(_, start)) + val tpt = transformTree(tree.tpt, start) + val rhs = transformTree(tree.rhs, start) + cpy.DefDef(tree)(tree.name, tparams, vparamss, tpt, rhs) + } + goDefDef(mapDefDef(localContext), start) + case tree: TypeDef => + implicit val ctx = prepTypeDef(tree, start)(outerCtx) + val rhs = transformTree(tree.rhs, start)(localContext) + goTypeDef(cpy.TypeDef(tree)(tree.name, rhs), start) + case tree: Bind => + implicit val ctx = prepBind(tree, start)(outerCtx) + val body = transformTree(tree.body, start) + goBind(cpy.Bind(tree)(tree.name, body), start) + case _ => + implicit val ctx = prepOther(tree, start)(outerCtx) + goOther(tree, start) } + + def transformUnnamed(tree: Tree, start: Int, outerCtx: Context): Tree = tree match { + case tree: Apply => + implicit val ctx = prepApply(tree, start)(outerCtx) + val fun = transformTree(tree.fun, start) + val args = transformTrees(tree.args, start) + goApply(cpy.Apply(tree)(fun, args), start) + case tree: TypeTree => + implicit val ctx = prepTypeTree(tree, start)(outerCtx) + goTypeTree(tree, start) + case tree: Thicket => + cpy.Thicket(tree)(transformTrees(tree.trees, start)) + case tree: This => + implicit val ctx = prepThis(tree, start)(outerCtx) + goThis(tree, start) + case tree: Literal => + implicit val ctx = prepLiteral(tree, start)(outerCtx) + goLiteral(tree, start) + case tree: Block => + implicit val ctx = prepBlock(tree, start)(outerCtx) + val stats = transformStats(tree.stats, ctx.owner, start) + val expr = transformTree(tree.expr, start) + goBlock(cpy.Block(tree)(stats, expr), start) + case tree: TypeApply => + implicit val ctx = prepTypeApply(tree, start)(outerCtx) + val fun = transformTree(tree.fun, start) + val args = transformTrees(tree.args, start) + goTypeApply(cpy.TypeApply(tree)(fun, args), start) + case tree: If => + implicit val ctx = prepIf(tree, start)(outerCtx) + val cond = transformTree(tree.cond, start) + val thenp = transformTree(tree.thenp, start) + val elsep = transformTree(tree.elsep, start) + goIf(cpy.If(tree)(cond, thenp, elsep), start) + case tree: New => + implicit val ctx = prepNew(tree, start)(outerCtx) + val tpt = transformTree(tree.tpt, start) + goNew(cpy.New(tree)(tpt), start) + case tree: Typed => + implicit val ctx = prepTyped(tree, start)(outerCtx) + val expr = transformTree(tree.expr, start) + val tpt = transformTree(tree.tpt, start) + goTyped(cpy.Typed(tree)(expr, tpt), start) + case tree: CaseDef => + implicit val ctx = prepCaseDef(tree, start)(outerCtx) + val pat = transformTree(tree.pat, start)(ctx.addMode(Mode.Pattern)) + val guard = transformTree(tree.guard, start) + val body = transformTree(tree.body, start) + goCaseDef(cpy.CaseDef(tree)(pat, guard, body), start) + case tree: Closure => + implicit val ctx = prepClosure(tree, start)(outerCtx) + val env = transformTrees(tree.env, start) + val meth = transformTree(tree.meth, start) + val tpt = transformTree(tree.tpt, start) + goClosure(cpy.Closure(tree)(env, meth, tpt), start) + case tree: Assign => + implicit val ctx = prepAssign(tree, start)(outerCtx) + val lhs = transformTree(tree.lhs, start) + val rhs = transformTree(tree.rhs, start) + goAssign(cpy.Assign(tree)(lhs, rhs), start) + case tree: SeqLiteral => + implicit val ctx = prepSeqLiteral(tree, start)(outerCtx) + val elems = transformTrees(tree.elems, start) + val elemtpt = transformTree(tree.elemtpt, start) + goSeqLiteral(cpy.SeqLiteral(tree)(elems, elemtpt), start) + case tree: Super => + implicit val ctx = prepSuper(tree, start)(outerCtx) + goSuper(tree, start) + case tree: Template => + implicit val ctx = prepTemplate(tree, start)(outerCtx) + val constr = transformSpecificTree(tree.constr, start) + val parents = transformTrees(tree.parents, start)(ctx.superCallContext) + val self = transformSpecificTree(tree.self, start) + val body = transformStats(tree.body, tree.symbol, start) + goTemplate(cpy.Template(tree)(constr, parents, self, body), start) + case tree: Match => + implicit val ctx = prepMatch(tree, start)(outerCtx) + val selector = transformTree(tree.selector, start) + val cases = transformSpecificTrees(tree.cases, start) + goMatch(cpy.Match(tree)(selector, cases), start) + case tree: UnApply => + implicit val ctx = prepUnApply(tree, start)(outerCtx) + val fun = transformTree(tree.fun, start) + val implicits = transformTrees(tree.implicits, start) + val patterns = transformTrees(tree.patterns, start) + goUnApply(cpy.UnApply(tree)(fun, implicits, patterns), start) + case tree: PackageDef => + implicit val ctx = prepPackageDef(tree, start)(outerCtx) + def mapPackage(implicit ctx: Context) = { + val pid = transformSpecificTree(tree.pid, start) + val stats = transformStats(tree.stats, tree.symbol, start) + cpy.PackageDef(tree)(pid, stats) + } + goPackageDef(mapPackage(localContext), start) + case tree: Try => + implicit val ctx = prepTry(tree, start)(outerCtx) + val expr = transformTree(tree.expr, start) + val cases = transformSpecificTrees(tree.cases, start) + val finalizer = transformTree(tree.finalizer, start) + goTry(cpy.Try(tree)(expr, cases, finalizer), start) + case tree: Inlined => + implicit val ctx = prepInlined(tree, start)(outerCtx) + val bindings = transformSpecificTrees(tree.bindings, start) + val expansion = transformTree(tree.expansion, start) + goInlined(cpy.Inlined(tree)(tree.call, bindings, expansion), start) + case tree: Return => + implicit val ctx = prepReturn(tree, start)(outerCtx) + val expr = transformTree(tree.expr, start) + goReturn(cpy.Return(tree)(expr, tree.from), start) + // don't transform `tree.from`, as this is not a normal ident, but + // a pointer to the enclosing method. + case tree: Alternative => + implicit val ctx = prepAlternative(tree, start)(outerCtx) + val trees = transformTrees(tree.trees, start) + goAlternative(cpy.Alternative(tree)(trees), start) + case tree => + implicit val ctx = prepOther(tree, start)(outerCtx) + goOther(tree, start) + } + + if (tree.isInstanceOf[NameTree]) transformNamed(tree, start, ctx) + else transformUnnamed(tree, start, ctx) } def transformSpecificTree[T <: Tree](tree: T, start: Int)(implicit ctx: Context): T = @@ -333,15 +374,15 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { case Thicket(stats) => cpy.Thicket(stat)(stats.mapConserve(transformStat)) case _ => transformTree(stat, start)(ctx.exprContext(stat, exprOwner)) } - val nestedCtx = statsContextTransformer(start)(trees, ctx) - val newTrees = flatten(trees.mapConserve(transformStat(_)(nestedCtx))) - statsNodeTransformer(start)(newTrees, nestedCtx) + val nestedCtx = prepStats(trees, start)(ctx) + val trees1 = flatten(trees.mapConserve(transformStat(_)(nestedCtx))) + goStats(trees1, start)(nestedCtx) } def transformUnit(tree: Tree)(implicit ctx: Context) = { - val nestedCtx = unitContextTransformer(0)(tree, ctx) - val newTree = transformTree(tree, 0)(nestedCtx) - unitNodeTransformer(0)(newTree, nestedCtx) + val nestedCtx = prepUnit(tree, 0)(ctx) + val tree1 = transformTree(tree, 0)(nestedCtx) + goUnit(tree1, 0)(nestedCtx) } def transformTrees(trees: List[Tree], start: Int)(implicit ctx: Context): List[Tree] = @@ -354,7 +395,7 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { ctx.compilationUnit.tpdTree = transformUnit(ctx.compilationUnit.tpdTree)(ctx.withPhase(miniPhases.last.next)) - // The rest of this class is all made up by initialization code + // Initialization code for ((phase, idx) <- miniPhases.zipWithIndex) { phase.superPhase = this @@ -382,264 +423,540 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { hasRedefinedMethod(phase.getClass) } - /** A transformer array is an array of node or context transformers. It has - * one more element than there are miniphases. It is constructed as follows: - * - * - the last element is always `last`, which is the identity transformer - * that returns the context or tree unchanged. - * - The element corresponding to phase P is `elemFn(P)` if `P` defines a - * method with name `methName`, or it the same as the following element - * if `P` does not define `methName`. - */ - private def newTransformerArray[T, R]( - methName: String, elemFn: IndexedTransformer[T, R], last: Transformer[T, R]) = { - val trans = new Array[Transformer[T, R]](miniPhases.length + 1) - trans(miniPhases.length) = last + private def newNxArray = new Array[MiniPhase](miniPhases.length + 1) + private val emptyNxArray = newNxArray + + private def init(methName: String): Array[MiniPhase] = { + var nx: Array[MiniPhase] = emptyNxArray for (idx <- miniPhases.length - 1 to 0 by -1) { val subPhase = miniPhases(idx) - trans(idx) = if (defines(subPhase, methName)) elemFn(subPhase) else trans(idx + 1) - } - trans - } - - private def newContextTransformerArray[T](suffix: String, elemFn: IndexedTransformer[T, Context]) = - newTransformerArray[T, Context]("prepareFor" + suffix, elemFn, idContextTransformer.asInstanceOf[Transformer[T, Context]]) - - private def newNodeTransformerArray[T, R](suffix: String, elemFn: IndexedTransformer[T, R]) = - newTransformerArray[T, R]("transform" + suffix, elemFn, idNodeTransformer.asInstanceOf[Transformer[T, R]]) - - private val statsContextTransformer = newContextTransformerArray("Stats", prepForStats) - private val statsNodeTransformer = newNodeTransformerArray("Stats", transStats) - private val unitContextTransformer = newContextTransformerArray("Unit", prepForUnit) - private val unitNodeTransformer = newNodeTransformerArray("Unit", transUnit) - private val otherContextTransformer = newContextTransformerArray("Other", prepForOther) - private val otherNodeTransformer = newNodeTransformerArray("Other", transOther) - - private val contextTransformer: Array[Array[Transformer[Tree, Context]]] = - Array.fill(Tag.NumTags)(otherContextTransformer) - private val nodeTransformer: Array[Array[Transformer[Tree, Tree]]] = - Array.fill(Tag.NumTags)(otherNodeTransformer) - - // Dotty problem, replace T with _ in the line below, and you get an irreducible application errpr - private def init[T](name: String, tag: TreeTag, ctf: IndexedTransformer[T, Context], ntf: IndexedTransformer[T, Tree]): Unit = { - if (miniPhases.exists(defines(_, "prepareFor" + name))) - contextTransformer(tag) = newContextTransformerArray(name, ctf.asInstanceOf[IndexedTransformer[Tree, Context]]) - if (miniPhases.exists(defines(_, "transform" + name))) - nodeTransformer(tag) = newNodeTransformerArray(name, ntf.asInstanceOf[IndexedTransformer[Tree, Tree]]) + if (defines(subPhase, methName)) { + if (nx eq emptyNxArray) nx = newNxArray + nx(idx) = subPhase + } + else if (nx ne emptyNxArray) nx(idx) = nx(idx + 1) + } + nx } - init("Ident", Tag.Ident, prepForIdent, transIdent) - init("Select", Tag.Select, prepForSelect, transSelect) - init("This", Tag.This, prepForThis, transThis) - init("Super", Tag.Super, prepForSuper, transSuper) - init("Apply", Tag.Apply, prepForApply, transApply) - init("TypeApply", Tag.TypeApply, prepForTypeApply, transTypeApply) - init("Literal", Tag.Literal, prepForLiteral, transLiteral) - init("New", Tag.New, prepForNew, transNew) - init("Typed", Tag.Typed, prepForTyped, transTyped) - init("Assign", Tag.Assign, prepForAssign, transAssign) - init("Block", Tag.Block, prepForBlock, transBlock) - init("If", Tag.If, prepForIf, transIf) - init("Closure", Tag.Closure, prepForClosure, transClosure) - init("Match", Tag.Match, prepForMatch, transMatch) - init("CaseDef", Tag.CaseDef, prepForCaseDef, transCaseDef) - init("Return", Tag.Return, prepForReturn, transReturn) - init("Try", Tag.Try, prepForTry, transTry) - init("SeqLiteral", Tag.SeqLiteral, prepForSeqLiteral, transSeqLiteral) - init("Inlined", Tag.Inlined, prepForInlined, transInlined) - init("TypeTree", Tag.TypeTree, prepForTypeTree, transTypeTree) - init("Bind", Tag.Bind, prepForBind, transBind) - init("Alternative", Tag.Alternative, prepForAlternative, transAlternative) - init("UnApply", Tag.UnApply, prepForUnApply, transUnApply) - init("ValDef", Tag.ValDef, prepForValDef, transValDef) - init("DefDef", Tag.DefDef, prepForDefDef, transDefDef) - init("TypeDef", Tag.TypeDef, prepForTypeDef, transTypeDef) - init("Template", Tag.Template, prepForTemplate, transTemplate) - init("PackageDef", Tag.PackageDef, prepForPackageDef, transPackageDef) - - private def prepForIdent(phase: MiniPhase): Transformer[Ident, Context] = - (tree, ctx) => contextTransformer(Tag.Ident)(phase.idxInGroup + 1)(tree, phase.prepareForIdent(tree)(ctx)) + private val nxIdentPrepPhase = init("prepareForIdent") + private val nxIdentTransPhase = init("transformIdent") + private val nxSelectPrepPhase = init("prepareForSelect") + private val nxSelectTransPhase = init("transformSelect") + private val nxThisPrepPhase = init("prepareForThis") + private val nxThisTransPhase = init("transformThis") + private val nxSuperPrepPhase = init("prepareForSuper") + private val nxSuperTransPhase = init("transformSuper") + private val nxApplyPrepPhase = init("prepareForApply") + private val nxApplyTransPhase = init("transformApply") + private val nxTypeApplyPrepPhase = init("prepareForTypeApply") + private val nxTypeApplyTransPhase = init("transformTypeApply") + private val nxLiteralPrepPhase = init("prepareForLiteral") + private val nxLiteralTransPhase = init("transformLiteral") + private val nxNewPrepPhase = init("prepareForNew") + private val nxNewTransPhase = init("transformNew") + private val nxTypedPrepPhase = init("prepareForTyped") + private val nxTypedTransPhase = init("transformTyped") + private val nxAssignPrepPhase = init("prepareForAssign") + private val nxAssignTransPhase = init("transformAssign") + private val nxBlockPrepPhase = init("prepareForBlock") + private val nxBlockTransPhase = init("transformBlock") + private val nxIfPrepPhase = init("prepareForIf") + private val nxIfTransPhase = init("transformIf") + private val nxClosurePrepPhase = init("prepareForClosure") + private val nxClosureTransPhase = init("transformClosure") + private val nxMatchPrepPhase = init("prepareForMatch") + private val nxMatchTransPhase = init("transformMatch") + private val nxCaseDefPrepPhase = init("prepareForCaseDef") + private val nxCaseDefTransPhase = init("transformCaseDef") + private val nxReturnPrepPhase = init("prepareForReturn") + private val nxReturnTransPhase = init("transformReturn") + private val nxTryPrepPhase = init("prepareForTry") + private val nxTryTransPhase = init("transformTry") + private val nxSeqLiteralPrepPhase = init("prepareForSeqLiteral") + private val nxSeqLiteralTransPhase = init("transformSeqLiteral") + private val nxInlinedPrepPhase = init("prepareForInlined") + private val nxInlinedTransPhase = init("transformInlined") + private val nxTypeTreePrepPhase = init("prepareForTypeTree") + private val nxTypeTreeTransPhase = init("transformTypeTree") + private val nxBindPrepPhase = init("prepareForBind") + private val nxBindTransPhase = init("transformBind") + private val nxAlternativePrepPhase = init("prepareForAlternative") + private val nxAlternativeTransPhase = init("transformAlternative") + private val nxUnApplyPrepPhase = init("prepareForUnApply") + private val nxUnApplyTransPhase = init("transformUnApply") + private val nxValDefPrepPhase = init("prepareForValDef") + private val nxValDefTransPhase = init("transformValDef") + private val nxDefDefPrepPhase = init("prepareForDefDef") + private val nxDefDefTransPhase = init("transformDefDef") + private val nxTypeDefPrepPhase = init("prepareForTypeDef") + private val nxTypeDefTransPhase = init("transformTypeDef") + private val nxTemplatePrepPhase = init("prepareForTemplate") + private val nxTemplateTransPhase = init("transformTemplate") + private val nxPackageDefPrepPhase = init("prepareForPackageDef") + private val nxPackageDefTransPhase = init("transformPackageDef") + private val nxStatsPrepPhase = init("prepareForStats") + private val nxStatsTransPhase = init("transformStats") + private val nxUnitPrepPhase = init("prepareForUnit") + private val nxUnitTransPhase = init("transformUnit") + private val nxOtherPrepPhase = init("prepareForOther") + private val nxOtherTransPhase = init("transformOther") + + // Boilerplate snippets + + def prepIdent(tree: Ident, start: Int)(implicit ctx: Context): Context = { + val phase = nxIdentPrepPhase(start) + if (phase == null) ctx + else prepIdent(tree, phase.idxInGroup + 1)(phase.prepareForIdent(tree)) + } - private def prepForSelect(phase: MiniPhase): Transformer[Select, Context] = - (tree, ctx) => contextTransformer(Tag.Select)(phase.idxInGroup + 1)(tree, phase.prepareForSelect(tree)(ctx)) + def goIdent(tree: Ident, start: Int)(implicit ctx: Context): Tree = { + val phase = nxIdentTransPhase(start) + if (phase == null) tree + else phase.transformIdent(tree)(ctx) match { + case tree1: Ident => goIdent(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForThis(phase: MiniPhase): Transformer[This, Context] = - (tree, ctx) => contextTransformer(Tag.This)(phase.idxInGroup + 1)(tree, phase.prepareForThis(tree)(ctx)) + def prepSelect(tree: Select, start: Int)(implicit ctx: Context): Context = { + val phase = nxSelectPrepPhase(start) + if (phase == null) ctx + else prepSelect(tree, phase.idxInGroup + 1)(phase.prepareForSelect(tree)) + } - private def prepForSuper(phase: MiniPhase): Transformer[Super, Context] = - (tree, ctx) => contextTransformer(Tag.Super)(phase.idxInGroup + 1)(tree, phase.prepareForSuper(tree)(ctx)) + def goSelect(tree: Select, start: Int)(implicit ctx: Context): Tree = { + val phase = nxSelectTransPhase(start) + if (phase == null) tree + else phase.transformSelect(tree)(ctx) match { + case tree1: Select => goSelect(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForApply(phase: MiniPhase): Transformer[Apply, Context] = - (tree, ctx) => contextTransformer(Tag.Apply)(phase.idxInGroup + 1)(tree, phase.prepareForApply(tree)(ctx)) + def prepThis(tree: This, start: Int)(implicit ctx: Context): Context = { + val phase = nxThisPrepPhase(start) + if (phase == null) ctx + else prepThis(tree, phase.idxInGroup + 1)(phase.prepareForThis(tree)) + } - private def prepForTypeApply(phase: MiniPhase): Transformer[TypeApply, Context] = - (tree, ctx) => contextTransformer(Tag.TypeApply)(phase.idxInGroup + 1)(tree, phase.prepareForTypeApply(tree)(ctx)) + def goThis(tree: This, start: Int)(implicit ctx: Context): Tree = { + val phase = nxThisTransPhase(start) + if (phase == null) tree + else phase.transformThis(tree)(ctx) match { + case tree1: This => goThis(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForLiteral(phase: MiniPhase): Transformer[Literal, Context] = - (tree, ctx) => contextTransformer(Tag.Literal)(phase.idxInGroup + 1)(tree, phase.prepareForLiteral(tree)(ctx)) + def prepSuper(tree: Super, start: Int)(implicit ctx: Context): Context = { + val phase = nxSuperPrepPhase(start) + if (phase == null) ctx + else prepSuper(tree, phase.idxInGroup + 1)(phase.prepareForSuper(tree)) + } - private def prepForNew(phase: MiniPhase): Transformer[New, Context] = - (tree, ctx) => contextTransformer(Tag.New)(phase.idxInGroup + 1)(tree, phase.prepareForNew(tree)(ctx)) + def goSuper(tree: Super, start: Int)(implicit ctx: Context): Tree = { + val phase = nxSuperTransPhase(start) + if (phase == null) tree + else phase.transformSuper(tree)(ctx) match { + case tree1: Super => goSuper(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForTyped(phase: MiniPhase): Transformer[Typed, Context] = - (tree, ctx) => contextTransformer(Tag.Typed)(phase.idxInGroup + 1)(tree, phase.prepareForTyped(tree)(ctx)) + def prepApply(tree: Apply, start: Int)(implicit ctx: Context): Context = { + val phase = nxApplyPrepPhase(start) + if (phase == null) ctx + else prepApply(tree, phase.idxInGroup + 1)(phase.prepareForApply(tree)) + } - private def prepForAssign(phase: MiniPhase): Transformer[Assign, Context] = - (tree, ctx) => contextTransformer(Tag.Assign)(phase.idxInGroup + 1)(tree, phase.prepareForAssign(tree)(ctx)) + def goApply(tree: Apply, start: Int)(implicit ctx: Context): Tree = { + val phase = nxApplyTransPhase(start) + if (phase == null) tree + else phase.transformApply(tree)(ctx) match { + case tree1: Apply => goApply(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForBlock(phase: MiniPhase): Transformer[Block, Context] = - (tree, ctx) => contextTransformer(Tag.Block)(phase.idxInGroup + 1)(tree, phase.prepareForBlock(tree)(ctx)) + def prepTypeApply(tree: TypeApply, start: Int)(implicit ctx: Context): Context = { + val phase = nxTypeApplyPrepPhase(start) + if (phase == null) ctx + else prepTypeApply(tree, phase.idxInGroup + 1)(phase.prepareForTypeApply(tree)) + } - private def prepForIf(phase: MiniPhase): Transformer[If, Context] = - (tree, ctx) => contextTransformer(Tag.If)(phase.idxInGroup + 1)(tree, phase.prepareForIf(tree)(ctx)) + def goTypeApply(tree: TypeApply, start: Int)(implicit ctx: Context): Tree = { + val phase = nxTypeApplyTransPhase(start) + if (phase == null) tree + else phase.transformTypeApply(tree)(ctx) match { + case tree1: TypeApply => goTypeApply(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForClosure(phase: MiniPhase): Transformer[Closure, Context] = - (tree, ctx) => contextTransformer(Tag.Closure)(phase.idxInGroup + 1)(tree, phase.prepareForClosure(tree)(ctx)) + def prepLiteral(tree: Literal, start: Int)(implicit ctx: Context): Context = { + val phase = nxLiteralPrepPhase(start) + if (phase == null) ctx + else prepLiteral(tree, phase.idxInGroup + 1)(phase.prepareForLiteral(tree)) + } - private def prepForMatch(phase: MiniPhase): Transformer[Match, Context] = - (tree, ctx) => contextTransformer(Tag.Match)(phase.idxInGroup + 1)(tree, phase.prepareForMatch(tree)(ctx)) + def goLiteral(tree: Literal, start: Int)(implicit ctx: Context): Tree = { + val phase = nxLiteralTransPhase(start) + if (phase == null) tree + else phase.transformLiteral(tree)(ctx) match { + case tree1: Literal => goLiteral(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForCaseDef(phase: MiniPhase): Transformer[CaseDef, Context] = - (tree, ctx) => contextTransformer(Tag.CaseDef)(phase.idxInGroup + 1)(tree, phase.prepareForCaseDef(tree)(ctx)) + def prepNew(tree: New, start: Int)(implicit ctx: Context): Context = { + val phase = nxNewPrepPhase(start) + if (phase == null) ctx + else prepNew(tree, phase.idxInGroup + 1)(phase.prepareForNew(tree)) + } - private def prepForReturn(phase: MiniPhase): Transformer[Return, Context] = - (tree, ctx) => contextTransformer(Tag.Return)(phase.idxInGroup + 1)(tree, phase.prepareForReturn(tree)(ctx)) + def goNew(tree: New, start: Int)(implicit ctx: Context): Tree = { + val phase = nxNewTransPhase(start) + if (phase == null) tree + else phase.transformNew(tree)(ctx) match { + case tree1: New => goNew(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForTry(phase: MiniPhase): Transformer[Try, Context] = - (tree, ctx) => contextTransformer(Tag.Try)(phase.idxInGroup + 1)(tree, phase.prepareForTry(tree)(ctx)) + def prepTyped(tree: Typed, start: Int)(implicit ctx: Context): Context = { + val phase = nxTypedPrepPhase(start) + if (phase == null) ctx + else prepTyped(tree, phase.idxInGroup + 1)(phase.prepareForTyped(tree)) + } - private def prepForSeqLiteral(phase: MiniPhase): Transformer[SeqLiteral, Context] = - (tree, ctx) => contextTransformer(Tag.SeqLiteral)(phase.idxInGroup + 1)(tree, phase.prepareForSeqLiteral(tree)(ctx)) + def goTyped(tree: Typed, start: Int)(implicit ctx: Context): Tree = { + val phase = nxTypedTransPhase(start) + if (phase == null) tree + else phase.transformTyped(tree)(ctx) match { + case tree1: Typed => goTyped(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForInlined(phase: MiniPhase): Transformer[Inlined, Context] = - (tree, ctx) => contextTransformer(Tag.Inlined)(phase.idxInGroup + 1)(tree, phase.prepareForInlined(tree)(ctx)) + def prepAssign(tree: Assign, start: Int)(implicit ctx: Context): Context = { + val phase = nxAssignPrepPhase(start) + if (phase == null) ctx + else prepAssign(tree, phase.idxInGroup + 1)(phase.prepareForAssign(tree)) + } - private def prepForTypeTree(phase: MiniPhase): Transformer[TypeTree, Context] = - (tree, ctx) => contextTransformer(Tag.TypeTree)(phase.idxInGroup + 1)(tree, phase.prepareForTypeTree(tree)(ctx)) + def goAssign(tree: Assign, start: Int)(implicit ctx: Context): Tree = { + val phase = nxAssignTransPhase(start) + if (phase == null) tree + else phase.transformAssign(tree)(ctx) match { + case tree1: Assign => goAssign(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForBind(phase: MiniPhase): Transformer[Bind, Context] = - (tree, ctx) => contextTransformer(Tag.Bind)(phase.idxInGroup + 1)(tree, phase.prepareForBind(tree)(ctx)) + def prepBlock(tree: Block, start: Int)(implicit ctx: Context): Context = { + val phase = nxBlockPrepPhase(start) + if (phase == null) ctx + else prepBlock(tree, phase.idxInGroup + 1)(phase.prepareForBlock(tree)) + } - private def prepForAlternative(phase: MiniPhase): Transformer[Alternative, Context] = - (tree, ctx) => contextTransformer(Tag.Alternative)(phase.idxInGroup + 1)(tree, phase.prepareForAlternative(tree)(ctx)) + def goBlock(tree: Block, start: Int)(implicit ctx: Context): Tree = { + val phase = nxBlockTransPhase(start) + if (phase == null) tree + else phase.transformBlock(tree)(ctx) match { + case tree1: Block => goBlock(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForUnApply(phase: MiniPhase): Transformer[UnApply, Context] = - (tree, ctx) => contextTransformer(Tag.UnApply)(phase.idxInGroup + 1)(tree, phase.prepareForUnApply(tree)(ctx)) + def prepIf(tree: If, start: Int)(implicit ctx: Context): Context = { + val phase = nxIfPrepPhase(start) + if (phase == null) ctx + else prepIf(tree, phase.idxInGroup + 1)(phase.prepareForIf(tree)) + } - private def prepForValDef(phase: MiniPhase): Transformer[ValDef, Context] = - (tree, ctx) => contextTransformer(Tag.ValDef)(phase.idxInGroup + 1)(tree, phase.prepareForValDef(tree)(ctx)) + def goIf(tree: If, start: Int)(implicit ctx: Context): Tree = { + val phase = nxIfTransPhase(start) + if (phase == null) tree + else phase.transformIf(tree)(ctx) match { + case tree1: If => goIf(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForDefDef(phase: MiniPhase): Transformer[DefDef, Context] = - (tree, ctx) => contextTransformer(Tag.DefDef)(phase.idxInGroup + 1)(tree, phase.prepareForDefDef(tree)(ctx)) + def prepClosure(tree: Closure, start: Int)(implicit ctx: Context): Context = { + val phase = nxClosurePrepPhase(start) + if (phase == null) ctx + else prepClosure(tree, phase.idxInGroup + 1)(phase.prepareForClosure(tree)) + } - private def prepForTypeDef(phase: MiniPhase): Transformer[TypeDef, Context] = - (tree, ctx) => contextTransformer(Tag.TypeDef)(phase.idxInGroup + 1)(tree, phase.prepareForTypeDef(tree)(ctx)) + def goClosure(tree: Closure, start: Int)(implicit ctx: Context): Tree = { + val phase = nxClosureTransPhase(start) + if (phase == null) tree + else phase.transformClosure(tree)(ctx) match { + case tree1: Closure => goClosure(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForTemplate(phase: MiniPhase): Transformer[Template, Context] = - (tree, ctx) => contextTransformer(Tag.Template)(phase.idxInGroup + 1)(tree, phase.prepareForTemplate(tree)(ctx)) + def prepMatch(tree: Match, start: Int)(implicit ctx: Context): Context = { + val phase = nxMatchPrepPhase(start) + if (phase == null) ctx + else prepMatch(tree, phase.idxInGroup + 1)(phase.prepareForMatch(tree)) + } - private def prepForPackageDef(phase: MiniPhase): Transformer[PackageDef, Context] = - (tree, ctx) => contextTransformer(Tag.PackageDef)(phase.idxInGroup + 1)(tree, phase.prepareForPackageDef(tree)(ctx)) + def goMatch(tree: Match, start: Int)(implicit ctx: Context): Tree = { + val phase = nxMatchTransPhase(start) + if (phase == null) tree + else phase.transformMatch(tree)(ctx) match { + case tree1: Match => goMatch(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForStats(phase: MiniPhase): Transformer[List[Tree], Context] = - (trees, ctx) => statsContextTransformer(phase.idxInGroup + 1)(trees, phase.prepareForStats(trees)(ctx)) + def prepCaseDef(tree: CaseDef, start: Int)(implicit ctx: Context): Context = { + val phase = nxCaseDefPrepPhase(start) + if (phase == null) ctx + else prepCaseDef(tree, phase.idxInGroup + 1)(phase.prepareForCaseDef(tree)) + } - private def prepForUnit(phase: MiniPhase): Transformer[Tree, Context] = - (tree, ctx) => unitContextTransformer(phase.idxInGroup + 1)(tree, phase.prepareForUnit(tree)(ctx)) + def goCaseDef(tree: CaseDef, start: Int)(implicit ctx: Context): Tree = { + val phase = nxCaseDefTransPhase(start) + if (phase == null) tree + else phase.transformCaseDef(tree)(ctx) match { + case tree1: CaseDef => goCaseDef(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def prepForOther(phase: MiniPhase): Transformer[Tree, Context] = - (tree, ctx) => otherContextTransformer(phase.idxInGroup + 1)(tree, phase.prepareForOther(tree)(ctx)) + def prepReturn(tree: Return, start: Int)(implicit ctx: Context): Context = { + val phase = nxReturnPrepPhase(start) + if (phase == null) ctx + else prepReturn(tree, phase.idxInGroup + 1)(phase.prepareForReturn(tree)) + } - private def transIdent(phase: MiniPhase): Transformer[Ident, Tree] = - (tree, ctx) => transformNode(phase.transformIdent(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goReturn(tree: Return, start: Int)(implicit ctx: Context): Tree = { + val phase = nxReturnTransPhase(start) + if (phase == null) tree + else phase.transformReturn(tree)(ctx) match { + case tree1: Return => goReturn(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transSelect(phase: MiniPhase): Transformer[Select, Tree] = - (tree, ctx) => transformNode(phase.transformSelect(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepTry(tree: Try, start: Int)(implicit ctx: Context): Context = { + val phase = nxTryPrepPhase(start) + if (phase == null) ctx + else prepTry(tree, phase.idxInGroup + 1)(phase.prepareForTry(tree)) + } - private def transThis(phase: MiniPhase): Transformer[This, Tree] = - (tree, ctx) => transformNode(phase.transformThis(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goTry(tree: Try, start: Int)(implicit ctx: Context): Tree = { + val phase = nxTryTransPhase(start) + if (phase == null) tree + else phase.transformTry(tree)(ctx) match { + case tree1: Try => goTry(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transSuper(phase: MiniPhase): Transformer[Super, Tree] = - (tree, ctx) => transformNode(phase.transformSuper(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepSeqLiteral(tree: SeqLiteral, start: Int)(implicit ctx: Context): Context = { + val phase = nxSeqLiteralPrepPhase(start) + if (phase == null) ctx + else prepSeqLiteral(tree, phase.idxInGroup + 1)(phase.prepareForSeqLiteral(tree)) + } - private def transApply(phase: MiniPhase): Transformer[Apply, Tree] = - (tree, ctx) => transformNode(phase.transformApply(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goSeqLiteral(tree: SeqLiteral, start: Int)(implicit ctx: Context): Tree = { + val phase = nxSeqLiteralTransPhase(start) + if (phase == null) tree + else phase.transformSeqLiteral(tree)(ctx) match { + case tree1: SeqLiteral => goSeqLiteral(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transTypeApply(phase: MiniPhase): Transformer[TypeApply, Tree] = - (tree, ctx) => transformNode(phase.transformTypeApply(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepInlined(tree: Inlined, start: Int)(implicit ctx: Context): Context = { + val phase = nxInlinedPrepPhase(start) + if (phase == null) ctx + else prepInlined(tree, phase.idxInGroup + 1)(phase.prepareForInlined(tree)) + } - private def transLiteral(phase: MiniPhase): Transformer[Literal, Tree] = - (tree, ctx) => transformNode(phase.transformLiteral(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goInlined(tree: Inlined, start: Int)(implicit ctx: Context): Tree = { + val phase = nxInlinedTransPhase(start) + if (phase == null) tree + else phase.transformInlined(tree)(ctx) match { + case tree1: Inlined => goInlined(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transNew(phase: MiniPhase): Transformer[New, Tree] = - (tree, ctx) => transformNode(phase.transformNew(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepTypeTree(tree: TypeTree, start: Int)(implicit ctx: Context): Context = { + val phase = nxTypeTreePrepPhase(start) + if (phase == null) ctx + else prepTypeTree(tree, phase.idxInGroup + 1)(phase.prepareForTypeTree(tree)) + } - private def transTyped(phase: MiniPhase): Transformer[Typed, Tree] = - (tree, ctx) => transformNode(phase.transformTyped(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goTypeTree(tree: TypeTree, start: Int)(implicit ctx: Context): Tree = { + val phase = nxTypeTreeTransPhase(start) + if (phase == null) tree + else phase.transformTypeTree(tree)(ctx) match { + case tree1: TypeTree => goTypeTree(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transAssign(phase: MiniPhase): Transformer[Assign, Tree] = - (tree, ctx) => transformNode(phase.transformAssign(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepBind(tree: Bind, start: Int)(implicit ctx: Context): Context = { + val phase = nxBindPrepPhase(start) + if (phase == null) ctx + else prepBind(tree, phase.idxInGroup + 1)(phase.prepareForBind(tree)) + } - private def transBlock(phase: MiniPhase): Transformer[Block, Tree] = - (tree, ctx) => transformNode(phase.transformBlock(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goBind(tree: Bind, start: Int)(implicit ctx: Context): Tree = { + val phase = nxBindTransPhase(start) + if (phase == null) tree + else phase.transformBind(tree)(ctx) match { + case tree1: Bind => goBind(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transIf(phase: MiniPhase): Transformer[If, Tree] = - (tree, ctx) => transformNode(phase.transformIf(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepAlternative(tree: Alternative, start: Int)(implicit ctx: Context): Context = { + val phase = nxAlternativePrepPhase(start) + if (phase == null) ctx + else prepAlternative(tree, phase.idxInGroup + 1)(phase.prepareForAlternative(tree)) + } - private def transClosure(phase: MiniPhase): Transformer[Closure, Tree] = - (tree, ctx) => transformNode(phase.transformClosure(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goAlternative(tree: Alternative, start: Int)(implicit ctx: Context): Tree = { + val phase = nxAlternativeTransPhase(start) + if (phase == null) tree + else phase.transformAlternative(tree)(ctx) match { + case tree1: Alternative => goAlternative(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transMatch(phase: MiniPhase): Transformer[Match, Tree] = - (tree, ctx) => transformNode(phase.transformMatch(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepUnApply(tree: UnApply, start: Int)(implicit ctx: Context): Context = { + val phase = nxUnApplyPrepPhase(start) + if (phase == null) ctx + else prepUnApply(tree, phase.idxInGroup + 1)(phase.prepareForUnApply(tree)) + } - private def transCaseDef(phase: MiniPhase): Transformer[CaseDef, Tree] = - (tree, ctx) => transformNode(phase.transformCaseDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goUnApply(tree: UnApply, start: Int)(implicit ctx: Context): Tree = { + val phase = nxUnApplyTransPhase(start) + if (phase == null) tree + else phase.transformUnApply(tree)(ctx) match { + case tree1: UnApply => goUnApply(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transReturn(phase: MiniPhase): Transformer[Return, Tree] = - (tree, ctx) => transformNode(phase.transformReturn(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepValDef(tree: ValDef, start: Int)(implicit ctx: Context): Context = { + val phase = nxValDefPrepPhase(start) + if (phase == null) ctx + else prepValDef(tree, phase.idxInGroup + 1)(phase.prepareForValDef(tree)) + } - private def transTry(phase: MiniPhase): Transformer[Try, Tree] = - (tree, ctx) => transformNode(phase.transformTry(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goValDef(tree: ValDef, start: Int)(implicit ctx: Context): Tree = { + val phase = nxValDefTransPhase(start) + if (phase == null) tree + else phase.transformValDef(tree)(ctx) match { + case tree1: ValDef => goValDef(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transSeqLiteral(phase: MiniPhase): Transformer[SeqLiteral, Tree] = - (tree, ctx) => transformNode(phase.transformSeqLiteral(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepDefDef(tree: DefDef, start: Int)(implicit ctx: Context): Context = { + val phase = nxDefDefPrepPhase(start) + if (phase == null) ctx + else prepDefDef(tree, phase.idxInGroup + 1)(phase.prepareForDefDef(tree)) + } - private def transInlined(phase: MiniPhase): Transformer[Inlined, Tree] = - (tree, ctx) => transformNode(phase.transformInlined(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goDefDef(tree: DefDef, start: Int)(implicit ctx: Context): Tree = { + val phase = nxDefDefTransPhase(start) + if (phase == null) tree + else phase.transformDefDef(tree)(ctx) match { + case tree1: DefDef => goDefDef(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transTypeTree(phase: MiniPhase): Transformer[TypeTree, Tree] = - (tree, ctx) => transformNode(phase.transformTypeTree(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepTypeDef(tree: TypeDef, start: Int)(implicit ctx: Context): Context = { + val phase = nxTypeDefPrepPhase(start) + if (phase == null) ctx + else prepTypeDef(tree, phase.idxInGroup + 1)(phase.prepareForTypeDef(tree)) + } - private def transBind(phase: MiniPhase): Transformer[Bind, Tree] = - (tree, ctx) => transformNode(phase.transformBind(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goTypeDef(tree: TypeDef, start: Int)(implicit ctx: Context): Tree = { + val phase = nxTypeDefTransPhase(start) + if (phase == null) tree + else phase.transformTypeDef(tree)(ctx) match { + case tree1: TypeDef => goTypeDef(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transAlternative(phase: MiniPhase): Transformer[Alternative, Tree] = - (tree, ctx) => transformNode(phase.transformAlternative(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepTemplate(tree: Template, start: Int)(implicit ctx: Context): Context = { + val phase = nxTemplatePrepPhase(start) + if (phase == null) ctx + else prepTemplate(tree, phase.idxInGroup + 1)(phase.prepareForTemplate(tree)) + } - private def transUnApply(phase: MiniPhase): Transformer[UnApply, Tree] = - (tree, ctx) => transformNode(phase.transformUnApply(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goTemplate(tree: Template, start: Int)(implicit ctx: Context): Tree = { + val phase = nxTemplateTransPhase(start) + if (phase == null) tree + else phase.transformTemplate(tree)(ctx) match { + case tree1: Template => goTemplate(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transValDef(phase: MiniPhase): Transformer[ValDef, Tree] = - (tree, ctx) => transformNode(phase.transformValDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepPackageDef(tree: PackageDef, start: Int)(implicit ctx: Context): Context = { + val phase = nxPackageDefPrepPhase(start) + if (phase == null) ctx + else prepPackageDef(tree, phase.idxInGroup + 1)(phase.prepareForPackageDef(tree)) + } - private def transDefDef(phase: MiniPhase): Transformer[DefDef, Tree] = - (tree, ctx) => transformNode(phase.transformDefDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goPackageDef(tree: PackageDef, start: Int)(implicit ctx: Context): Tree = { + val phase = nxPackageDefTransPhase(start) + if (phase == null) tree + else phase.transformPackageDef(tree)(ctx) match { + case tree1: PackageDef => goPackageDef(tree1, phase.idxInGroup + 1) + case tree1 => transformNode(tree1, phase.idxInGroup + 1) + } + } - private def transTypeDef(phase: MiniPhase): Transformer[TypeDef, Tree] = - (tree, ctx) => transformNode(phase.transformTypeDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepStats(trees: List[Tree], start: Int)(implicit ctx: Context): Context = { + val phase = nxStatsPrepPhase(start) + if (phase == null) ctx + else prepStats(trees, phase.idxInGroup + 1)(phase.prepareForStats(trees)) + } - private def transTemplate(phase: MiniPhase): Transformer[Template, Tree] = - (tree, ctx) => transformNode(phase.transformTemplate(tree)(ctx), phase.idxInGroup + 1)(ctx) + def goStats(trees: List[Tree], start: Int)(implicit ctx: Context): List[Tree] = { + val phase = nxStatsTransPhase(start) + if (phase == null) trees + else goStats(phase.transformStats(trees)(ctx), phase.idxInGroup + 1) + } - private def transPackageDef(phase: MiniPhase): Transformer[PackageDef, Tree] = - (tree, ctx) => transformNode(phase.transformPackageDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + def prepUnit(tree: Tree, start: Int)(implicit ctx: Context): Context = { + val phase = nxUnitPrepPhase(start) + if (phase == null) ctx + else prepUnit(tree, phase.idxInGroup + 1)(phase.prepareForUnit(tree)) + } - private def transStats(phase: MiniPhase): Transformer[List[Tree], List[Tree]] = - (trees, ctx) => statsNodeTransformer(phase.idxInGroup + 1)(phase.transformStats(trees)(ctx), ctx) + def goUnit(tree: Tree, start: Int)(implicit ctx: Context): Tree = { + val phase = nxUnitTransPhase(start) + if (phase == null) tree + else goUnit(phase.transformUnit(tree)(ctx), phase.idxInGroup + 1) + } - private def transUnit(phase: MiniPhase): Transformer[Tree, Tree] = - (tree, ctx) => unitNodeTransformer(phase.idxInGroup + 1)(phase.transformUnit(tree)(ctx), ctx) + def prepOther(tree: Tree, start: Int)(implicit ctx: Context): Context = { + val phase = nxOtherPrepPhase(start) + if (phase == null) ctx + else prepOther(tree, phase.idxInGroup + 1)(phase.prepareForOther(tree)) + } - private def transOther(phase: MiniPhase): Transformer[Tree, Tree] = - (tree, ctx) => otherNodeTransformer(phase.idxInGroup + 1)(phase.transformOther(tree)(ctx), ctx) -} \ No newline at end of file + def goOther(tree: Tree, start: Int)(implicit ctx: Context): Tree = { + val phase = nxOtherTransPhase(start) + if (phase == null) tree + else goOther(phase.transformOther(tree)(ctx), phase.idxInGroup + 1) + } +} From 38209fa2f9e0bade29c194f0aadf04a963d9766f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 27 Oct 2017 18:41:31 +0200 Subject: [PATCH 2/3] Revert: Add tag method to Tree nodes (reverted from commit 0934483934a537f04b5c0dc54deb6213f690d811) --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 118 ------------------ compiler/src/dotty/tools/dotc/ast/untpd.scala | 65 +++------- 2 files changed, 15 insertions(+), 168 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 0453f65dabdb..0fb504f62d12 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -19,82 +19,6 @@ import language.implicitConversions object Trees { - type TreeTag = Int - - object Tag { - final val Ident = 0 - final val Select = 1 - final val This = 2 - final val Super = 3 - final val Apply = 4 - final val TypeApply = 5 - final val Literal = 6 - final val New = 7 - final val Typed = 8 - final val NamedArg = 9 - final val Assign = 10 - final val Block = 11 - final val If = 12 - final val Closure = 13 - final val Match = 14 - final val CaseDef = 15 - final val Return = 16 - final val Try = 17 - final val SeqLiteral = 18 - final val Inlined = 19 - final val TypeTree = 20 - final val Bind = 21 - final val Alternative = 22 - final val UnApply = 23 - final val ValDef = 24 - final val DefDef = 25 - final val TypeDef = 26 - final val Template = 27 - final val Import = 28 - final val PackageDef = 29 - final val Thicket = 30 - - /** The highest tree tag that can appear in a picked tree + 1 */ - final val NumPickledTreeTags = 31 - - final val Annotated = 31 - final val SingletonTypeTree = 32 - final val AndTypeTree = 33 - final val OrTypeTree = 34 - final val RefinedTypeTree = 35 - final val AppliedTypeTree = 36 - final val LambdaTypeTree = 37 - final val ByNameTypeTree = 38 - final val TypeBoundsTree = 39 - - /** The highest tree tag that can appear in a typed tree + 1 */ - final val NumTypedTreeTags = 40 - - final val TypedSplice = 40 - final val ModuleDef = 41 - final val ParsedTry = 42 - final val SymbolLit = 43 - final val InterpolatedString = 44 - final val Function = 45 - final val InfixOp = 46 - final val PostfixOp = 47 - final val PrefixOp = 48 - final val Parens = 49 - final val Tuple = 50 - final val Throw = 51 - final val WhileDo = 42 - final val DoWhile = 43 - final val ForYield = 44 - final val ForDo = 45 - final val GenFrom = 46 - final val GenAlias = 47 - final val ContextBounds = 48 - final val PatDef = 49 - - /** The highest tree tag + 1 */ - final val NumTags = 50 - } - // Note: it would be more logical to make Untyped = Nothing. // However, this interacts in a bad way with Scala's current type inference. // In fact, we cannot write something like Select(pre, name), where pre is @@ -154,8 +78,6 @@ object Trees { /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] - def tag: TreeTag - private[this] var myTpe: T = _ /** Destructively set the type of the tree. This should be called only when it is known that @@ -435,7 +357,6 @@ object Trees { case class Ident[-T >: Untyped] private[ast] (name: Name) extends RefTree[T] { type ThisTree[-T >: Untyped] = Ident[T] - final def tag = Tag.Ident def qualifier: Tree[T] = genericEmptyTree /** Is this a `BackquotedIdent` ? */ @@ -453,7 +374,6 @@ object Trees { case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name) extends RefTree[T] { type ThisTree[-T >: Untyped] = Select[T] - final def tag = Tag.Select } class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature) @@ -465,7 +385,6 @@ object Trees { case class This[-T >: Untyped] private[ast] (qual: untpd.Ident) extends DenotingTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = This[T] - final def tag = Tag.This // Denotation of a This tree is always the underlying class; needs correction for modules. override def denot(implicit ctx: Context): Denotation = { typeOpt match { @@ -481,7 +400,6 @@ object Trees { case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Super[T] - final def tag = Tag.Super def forwardTo = qual } @@ -496,35 +414,30 @@ object Trees { case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] - final def tag = Tag.Apply } /** fun[args] */ case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { type ThisTree[-T >: Untyped] = TypeApply[T] - final def tag = Tag.TypeApply } /** const */ case class Literal[-T >: Untyped] private[ast] (const: Constant) extends TermTree[T] { type ThisTree[-T >: Untyped] = Literal[T] - final def tag = Tag.Literal } /** new tpt, but no constructor call */ case class New[-T >: Untyped] private[ast] (tpt: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = New[T] - final def tag = Tag.New } /** expr : tpt */ case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T]) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Typed[T] - final def tag = Tag.Typed def forwardTo = expr } @@ -532,28 +445,24 @@ object Trees { case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = NamedArg[T] - final def tag = Tag.NamedArg } /** name = arg, outside a parameter list */ case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Assign[T] - final def tag = Tag.Assign } /** { stats; expr } */ case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Block[T] - final def tag = Tag.Block } /** if cond then thenp else elsep */ case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] - final def tag = Tag.If } /** A closure with an environment and a reference to a method. @@ -568,21 +477,18 @@ object Trees { case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Closure[T] - final def tag = Tag.Closure } /** selector match { cases } */ case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Match[T] - final def tag = Tag.Match } /** case pat if guard => body; only appears as child of a Match */ case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = CaseDef[T] - final def tag = Tag.CaseDef } /** return expr @@ -593,7 +499,6 @@ object Trees { case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree) extends TermTree[T] { type ThisTree[-T >: Untyped] = Return[T] - final def tag = Tag.Return } /** try block catch handler finally finalizer @@ -618,7 +523,6 @@ object Trees { case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Try[T] - final def tag = Tag.Try } /** Seq(elems) @@ -627,7 +531,6 @@ object Trees { case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] - final def tag = Tag.SeqLiteral } /** Array(elems) */ @@ -655,14 +558,12 @@ object Trees { case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] - final def tag = Tag.Inlined } /** A type tree that represents an existing or inferred type */ case class TypeTree[-T >: Untyped] () extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = TypeTree[T] - final def tag = Tag.TypeTree override def isEmpty = !hasType override def toString = s"TypeTree${if (hasType) s"[$typeOpt]" else ""}" @@ -672,28 +573,24 @@ object Trees { case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T]) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = SingletonTypeTree[T] - final def tag = Tag.SingletonTypeTree } /** left & right */ case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = AndTypeTree[T] - final def tag = Tag.AndTypeTree } /** left | right */ case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = OrTypeTree[T] - final def tag = Tag.OrTypeTree } /** tpt { refinements } */ case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = RefinedTypeTree[T] - final def tag = Tag.RefinedTypeTree def forwardTo = tpt } @@ -701,7 +598,6 @@ object Trees { case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = AppliedTypeTree[T] - final def tag = Tag.AppliedTypeTree def forwardTo = tpt } @@ -709,28 +605,24 @@ object Trees { case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = LambdaTypeTree[T] - final def tag = Tag.LambdaTypeTree } /** => T */ case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = ByNameTypeTree[T] - final def tag = Tag.ByNameTypeTree } /** >: lo <: hi */ case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] - final def tag = Tag.TypeBoundsTree } /** name @ body */ case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T]) extends NameTree[T] with DefTree[T] with PatternTree[T] { type ThisTree[-T >: Untyped] = Bind[T] - final def tag = Tag.Bind override def isType = name.isTypeName override def isTerm = name.isTermName } @@ -739,7 +631,6 @@ object Trees { case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]]) extends PatternTree[T] { type ThisTree[-T >: Untyped] = Alternative[T] - final def tag = Tag.Alternative } /** The typed translation of `extractor(patterns)` in a pattern. The translation has the following @@ -759,14 +650,12 @@ object Trees { case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]]) extends PatternTree[T] { type ThisTree[-T >: Untyped] = UnApply[T] - final def tag = Tag.UnApply } /** mods val name: tpt = rhs */ case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] - final def tag = Tag.ValDef assert(isEmpty || tpt != genericEmptyTree) def unforced = preRhs protected def force(x: AnyRef) = preRhs = x @@ -777,7 +666,6 @@ object Trees { vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] - final def tag = Tag.DefDef assert(tpt != genericEmptyTree) def unforced = preRhs protected def force(x: AnyRef) = preRhs = x @@ -791,7 +679,6 @@ object Trees { case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T]) extends MemberDef[T] { type ThisTree[-T >: Untyped] = TypeDef[T] - final def tag = Tag.TypeDef /** Is this a definition of a class? */ def isClassDef = rhs.isInstanceOf[Template[_]] @@ -801,7 +688,6 @@ object Trees { case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList) extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] - final def tag = Tag.Template def unforcedBody = unforced def unforced = preBody protected def force(x: AnyRef) = preBody = x @@ -815,14 +701,12 @@ object Trees { case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]]) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] - final def tag = Tag.Import } /** package pid { stats } */ case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]]) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = PackageDef[T] - final def tag = Tag.PackageDef def forwardTo = pid } @@ -830,7 +714,6 @@ object Trees { case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T]) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = Annotated[T] - final def tag = Tag.Annotated def forwardTo = arg } @@ -849,7 +732,6 @@ object Trees { case class Thicket[-T >: Untyped](trees: List[Tree[T]]) extends Tree[T] with WithoutTypeOrPos[T] { type ThisTree[-T >: Untyped] = Thicket[T] - final def tag = Tag.Thicket override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 28ef978a5012..bf40539679ec 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -25,7 +25,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * @param owner The current owner at the time the tree was defined */ abstract case class TypedSplice(tree: tpd.Tree)(val owner: Symbol) extends ProxyTree { - final def tag = Tag.TypedSplice def forwardTo = tree } @@ -38,28 +37,20 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class ModuleDef(name: TermName, impl: Template) extends MemberDef { type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef - final def tag = Tag.ModuleDef def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this)(name.toTermName, impl) } - case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree { - final def tag = Tag.ParsedTry - } + case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree - case class SymbolLit(str: String) extends TermTree { - final def tag = Tag.SymbolLit - } + case class SymbolLit(str: String) extends TermTree /** An interpolated string * @param segments a list of two element tickets consisting of string literal and argument tree, * possibly with a simple string literal as last element of the list */ - case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree { - final def tag = Tag.InterpolatedString - } + case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree case class Function(args: List[Tree], body: Tree) extends Tree { - final def tag = Tag.Function override def isTerm = body.isTerm override def isType = body.isType } @@ -76,51 +67,25 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { */ class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body) - case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree { - final def tag = Tag.InfixOp - } - case class PostfixOp(od: Tree, op: Ident) extends OpTree { - final def tag = Tag.PostfixOp - } - case class PrefixOp(op: Ident, od: Tree) extends OpTree { - final def tag = Tag.PrefixOp - } + case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree + case class PostfixOp(od: Tree, op: Ident) extends OpTree + case class PrefixOp(op: Ident, od: Tree) extends OpTree case class Parens(t: Tree) extends ProxyTree { - final def tag = Tag.Parens def forwardTo = t } case class Tuple(trees: List[Tree]) extends Tree { - final def tag = Tag.Tuple override def isTerm = trees.isEmpty || trees.head.isTerm override def isType = !isTerm } - case class Throw(expr: Tree) extends TermTree { - final def tag = Tag.Throw - } - case class WhileDo(cond: Tree, body: Tree) extends TermTree { - final def tag = Tag.WhileDo - } - case class DoWhile(body: Tree, cond: Tree) extends TermTree { - final def tag = Tag.DoWhile - } - case class ForYield(enums: List[Tree], expr: Tree) extends TermTree { - final def tag = Tag.ForYield - } - case class ForDo(enums: List[Tree], body: Tree) extends TermTree { - final def tag = Tag.ForDo - } - case class GenFrom(pat: Tree, expr: Tree) extends Tree { - final def tag = Tag.GenFrom - } - case class GenAlias(pat: Tree, expr: Tree) extends Tree { - final def tag = Tag.GenAlias - } - case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree { - final def tag = Tag.ContextBounds - } - case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree { - final def tag = Tag.PatDef - } + case class Throw(expr: Tree) extends TermTree + case class WhileDo(cond: Tree, body: Tree) extends TermTree + case class DoWhile(body: Tree, cond: Tree) extends TermTree + case class ForYield(enums: List[Tree], expr: Tree) extends TermTree + case class ForDo(enums: List[Tree], body: Tree) extends TermTree + case class GenFrom(pat: Tree, expr: Tree) extends Tree + case class GenAlias(pat: Tree, expr: Tree) extends Tree + case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree + case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY) with WithoutTypeOrPos[Untyped] { override def isEmpty = true From a7c34ec6c6baccaf0ce0c0609e653d15d65b5533 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 27 Oct 2017 18:42:59 +0200 Subject: [PATCH 3/3] Remove TreeTransform --- .../tools/dotc/transform/TreeTransform.scala | 1231 ----------------- 1 file changed, 1231 deletions(-) delete mode 100644 compiler/src/dotty/tools/dotc/transform/TreeTransform.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala b/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala deleted file mode 100644 index d3fd77f1403c..000000000000 --- a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala +++ /dev/null @@ -1,1231 +0,0 @@ -package dotty.tools -package dotc -package transform - -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.DenotTransformers.{InfoTransformer, DenotTransformer} -import dotty.tools.dotc.core.Denotations.SingleDenotation -import dotty.tools.dotc.core.Phases.Phase -import dotty.tools.dotc.core.Periods._ -import dotty.tools.dotc.core.SymDenotations.SymDenotation -import dotty.tools.dotc.core.Symbols.Symbol -import dotty.tools.dotc.core.Flags.PackageVal -import dotty.tools.dotc.core.Mode -import dotty.tools.dotc.ast.Trees._ -import dotty.tools.dotc.core.Decorators._ -import dotty.tools.dotc.util.DotClass -import scala.annotation.tailrec -import config.Printers.transforms -import scala.util.control.NonFatal -import reporting.trace - -object TreeTransforms { - import tpd._ - - /** The base class of tree transforms. For each kind of tree K, there are - * two methods which can be overridden: - * - * prepareForK // return a new TreeTransform which gets applied to the K - * // node and its children - * transformK // transform node of type K - * - * If a transform does not need to visit a node or any of its children, it - * signals this fact by returning a NoTransform from a prepare method. - * - * If all transforms in a group are NoTransforms, the tree is no longer traversed. - * - * - * Performance analysis: Taking the dotty compiler frontend as a use case, we are aiming for a warm performance of - * about 4000 lines / sec. This means 6 seconds for a codebase of 24'000 lines. Of these the frontend consumes - * over 2.5 seconds, erasure and code generation will most likely consume over 1 second each. So we would have - * about 1 sec for all other transformations in our budget. Of this second, let's assume a maximum of 20% for - * the general dispatch overhead as opposed to the concrete work done in transformations. So that leaves us with - * 0.2sec, or roughly 600M processor cycles. - * - * Now, to the amount of work that needs to be done. The codebase produces an average of about 250'000 trees after typechecking. - * Transformations are likely to make this bigger so let's assume 300K trees on average. We estimate to have about 100 - * micro-transformations. Let's say 5 transformation groups of 20 micro-transformations each. (by comparison, - * scalac has in excess of 20 phases, and most phases do multiple transformations). There are then 30M visits - * of a node by a transformation. Each visit has a budget of 20 processor cycles. - * - * A more detailed breakdown: I assume that about one third of all transformations have real work to do for each node. - * This might look high, but keep in mind that the most common nodes are Idents and Selects, and most transformations - * touch these. By contrast the amount of work for generating new transformations should be negligible. - * - * So, in 400 clock cycles we need to (1) perform a pattern match according to the type of node, (2) generate new - * transformations if applicable, (3) reconstitute the tree node from the result of transforming the children, and - * (4) chain 7 out of 20 transformations over the resulting tree node. I believe the current algorithm is suitable - * for achieving this goal, but there can be no wasted cycles anywhere. - */ - abstract class TreeTransform extends DotClass { - - def phase: MiniPhase - - val cpy: TypedTreeCopier = cpyBetweenPhases - - def prepareForIdent(tree: Ident)(implicit ctx: Context) = this - def prepareForSelect(tree: Select)(implicit ctx: Context) = this - def prepareForThis(tree: This)(implicit ctx: Context) = this - def prepareForSuper(tree: Super)(implicit ctx: Context) = this - def prepareForApply(tree: Apply)(implicit ctx: Context) = this - def prepareForTypeApply(tree: TypeApply)(implicit ctx: Context) = this - def prepareForLiteral(tree: Literal)(implicit ctx: Context) = this - def prepareForNew(tree: New)(implicit ctx: Context) = this - def prepareForTyped(tree: Typed)(implicit ctx: Context) = this - def prepareForAssign(tree: Assign)(implicit ctx: Context) = this - def prepareForBlock(tree: Block)(implicit ctx: Context) = this - def prepareForIf(tree: If)(implicit ctx: Context) = this - def prepareForClosure(tree: Closure)(implicit ctx: Context) = this - def prepareForMatch(tree: Match)(implicit ctx: Context) = this - def prepareForCaseDef(tree: CaseDef)(implicit ctx: Context) = this - def prepareForReturn(tree: Return)(implicit ctx: Context) = this - def prepareForTry(tree: Try)(implicit ctx: Context) = this - def prepareForSeqLiteral(tree: SeqLiteral)(implicit ctx: Context) = this - def prepareForInlined(tree: Inlined)(implicit ctx: Context) = this - def prepareForTypeTree(tree: TypeTree)(implicit ctx: Context) = this - def prepareForBind(tree: Bind)(implicit ctx: Context) = this - def prepareForAlternative(tree: Alternative)(implicit ctx: Context) = this - def prepareForTypeDef(tree: TypeDef)(implicit ctx: Context) = this - def prepareForUnApply(tree: UnApply)(implicit ctx: Context) = this - def prepareForValDef(tree: ValDef)(implicit ctx: Context) = this - def prepareForDefDef(tree: DefDef)(implicit ctx: Context) = this - def prepareForTemplate(tree: Template)(implicit ctx: Context) = this - def prepareForPackageDef(tree: PackageDef)(implicit ctx: Context) = this - def prepareForStats(trees: List[Tree])(implicit ctx: Context) = this - - def prepareForUnit(tree: Tree)(implicit ctx: Context) = this - - def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformThis(tree: This)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformSuper(tree: Super)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformLiteral(tree: Literal)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformNew(tree: New)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformAssign(tree: Assign)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformMatch(tree: Match)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformCaseDef(tree: CaseDef)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformReturn(tree: Return)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformTry(tree: Try)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformSeqLiteral(tree: SeqLiteral)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformInlined(tree: Inlined)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformTypeTree(tree: TypeTree)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformBind(tree: Bind)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformAlternative(tree: Alternative)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformUnApply(tree: UnApply)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformPackageDef(tree: PackageDef)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = trees - def transformOther(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = tree - - def transformUnit(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = tree - - /** Transform tree using all transforms of current group (including this one) */ - def transform(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = info.group.transform(tree, info, 0) - - /** Transform subtree using all transforms following the current one in this group */ - def transformFollowingDeep(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = info.group.transform(tree, info, phase.idx + 1) - - /** Transform single node using all transforms following the current one in this group */ - def transformFollowing(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = info.group.transformSingle(tree, phase.idx + 1) - } - - /** A phase that defines a TreeTransform to be used in a group */ - trait MiniPhase extends Phase { thisPhase => - def treeTransform: TreeTransform - - /** id of this mini phase in group */ - var idx: Int = _ - - /** List of names of phases that should have finished their processing of all compilation units - * before this phase starts - */ - def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set.empty - - protected def mkTreeTransformer = new TreeTransformer { - override def phaseName: String = thisPhase.phaseName - override def miniPhases = Array(thisPhase) - } - - override def run(implicit ctx: Context): Unit = { - mkTreeTransformer.run - } - } - - /** A mini phase that is its own tree transform */ - abstract class MiniPhaseTransform extends TreeTransform with MiniPhase { - def treeTransform = this - def phase = this - } - - private class NoTreeTransform extends TreeTransform { - def phase = unsupported("phase") - } - - @sharable val NoTransform: TreeTransform = new NoTreeTransform - - type Mutator[T] = (TreeTransform, T, Context) => TreeTransform - - class TransformerInfo(val transformers: Array[TreeTransform], val nx: NXTransformations, val group: TreeTransformer) - - /** This class maintains track of which methods are redefined in MiniPhases and creates execution plans for transformXXX and prepareXXX - * Thanks to Martin for this idea - * @see NXTransformations.index for format of plan - */ - class NXTransformations { - private val clsMethodsCache = new java.util.IdentityHashMap[Class[_], Array[java.lang.reflect.Method]] - - // TODO: We spend too much time here. See if we can call it less or make it faster, - // e.g. by checking `cls.getMethod(name, ...).getDeclaringClass != classOf[TreeTransform]` instead. - private def hasRedefinedMethod(cls: Class[_], name: String): Boolean = { - if (cls.eq(classOf[TreeTransform]) || cls.eq(classOf[NoTreeTransform]) || - cls.eq(classOf[MiniPhaseTransform])) - return false - - // Class#getDeclaredMethods is slow, so we cache its output - var clsMethods = clsMethodsCache.get(cls) - if (clsMethods eq null) { - clsMethods = cls.getDeclaredMethods - clsMethodsCache.put(cls, clsMethods) - } - - var i = clsMethods.length - 1 - while (i >= 0) { - if (clsMethods(i).getName == name) - return true - i -= 1 - } - - hasRedefinedMethod(cls.getSuperclass, name) - } - - /** Create an index array `next` of size one larger than the size of `transforms` such that - * for each index i, `next(i)` is the smallest index j such that - * - * i <= j - * j == transforms.length || transform(j) defines a non-default method with given `name` - */ - private def index(transformations: Array[Class[_]], name: String): Array[Int] = { - val len = transformations.length - val next = new Array[Int](len + 1) - var nextTransform: Int = len - - /* loop invariant: nextTransform == the smallest j such that - * i < j and - * j == transforms.length || transform(j) defines a non-default method with given `name` - */ - next(len) = len - var i = len - 1 - while (i >= 0) { - // update nextTransform if this phase redefines the method - if (hasRedefinedMethod(transformations(i), name)) { - nextTransform = i - } - next(i) = nextTransform - i -= 1 - } - next - } - - private def indexUpdate(prev: Array[Int], changedTransformation: Class[_], index: Int, name: String, copy: Boolean = true) = { - val isDefinedNow = hasRedefinedMethod(changedTransformation, name) - val wasDefinedBefore = prev(index) == index - if (isDefinedNow == wasDefinedBefore) prev - else { - val result = if (copy) prev.clone() else prev - val oldValue = result(index) - val newValue = - if (wasDefinedBefore /* && !isDefinedNow */ ) prev(index + 1) - else index // isDefinedNow - var i = index - while (i >= 0 && result(i) == oldValue) { - result(i) = newValue - i -= 1 - } - result - } - } - - def this(transformations: Array[Class[_]]) = { - this() - nxPrepIdent = index(transformations, "prepareForIdent") - nxPrepSelect = index(transformations, "prepareForSelect") - nxPrepThis = index(transformations, "prepareForThis") - nxPrepSuper = index(transformations, "prepareForSuper") - nxPrepApply = index(transformations, "prepareForApply") - nxPrepTypeApply = index(transformations, "prepareForTypeApply") - nxPrepLiteral = index(transformations, "prepareForLiteral") - nxPrepNew = index(transformations, "prepareForNew") - nxPrepTyped = index(transformations, "prepareForTyped") - nxPrepAssign = index(transformations, "prepareForAssign") - nxPrepBlock = index(transformations, "prepareForBlock") - nxPrepIf = index(transformations, "prepareForIf") - nxPrepClosure = index(transformations, "prepareForClosure") - nxPrepCaseDef = index(transformations, "prepareForCaseDef") - nxPrepMatch = index(transformations, "prepareForMatch") - nxPrepReturn = index(transformations, "prepareForReturn") - nxPrepTry = index(transformations, "prepareForTry") - nxPrepSeqLiteral = index(transformations, "prepareForSeqLiteral") - nxPrepInlined = index(transformations, "prepareForInlined") - nxPrepTypeTree = index(transformations, "prepareForTypeTree") - nxPrepBind = index(transformations, "prepareForBind") - nxPrepAlternative = index(transformations, "prepareForAlternative") - nxPrepUnApply = index(transformations, "prepareForUnApply") - nxPrepValDef = index(transformations, "prepareForValDef") - nxPrepDefDef = index(transformations, "prepareForDefDef") - nxPrepTypeDef = index(transformations, "prepareForTypeDef") - nxPrepTemplate = index(transformations, "prepareForTemplate") - nxPrepPackageDef = index(transformations, "prepareForPackageDef") - nxPrepStats = index(transformations, "prepareForStats") - nxPrepUnit = index(transformations, "prepareForUnit") - - nxTransIdent = index(transformations, "transformIdent") - nxTransSelect = index(transformations, "transformSelect") - nxTransThis = index(transformations, "transformThis") - nxTransSuper = index(transformations, "transformSuper") - nxTransApply = index(transformations, "transformApply") - nxTransTypeApply = index(transformations, "transformTypeApply") - nxTransLiteral = index(transformations, "transformLiteral") - nxTransNew = index(transformations, "transformNew") - nxTransTyped = index(transformations, "transformTyped") - nxTransAssign = index(transformations, "transformAssign") - nxTransBlock = index(transformations, "transformBlock") - nxTransIf = index(transformations, "transformIf") - nxTransClosure = index(transformations, "transformClosure") - nxTransMatch = index(transformations, "transformMatch") - nxTransCaseDef = index(transformations, "transformCaseDef") - nxTransReturn = index(transformations, "transformReturn") - nxTransTry = index(transformations, "transformTry") - nxTransSeqLiteral = index(transformations, "transformSeqLiteral") - nxTransInlined = index(transformations, "transformInlined") - nxTransTypeTree = index(transformations, "transformTypeTree") - nxTransBind = index(transformations, "transformBind") - nxTransAlternative = index(transformations, "transformAlternative") - nxTransUnApply = index(transformations, "transformUnApply") - nxTransValDef = index(transformations, "transformValDef") - nxTransDefDef = index(transformations, "transformDefDef") - nxTransTypeDef = index(transformations, "transformTypeDef") - nxTransTemplate = index(transformations, "transformTemplate") - nxTransPackageDef = index(transformations, "transformPackageDef") - nxTransStats = index(transformations, "transformStats") - nxTransUnit = index(transformations, "transformUnit") - nxTransOther = index(transformations, "transformOther") - } - - def this(transformations: Array[TreeTransform]) = { - this(transformations.map(_.getClass).asInstanceOf[Array[Class[_]]]) - } - - def this(prev: NXTransformations, changedTransformation: TreeTransform, transformationIndex: Int, reuse: Boolean = false) = { - this() - val copy = !reuse - val changedTransformationClass = changedTransformation.getClass - nxPrepIdent = indexUpdate(prev.nxPrepIdent, changedTransformationClass, transformationIndex, "prepareForIdent", copy) - nxPrepSelect = indexUpdate(prev.nxPrepSelect, changedTransformationClass, transformationIndex, "prepareForSelect", copy) - nxPrepThis = indexUpdate(prev.nxPrepThis, changedTransformationClass, transformationIndex, "prepareForThis", copy) - nxPrepSuper = indexUpdate(prev.nxPrepSuper, changedTransformationClass, transformationIndex, "prepareForSuper", copy) - nxPrepApply = indexUpdate(prev.nxPrepApply, changedTransformationClass, transformationIndex, "prepareForApply", copy) - nxPrepTypeApply = indexUpdate(prev.nxPrepTypeApply, changedTransformationClass, transformationIndex, "prepareForTypeApply", copy) - nxPrepLiteral = indexUpdate(prev.nxPrepLiteral, changedTransformationClass, transformationIndex, "prepareForLiteral", copy) - nxPrepNew = indexUpdate(prev.nxPrepNew, changedTransformationClass, transformationIndex, "prepareForNew", copy) - nxPrepTyped = indexUpdate(prev.nxPrepTyped, changedTransformationClass, transformationIndex, "prepareForTyped", copy) - nxPrepAssign = indexUpdate(prev.nxPrepAssign, changedTransformationClass, transformationIndex, "prepareForAssign", copy) - nxPrepBlock = indexUpdate(prev.nxPrepBlock, changedTransformationClass, transformationIndex, "prepareForBlock", copy) - nxPrepIf = indexUpdate(prev.nxPrepIf, changedTransformationClass, transformationIndex, "prepareForIf", copy) - nxPrepClosure = indexUpdate(prev.nxPrepClosure, changedTransformationClass, transformationIndex, "prepareForClosure", copy) - nxPrepMatch = indexUpdate(prev.nxPrepMatch, changedTransformationClass, transformationIndex, "prepareForMatch", copy) - nxPrepCaseDef = indexUpdate(prev.nxPrepCaseDef, changedTransformationClass, transformationIndex, "prepareForCaseDef", copy) - nxPrepReturn = indexUpdate(prev.nxPrepReturn, changedTransformationClass, transformationIndex, "prepareForReturn", copy) - nxPrepTry = indexUpdate(prev.nxPrepTry, changedTransformationClass, transformationIndex, "prepareForTry", copy) - nxPrepSeqLiteral = indexUpdate(prev.nxPrepSeqLiteral, changedTransformationClass, transformationIndex, "prepareForSeqLiteral", copy) - nxPrepInlined = indexUpdate(prev.nxPrepInlined, changedTransformationClass, transformationIndex, "prepareForInlined", copy) - nxPrepTypeTree = indexUpdate(prev.nxPrepTypeTree, changedTransformationClass, transformationIndex, "prepareForTypeTree", copy) - nxPrepBind = indexUpdate(prev.nxPrepBind, changedTransformationClass, transformationIndex, "prepareForBind", copy) - nxPrepAlternative = indexUpdate(prev.nxPrepAlternative, changedTransformationClass, transformationIndex, "prepareForAlternative", copy) - nxPrepUnApply = indexUpdate(prev.nxPrepUnApply, changedTransformationClass, transformationIndex, "prepareForUnApply", copy) - nxPrepValDef = indexUpdate(prev.nxPrepValDef, changedTransformationClass, transformationIndex, "prepareForValDef", copy) - nxPrepDefDef = indexUpdate(prev.nxPrepDefDef, changedTransformationClass, transformationIndex, "prepareForDefDef", copy) - nxPrepTypeDef = indexUpdate(prev.nxPrepTypeDef, changedTransformationClass, transformationIndex, "prepareForTypeDef", copy) - nxPrepTemplate = indexUpdate(prev.nxPrepTemplate, changedTransformationClass, transformationIndex, "prepareForTemplate", copy) - nxPrepPackageDef = indexUpdate(prev.nxPrepPackageDef, changedTransformationClass, transformationIndex, "prepareForPackageDef", copy) - nxPrepStats = indexUpdate(prev.nxPrepStats, changedTransformationClass, transformationIndex, "prepareForStats", copy) - - nxTransIdent = indexUpdate(prev.nxTransIdent, changedTransformationClass, transformationIndex, "transformIdent", copy) - nxTransSelect = indexUpdate(prev.nxTransSelect, changedTransformationClass, transformationIndex, "transformSelect", copy) - nxTransThis = indexUpdate(prev.nxTransThis, changedTransformationClass, transformationIndex, "transformThis", copy) - nxTransSuper = indexUpdate(prev.nxTransSuper, changedTransformationClass, transformationIndex, "transformSuper", copy) - nxTransApply = indexUpdate(prev.nxTransApply, changedTransformationClass, transformationIndex, "transformApply", copy) - nxTransTypeApply = indexUpdate(prev.nxTransTypeApply, changedTransformationClass, transformationIndex, "transformTypeApply", copy) - nxTransLiteral = indexUpdate(prev.nxTransLiteral, changedTransformationClass, transformationIndex, "transformLiteral", copy) - nxTransNew = indexUpdate(prev.nxTransNew, changedTransformationClass, transformationIndex, "transformNew", copy) - nxTransTyped = indexUpdate(prev.nxTransTyped, changedTransformationClass, transformationIndex, "transformTyped", copy) - nxTransAssign = indexUpdate(prev.nxTransAssign, changedTransformationClass, transformationIndex, "transformAssign", copy) - nxTransBlock = indexUpdate(prev.nxTransBlock, changedTransformationClass, transformationIndex, "transformBlock", copy) - nxTransIf = indexUpdate(prev.nxTransIf, changedTransformationClass, transformationIndex, "transformIf", copy) - nxTransClosure = indexUpdate(prev.nxTransClosure, changedTransformationClass, transformationIndex, "transformClosure", copy) - nxTransMatch = indexUpdate(prev.nxTransMatch, changedTransformationClass, transformationIndex, "transformMatch", copy) - nxTransCaseDef = indexUpdate(prev.nxTransCaseDef, changedTransformationClass, transformationIndex, "transformCaseDef", copy) - nxTransReturn = indexUpdate(prev.nxTransReturn, changedTransformationClass, transformationIndex, "transformReturn", copy) - nxTransTry = indexUpdate(prev.nxTransTry, changedTransformationClass, transformationIndex, "transformTry", copy) - nxTransSeqLiteral = indexUpdate(prev.nxTransSeqLiteral, changedTransformationClass, transformationIndex, "transformSeqLiteral", copy) - nxTransInlined = indexUpdate(prev.nxTransInlined, changedTransformationClass, transformationIndex, "transformInlined", copy) - nxTransTypeTree = indexUpdate(prev.nxTransTypeTree, changedTransformationClass, transformationIndex, "transformTypeTree", copy) - nxTransBind = indexUpdate(prev.nxTransBind, changedTransformationClass, transformationIndex, "transformBind", copy) - nxTransAlternative = indexUpdate(prev.nxTransAlternative, changedTransformationClass, transformationIndex, "transformAlternative", copy) - nxTransUnApply = indexUpdate(prev.nxTransUnApply, changedTransformationClass, transformationIndex, "transformUnApply", copy) - nxTransValDef = indexUpdate(prev.nxTransValDef, changedTransformationClass, transformationIndex, "transformValDef", copy) - nxTransDefDef = indexUpdate(prev.nxTransDefDef, changedTransformationClass, transformationIndex, "transformDefDef", copy) - nxTransTypeDef = indexUpdate(prev.nxTransTypeDef, changedTransformationClass, transformationIndex, "transformTypeDef", copy) - nxTransTemplate = indexUpdate(prev.nxTransTemplate, changedTransformationClass, transformationIndex, "transformTemplate", copy) - nxTransPackageDef = indexUpdate(prev.nxTransPackageDef, changedTransformationClass, transformationIndex, "transformPackageDef", copy) - nxTransStats = indexUpdate(prev.nxTransStats, changedTransformationClass, transformationIndex, "transformStats", copy) - nxTransOther = indexUpdate(prev.nxTransOther, changedTransformationClass, transformationIndex, "transformOther", copy) - } - - /** Those arrays are used as "execution plan" in order to only execute non-trivial transformations\preparations - * for every integer i array(i) contains first non trivial transformation\preparation on particular tree subtype. - * If no nontrivial transformation are left stored value is greater than transformers.size - */ - var nxPrepIdent: Array[Int] = _ - var nxPrepSelect: Array[Int] = _ - var nxPrepThis: Array[Int] = _ - var nxPrepSuper: Array[Int] = _ - var nxPrepApply: Array[Int] = _ - var nxPrepTypeApply: Array[Int] = _ - var nxPrepLiteral: Array[Int] = _ - var nxPrepNew: Array[Int] = _ - var nxPrepTyped: Array[Int] = _ - var nxPrepAssign: Array[Int] = _ - var nxPrepBlock: Array[Int] = _ - var nxPrepIf: Array[Int] = _ - var nxPrepClosure: Array[Int] = _ - var nxPrepMatch: Array[Int] = _ - var nxPrepCaseDef: Array[Int] = _ - var nxPrepReturn: Array[Int] = _ - var nxPrepTry: Array[Int] = _ - var nxPrepSeqLiteral: Array[Int] = _ - var nxPrepInlined: Array[Int] = _ - var nxPrepTypeTree: Array[Int] = _ - var nxPrepBind: Array[Int] = _ - var nxPrepAlternative: Array[Int] = _ - var nxPrepUnApply: Array[Int] = _ - var nxPrepValDef: Array[Int] = _ - var nxPrepDefDef: Array[Int] = _ - var nxPrepTypeDef: Array[Int] = _ - var nxPrepTemplate: Array[Int] = _ - var nxPrepPackageDef: Array[Int] = _ - var nxPrepStats: Array[Int] = _ - var nxPrepUnit: Array[Int] = _ - - var nxTransIdent: Array[Int] = _ - var nxTransSelect: Array[Int] = _ - var nxTransThis: Array[Int] = _ - var nxTransSuper: Array[Int] = _ - var nxTransApply: Array[Int] = _ - var nxTransTypeApply: Array[Int] = _ - var nxTransLiteral: Array[Int] = _ - var nxTransNew: Array[Int] = _ - var nxTransTyped: Array[Int] = _ - var nxTransAssign: Array[Int] = _ - var nxTransBlock: Array[Int] = _ - var nxTransIf: Array[Int] = _ - var nxTransClosure: Array[Int] = _ - var nxTransMatch: Array[Int] = _ - var nxTransCaseDef: Array[Int] = _ - var nxTransReturn: Array[Int] = _ - var nxTransTry: Array[Int] = _ - var nxTransSeqLiteral: Array[Int] = _ - var nxTransInlined: Array[Int] = _ - var nxTransTypeTree: Array[Int] = _ - var nxTransBind: Array[Int] = _ - var nxTransAlternative: Array[Int] = _ - var nxTransUnApply: Array[Int] = _ - var nxTransValDef: Array[Int] = _ - var nxTransDefDef: Array[Int] = _ - var nxTransTypeDef: Array[Int] = _ - var nxTransTemplate: Array[Int] = _ - var nxTransPackageDef: Array[Int] = _ - var nxTransStats: Array[Int] = _ - var nxTransUnit: Array[Int] = _ - var nxTransOther: Array[Int] = _ - } - - /** A group of tree transforms that are applied in sequence during the same phase */ - abstract class TreeTransformer extends Phase { - - def miniPhases: Array[MiniPhase] - - private var myGroupEndId: PhaseId = NoPhaseId - - def groupEndId: PhaseId = { - if (myGroupEndId == NoPhaseId) myGroupEndId = miniPhases.last.id + 1 - myGroupEndId - } - - val cpy: TypedTreeCopier = cpyBetweenPhases - - override def run(implicit ctx: Context): Unit = { - val curTree = ctx.compilationUnit.tpdTree - val newTree = macroTransform(curTree) - ctx.compilationUnit.tpdTree = newTree - } - - def mutateTransformers[T](info: TransformerInfo, mutator: Mutator[T], mutationPlan: Array[Int], tree: T, cur: Int)(implicit ctx: Context) = { - var transformersCopied = false - var nxCopied = false - var result = info.transformers - var resultNX = info.nx - var i = mutationPlan(cur) - // @DarkDimius You commented on the previous version - // - // var i = mutationPlan(0) // if TreeTransform.transform() method didn't exist we could have used mutationPlan(cur) - // - // But we need to use `cur` or otherwise we call prepare actions preceding the - // phase that issued a transformFollowing. This can lead to "denotation not defined - // here" errors. Note that tests still pass with the current modified code. - val l = result.length - var allDone = i < l - while (i < l) { - val oldTransform = result(i) - val newTransform = mutator(oldTransform, tree, ctx.withPhase(groupEndId)) - allDone = allDone && (newTransform eq NoTransform) - if (!(oldTransform eq newTransform)) { - if (!transformersCopied) result = result.clone() - transformersCopied = true - result(i) = newTransform - if (!(newTransform.getClass == oldTransform.getClass)) { - resultNX = new NXTransformations(resultNX, newTransform, i, nxCopied) - nxCopied = true - } - } - i = mutationPlan(i + 1) - } - if (allDone) null - else if (!transformersCopied) info - else new TransformerInfo(result, resultNX, info.group) - } - - val prepForIdent: Mutator[Ident] = (trans, tree, ctx) => trans.prepareForIdent(tree)(ctx) - val prepForSelect: Mutator[Select] = (trans, tree, ctx) => trans.prepareForSelect(tree)(ctx) - val prepForThis: Mutator[This] = (trans, tree, ctx) => trans.prepareForThis(tree)(ctx) - val prepForSuper: Mutator[Super] = (trans, tree, ctx) => trans.prepareForSuper(tree)(ctx) - val prepForApply: Mutator[Apply] = (trans, tree, ctx) => trans.prepareForApply(tree)(ctx) - val prepForTypeApply: Mutator[TypeApply] = (trans, tree, ctx) => trans.prepareForTypeApply(tree)(ctx) - val prepForNew: Mutator[New] = (trans, tree, ctx) => trans.prepareForNew(tree)(ctx) - val prepForTyped: Mutator[Typed] = (trans, tree, ctx) => trans.prepareForTyped(tree)(ctx) - val prepForAssign: Mutator[Assign] = (trans, tree, ctx) => trans.prepareForAssign(tree)(ctx) - val prepForLiteral: Mutator[Literal] = (trans, tree, ctx) => trans.prepareForLiteral(tree)(ctx) - val prepForBlock: Mutator[Block] = (trans, tree, ctx) => trans.prepareForBlock(tree)(ctx) - val prepForIf: Mutator[If] = (trans, tree, ctx) => trans.prepareForIf(tree)(ctx) - val prepForClosure: Mutator[Closure] = (trans, tree, ctx) => trans.prepareForClosure(tree)(ctx) - val prepForMatch: Mutator[Match] = (trans, tree, ctx) => trans.prepareForMatch(tree)(ctx) - val prepForCaseDef: Mutator[CaseDef] = (trans, tree, ctx) => trans.prepareForCaseDef(tree)(ctx) - val prepForReturn: Mutator[Return] = (trans, tree, ctx) => trans.prepareForReturn(tree)(ctx) - val prepForTry: Mutator[Try] = (trans, tree, ctx) => trans.prepareForTry(tree)(ctx) - val prepForSeqLiteral: Mutator[SeqLiteral] = (trans, tree, ctx) => trans.prepareForSeqLiteral(tree)(ctx) - val prepForInlined: Mutator[Inlined] = (trans, tree, ctx) => trans.prepareForInlined(tree)(ctx) - val prepForTypeTree: Mutator[TypeTree] = (trans, tree, ctx) => trans.prepareForTypeTree(tree)(ctx) - val prepForBind: Mutator[Bind] = (trans, tree, ctx) => trans.prepareForBind(tree)(ctx) - val prepForAlternative: Mutator[Alternative] = (trans, tree, ctx) => trans.prepareForAlternative(tree)(ctx) - val prepForUnApply: Mutator[UnApply] = (trans, tree, ctx) => trans.prepareForUnApply(tree)(ctx) - val prepForValDef: Mutator[ValDef] = (trans, tree, ctx) => trans.prepareForValDef(tree)(ctx) - val prepForDefDef: Mutator[DefDef] = (trans, tree, ctx) => trans.prepareForDefDef(tree)(ctx) - val prepForTypeDef: Mutator[TypeDef] = (trans, tree, ctx) => trans.prepareForTypeDef(tree)(ctx) - val prepForTemplate: Mutator[Template] = (trans, tree, ctx) => trans.prepareForTemplate(tree)(ctx) - val prepForPackageDef: Mutator[PackageDef] = (trans, tree, ctx) => trans.prepareForPackageDef(tree)(ctx) - val prepForStats: Mutator[List[Tree]] = (trans, trees, ctx) => trans.prepareForStats(trees)(ctx) - val prepForUnit: Mutator[Tree] = (trans, tree, ctx) => trans.prepareForUnit(tree)(ctx) - - val initialTransformationsCache = miniPhases.zipWithIndex.map { - case (miniPhase, id) => - miniPhase.idx = id - miniPhase.treeTransform - } - - val initialInfoCache = new TransformerInfo(initialTransformationsCache, new NXTransformations(initialTransformationsCache), this) - - def macroTransform(t: Tree)(implicit ctx: Context): Tree = { - val info = initialInfoCache - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForUnit, info.nx.nxPrepUnit, t, 0) - if (mutatedInfo eq null) t - else goUnit(transform(t, mutatedInfo, 0), mutatedInfo.nx.nxTransUnit(0)) - } - - @tailrec - final private[TreeTransforms] def goIdent(tree: Ident, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformIdent(tree)(ctx.withPhase(groupEndId), info) match { - case t: Ident => goIdent(t, info.nx.nxTransIdent(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goSelect(tree: Select, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformSelect(tree)(ctx.withPhase(groupEndId), info) match { - case t: Select => goSelect(t, info.nx.nxTransSelect(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goThis(tree: This, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformThis(tree)(ctx.withPhase(groupEndId), info) match { - case t: This => goThis(t, info.nx.nxTransThis(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goSuper(tree: Super, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformSuper(tree)(ctx.withPhase(groupEndId), info) match { - case t: Super => goSuper(t, info.nx.nxTransSuper(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goApply(tree: Apply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformApply(tree)(ctx.withPhase(groupEndId), info) match { - case t: Apply => goApply(t, info.nx.nxTransApply(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goTypeApply(tree: TypeApply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformTypeApply(tree)(ctx.withPhase(groupEndId), info) match { - case t: TypeApply => goTypeApply(t, info.nx.nxTransTypeApply(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goNew(tree: New, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformNew(tree)(ctx.withPhase(groupEndId), info) match { - case t: New => goNew(t, info.nx.nxTransNew(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goTyped(tree: Typed, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformTyped(tree)(ctx.withPhase(groupEndId), info) match { - case t: Typed => goTyped(t, info.nx.nxTransTyped(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goAssign(tree: Assign, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformAssign(tree)(ctx.withPhase(groupEndId), info) match { - case t: Assign => goAssign(t, info.nx.nxTransAssign(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goLiteral(tree: Literal, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformLiteral(tree)(ctx.withPhase(groupEndId), info) match { - case t: Literal => goLiteral(t, info.nx.nxTransLiteral(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goBlock(tree: Block, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformBlock(tree)(ctx.withPhase(groupEndId), info) match { - case t: Block => goBlock(t, info.nx.nxTransBlock(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goIf(tree: If, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformIf(tree)(ctx.withPhase(groupEndId), info) match { - case t: If => goIf(t, info.nx.nxTransIf(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goClosure(tree: Closure, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformClosure(tree)(ctx.withPhase(groupEndId), info) match { - case t: Closure => goClosure(t, info.nx.nxTransClosure(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goMatch(tree: Match, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformMatch(tree)(ctx.withPhase(groupEndId), info) match { - case t: Match => goMatch(t, info.nx.nxTransMatch(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goCaseDef(tree: CaseDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformCaseDef(tree)(ctx.withPhase(groupEndId), info) match { - case t: CaseDef => goCaseDef(t, info.nx.nxTransCaseDef(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goReturn(tree: Return, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformReturn(tree)(ctx.withPhase(groupEndId), info) match { - case t: Return => goReturn(t, info.nx.nxTransReturn(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goTry(tree: Try, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformTry(tree)(ctx.withPhase(groupEndId), info) match { - case t: Try => goTry(t, info.nx.nxTransTry(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goSeqLiteral(tree: SeqLiteral, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformSeqLiteral(tree)(ctx.withPhase(groupEndId), info) match { - case t: SeqLiteral => goSeqLiteral(t, info.nx.nxTransSeqLiteral(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goInlined(tree: Inlined, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformInlined(tree)(ctx.withPhase(groupEndId), info) match { - case t: Inlined => goInlined(t, info.nx.nxTransInlined(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goTypeTree(tree: TypeTree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformTypeTree(tree)(ctx.withPhase(groupEndId), info) match { - case t: TypeTree => goTypeTree(t, info.nx.nxTransTypeTree(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goBind(tree: Bind, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformBind(tree)(ctx.withPhase(groupEndId), info) match { - case t: Bind => goBind(t, info.nx.nxTransBind(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goAlternative(tree: Alternative, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformAlternative(tree)(ctx.withPhase(groupEndId), info) match { - case t: Alternative => goAlternative(t, info.nx.nxTransAlternative(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goValDef(tree: ValDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformValDef(tree)(ctx.withPhase(groupEndId), info) match { - case t: ValDef => goValDef(t, info.nx.nxTransValDef(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goDefDef(tree: DefDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformDefDef(tree)(ctx.withPhase(groupEndId), info) match { - case t: DefDef => goDefDef(t, info.nx.nxTransDefDef(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goUnApply(tree: UnApply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformUnApply(tree)(ctx.withPhase(groupEndId), info) match { - case t: UnApply => goUnApply(t, info.nx.nxTransUnApply(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goTypeDef(tree: TypeDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformTypeDef(tree)(ctx.withPhase(groupEndId), info) match { - case t: TypeDef => goTypeDef(t, info.nx.nxTransTypeDef(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goTemplate(tree: Template, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformTemplate(tree)(ctx.withPhase(groupEndId), info) match { - case t: Template => goTemplate(t, info.nx.nxTransTemplate(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goPackageDef(tree: PackageDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - trans.transformPackageDef(tree)(ctx.withPhase(groupEndId), info) match { - case t: PackageDef => goPackageDef(t, info.nx.nxTransPackageDef(cur + 1)) - case t => transformSingle(t, cur + 1) - } - } else tree - } - - @tailrec - final private[TreeTransforms] def goUnit(tree: Tree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - val t = trans.transformUnit(tree)(ctx.withPhase(groupEndId), info) - goUnit(t, info.nx.nxTransUnit(cur + 1)) - } else tree - } - - final private[TreeTransforms] def goOther(tree: Tree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - val t = trans.transformOther(tree)(ctx.withPhase(groupEndId), info) - transformSingle(t, cur + 1) - } else tree - } - - final private[TreeTransforms] def goNamed(tree: NameTree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = - tree match { - case tree: Ident => goIdent(tree, info.nx.nxTransIdent(cur)) - case tree: Select => goSelect(tree, info.nx.nxTransSelect(cur)) - case tree: Bind => goBind(tree, cur) - case tree: ValDef if !tree.isEmpty => goValDef(tree, info.nx.nxTransValDef(cur)) - case tree: DefDef => goDefDef(tree, info.nx.nxTransDefDef(cur)) - case tree: TypeDef => goTypeDef(tree, info.nx.nxTransTypeDef(cur)) - case _ => tree - } - - final private[TreeTransforms] def goUnnamed(tree: Tree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = - tree match { - case tree: This => goThis(tree, info.nx.nxTransThis(cur)) - case tree: Super => goSuper(tree, info.nx.nxTransSuper(cur)) - case tree: Apply => goApply(tree, info.nx.nxTransApply(cur)) - case tree: TypeApply => goTypeApply(tree, info.nx.nxTransTypeApply(cur)) - case tree: Literal => goLiteral(tree, info.nx.nxTransLiteral(cur)) - case tree: New => goNew(tree, info.nx.nxTransNew(cur)) - case tree: Typed => goTyped(tree, info.nx.nxTransTyped(cur)) - case tree: Assign => goAssign(tree, info.nx.nxTransAssign(cur)) - case tree: Block => goBlock(tree, info.nx.nxTransBlock(cur)) - case tree: If => goIf(tree, info.nx.nxTransIf(cur)) - case tree: Closure => goClosure(tree, info.nx.nxTransClosure(cur)) - case tree: Match => goMatch(tree, info.nx.nxTransMatch(cur)) - case tree: CaseDef => goCaseDef(tree, info.nx.nxTransCaseDef(cur)) - case tree: Return => goReturn(tree, info.nx.nxTransReturn(cur)) - case tree: Try => goTry(tree, info.nx.nxTransTry(cur)) - case tree: SeqLiteral => goSeqLiteral(tree, info.nx.nxTransSeqLiteral(cur)) - case tree: Inlined => goInlined(tree, info.nx.nxTransInlined(cur)) - case tree: TypeTree => goTypeTree(tree, info.nx.nxTransTypeTree(cur)) - case tree: Alternative => goAlternative(tree, info.nx.nxTransAlternative(cur)) - case tree: UnApply => goUnApply(tree, info.nx.nxTransUnApply(cur)) - case tree: Template => goTemplate(tree, info.nx.nxTransTemplate(cur)) - case tree: PackageDef => goPackageDef(tree, info.nx.nxTransPackageDef(cur)) - case Thicket(trees) => tree - case tree => goOther(tree, info.nx.nxTransOther(cur)) - } - - final private[TreeTransforms] def transformSingle(tree: Tree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = - if (cur < info.transformers.length) { - tree match { - // split one big match into 2 smaller ones - case tree: NameTree => goNamed(tree, cur) - case tree => goUnnamed(tree, cur) - } - } else tree - - // TODO merge with localCtx in MacroTransform - // Generally: If we will keep MacroTransform, merge common behavior with TreeTransform - def localContext(sym: Symbol)(implicit ctx: Context) = { - val owner = if (sym is PackageVal) sym.moduleClass else sym - ctx.fresh.setOwner(owner) - } - - final private[TreeTransforms] def transformNamed(tree: NameTree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = - tree match { - case tree: Ident => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForIdent, info.nx.nxPrepIdent, tree, cur) - // Dotty deviation: implicits need explicit type - if (mutatedInfo eq null) tree - else goIdent(tree, mutatedInfo.nx.nxTransIdent(cur)) - case tree: Select => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSelect, info.nx.nxPrepSelect, tree, cur) - if (mutatedInfo eq null) tree - else { - val qual = transform(tree.qualifier, mutatedInfo, cur) - goSelect(cpy.Select(tree)(qual, tree.name), mutatedInfo.nx.nxTransSelect(cur)) - } - case tree: ValDef if !tree.isEmpty => // As a result of discussing with Martin: emptyValDefs shouldn't be copied // NAME - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForValDef, info.nx.nxPrepValDef, tree, cur) - if (mutatedInfo eq null) tree - else { - val nestedCtx = if (tree.symbol.exists) localContext(tree.symbol) else ctx - val tpt = transform(tree.tpt, mutatedInfo, cur)(nestedCtx) - val rhs = transform(tree.rhs, mutatedInfo, cur)(nestedCtx) - goValDef(cpy.ValDef(tree)(tree.name, tpt, rhs), mutatedInfo.nx.nxTransValDef(cur)) - } - case tree: DefDef => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForDefDef, info.nx.nxPrepDefDef, tree, cur) - if (mutatedInfo eq null) tree - else { - val nestedCtx = localContext(tree.symbol) - val tparams = transformSubTrees(tree.tparams, mutatedInfo, cur)(nestedCtx) - val vparams = tree.vparamss.mapConserve(x => transformSubTrees(x, mutatedInfo, cur)(nestedCtx)) - val tpt = transform(tree.tpt, mutatedInfo, cur)(nestedCtx) - val rhs = transform(tree.rhs, mutatedInfo, cur)(nestedCtx) - goDefDef(cpy.DefDef(tree)(tree.name, tparams, vparams, tpt, rhs), mutatedInfo.nx.nxTransDefDef(cur)) - } - case tree: TypeDef => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeDef, info.nx.nxPrepTypeDef, tree, cur) - if (mutatedInfo eq null) tree - else { - val rhs = transform(tree.rhs, mutatedInfo, cur)(localContext(tree.symbol)) - goTypeDef(cpy.TypeDef(tree)(tree.name, rhs), mutatedInfo.nx.nxTransTypeDef(cur)) - } - case tree: Bind => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForBind, info.nx.nxPrepBind, tree, cur) - if (mutatedInfo eq null) tree - else { - val body = transform(tree.body, mutatedInfo, cur) - goBind(cpy.Bind(tree)(tree.name, body), mutatedInfo.nx.nxTransBind(cur)) - } - case _ => - tree - } - - final private[TreeTransforms] def transformUnnamed(tree: Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = - tree match { - case tree: Apply => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForApply, info.nx.nxPrepApply, tree, cur) - if (mutatedInfo eq null) tree - else { - val fun = transform(tree.fun, mutatedInfo, cur) - val args = transformSubTrees(tree.args, mutatedInfo, cur) - goApply(cpy.Apply(tree)(fun, args), mutatedInfo.nx.nxTransApply(cur)) - } - case tree: TypeTree => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeTree, info.nx.nxPrepTypeTree, tree, cur) - if (mutatedInfo eq null) tree - else goTypeTree(tree, mutatedInfo.nx.nxTransTypeTree(cur)) - case Thicket(trees) => - cpy.Thicket(tree)(transformTrees(trees, info, cur)) - case tree: This => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForThis, info.nx.nxPrepThis, tree, cur) - if (mutatedInfo eq null) tree - else goThis(tree, mutatedInfo.nx.nxTransThis(cur)) - case tree: Literal => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForLiteral, info.nx.nxPrepLiteral, tree, cur) - if (mutatedInfo eq null) tree - else goLiteral(tree, mutatedInfo.nx.nxTransLiteral(cur)) - case tree: Block => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForBlock, info.nx.nxPrepBlock, tree, cur) - if (mutatedInfo eq null) tree - else { - val stats = transformStats(tree.stats, ctx.owner, mutatedInfo, cur) - val expr = transform(tree.expr, mutatedInfo, cur) - goBlock(cpy.Block(tree)(stats, expr), mutatedInfo.nx.nxTransBlock(cur)) - } - case tree: TypeApply => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeApply, info.nx.nxPrepTypeApply, tree, cur) - if (mutatedInfo eq null) tree - else { - val fun = transform(tree.fun, mutatedInfo, cur) - val args = transformTrees(tree.args, mutatedInfo, cur) - goTypeApply(cpy.TypeApply(tree)(fun, args), mutatedInfo.nx.nxTransTypeApply(cur)) - } - case tree: If => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForIf, info.nx.nxPrepIf, tree, cur) - if (mutatedInfo eq null) tree - else { - val cond = transform(tree.cond, mutatedInfo, cur) - val thenp = transform(tree.thenp, mutatedInfo, cur) - val elsep = transform(tree.elsep, mutatedInfo, cur) - goIf(cpy.If(tree)(cond, thenp, elsep), mutatedInfo.nx.nxTransIf(cur)) - } - case tree: New => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForNew, info.nx.nxPrepNew, tree, cur) - if (mutatedInfo eq null) tree - else { - val tpt = transform(tree.tpt, mutatedInfo, cur) - goNew(cpy.New(tree)(tpt), mutatedInfo.nx.nxTransNew(cur)) - } - case tree: Typed => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTyped, info.nx.nxPrepTyped, tree, cur) - if (mutatedInfo eq null) tree - else { - val expr = transform(tree.expr, mutatedInfo, cur) - val tpt = transform(tree.tpt, mutatedInfo, cur) - goTyped(cpy.Typed(tree)(expr, tpt), mutatedInfo.nx.nxTransTyped(cur)) - } - case tree: CaseDef => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForCaseDef, info.nx.nxPrepCaseDef, tree, cur) - if (mutatedInfo eq null) tree - else { - val pat = transform(tree.pat, mutatedInfo, cur)(ctx.addMode(Mode.Pattern)) - val guard = transform(tree.guard, mutatedInfo, cur) - val body = transform(tree.body, mutatedInfo, cur) - goCaseDef(cpy.CaseDef(tree)(pat, guard, body), mutatedInfo.nx.nxTransCaseDef(cur)) - } - case tree: Closure => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForClosure, info.nx.nxPrepClosure, tree, cur) - if (mutatedInfo eq null) tree - else { - val env = transformTrees(tree.env, mutatedInfo, cur) - val meth = transform(tree.meth, mutatedInfo, cur) - val tpt = transform(tree.tpt, mutatedInfo, cur) - goClosure(cpy.Closure(tree)(env, meth, tpt), mutatedInfo.nx.nxTransClosure(cur)) - } - case tree: Assign => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForAssign, info.nx.nxPrepAssign, tree, cur) - if (mutatedInfo eq null) tree - else { - val lhs = transform(tree.lhs, mutatedInfo, cur) - val rhs = transform(tree.rhs, mutatedInfo, cur) - goAssign(cpy.Assign(tree)(lhs, rhs), mutatedInfo.nx.nxTransAssign(cur)) - } - case tree: SeqLiteral => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSeqLiteral, info.nx.nxPrepSeqLiteral, tree, cur) - if (mutatedInfo eq null) tree - else { - val elems = transformTrees(tree.elems, mutatedInfo, cur) - val elemtpt = transform(tree.elemtpt, mutatedInfo, cur) - goSeqLiteral(cpy.SeqLiteral(tree)(elems, elemtpt), mutatedInfo.nx.nxTransSeqLiteral(cur)) - } - case tree: Super => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSuper, info.nx.nxPrepSuper, tree, cur) - if (mutatedInfo eq null) tree - else { - val qual = transform(tree.qual, mutatedInfo, cur) - goSuper(cpy.Super(tree)(qual, tree.mix), mutatedInfo.nx.nxTransSuper(cur)) - } - case tree: Template => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTemplate, info.nx.nxPrepTemplate, tree, cur) - if (mutatedInfo eq null) tree - else { - val constr = transformSub(tree.constr, mutatedInfo, cur) - val parents = transformTrees(tree.parents, mutatedInfo, cur)(ctx.superCallContext) - val self = transformSub(tree.self, mutatedInfo, cur) - val body = transformStats(tree.body, tree.symbol, mutatedInfo, cur) - goTemplate(cpy.Template(tree)(constr, parents, self, body), mutatedInfo.nx.nxTransTemplate(cur)) - } - case tree: Match => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForMatch, info.nx.nxPrepMatch, tree, cur) - if (mutatedInfo eq null) tree - else { - val selector = transform(tree.selector, mutatedInfo, cur) - val cases = transformSubTrees(tree.cases, mutatedInfo, cur) - goMatch(cpy.Match(tree)(selector, cases), mutatedInfo.nx.nxTransMatch(cur)) - } - case tree: UnApply => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForUnApply, info.nx.nxPrepUnApply, tree, cur) - if (mutatedInfo eq null) tree - else { - val fun = transform(tree.fun, mutatedInfo, cur) - val implicits = transformTrees(tree.implicits, mutatedInfo, cur) - val patterns = transformTrees(tree.patterns, mutatedInfo, cur) - goUnApply(cpy.UnApply(tree)(fun, implicits, patterns), mutatedInfo.nx.nxTransUnApply(cur)) - } - case tree: PackageDef => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForPackageDef, info.nx.nxPrepPackageDef, tree, cur) - if (mutatedInfo eq null) tree - else { - val nestedCtx = localContext(tree.symbol) - val pid = transformSub(tree.pid, mutatedInfo, cur) - val stats = transformStats(tree.stats, tree.symbol, mutatedInfo, cur)(nestedCtx) - goPackageDef(cpy.PackageDef(tree)(pid, stats), mutatedInfo.nx.nxTransPackageDef(cur)) - } - case tree: Try => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTry, info.nx.nxPrepTry, tree, cur) - if (mutatedInfo eq null) tree - else { - val block = transform(tree.expr, mutatedInfo, cur) - val cases1 = tree.cases.mapConserve(transform(_, mutatedInfo, cur)).asInstanceOf[List[CaseDef]] - val finalizer = transform(tree.finalizer, mutatedInfo, cur) - goTry(cpy.Try(tree)(block, cases1, finalizer), mutatedInfo.nx.nxTransTry(cur)) - } - case tree: Inlined => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForInlined, info.nx.nxPrepInlined, tree, cur) - if (mutatedInfo eq null) tree - else { - val bindings = transformSubTrees(tree.bindings, mutatedInfo, cur) - val expansion = transform(tree.expansion, mutatedInfo, cur)(inlineContext(tree)) - goInlined(cpy.Inlined(tree)(tree.call, bindings, expansion), mutatedInfo.nx.nxTransInlined(cur)) - } - case tree: Return => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForReturn, info.nx.nxPrepReturn, tree, cur) - if (mutatedInfo eq null) tree - else { - val expr = transform(tree.expr, mutatedInfo, cur) - val from = tree.from - // don't transform the `from` part, as this is not a normal ident, but - // a pointer to the enclosing method. Transforming this as a normal ident - // can go wrong easily. If a transformation is needed, it should be - // the responsibility of the transformReturn method to handle this also. - goReturn(cpy.Return(tree)(expr, from), mutatedInfo.nx.nxTransReturn(cur)) - } - case tree: Alternative => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForAlternative, info.nx.nxPrepAlternative, tree, cur) - if (mutatedInfo eq null) tree - else { - val trees = transformTrees(tree.trees, mutatedInfo, cur) - goAlternative(cpy.Alternative(tree)(trees), mutatedInfo.nx.nxTransAlternative(cur)) - } - case tree => - implicit val originalInfo: TransformerInfo = info - goOther(tree, info.nx.nxTransOther(cur)) - } - - private[this] var crashingTree: Tree = EmptyTree - - def transform(tree: Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = trace(s"transforming ${tree.show} at ${ctx.phase}", transforms, show = true) { - try - if (cur < info.transformers.length) { - util.Stats.record("TreeTransform.transform") - // if cur > 0 then some of the symbols can be created by already performed transformations - // this means that their denotations could not exists in previous period - val pctx = ctx.withPhase(groupEndId) - tree match { - //split one big match into 2 smaller ones - case tree: NameTree => transformNamed(tree, info, cur)(pctx) - case tree => transformUnnamed(tree, info, cur)(pctx) - } - } else tree - catch { - case NonFatal(ex) => - if (tree ne crashingTree) { - crashingTree = tree - println(i"exception while transforming $tree of class ${tree.getClass} # ${tree.uniqueId}") - } - throw ex - } - } - - @tailrec - final private[TreeTransforms] def goStats(trees: List[Tree], cur: Int)(implicit ctx: Context, info: TransformerInfo): List[Tree] = { - if (cur < info.transformers.length) { - val trans = info.transformers(cur) - val stats = trans.transformStats(trees)(ctx.withPhase(groupEndId), info) - goStats(stats, info.nx.nxTransStats(cur + 1)) - } else trees - } - - def transformStats(trees: List[Tree], exprOwner: Symbol, info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tree] = { - val newInfo = mutateTransformers(info, prepForStats, info.nx.nxPrepStats, trees, current) - def transformStat(stat: Tree): Tree = stat match { - case _: Import | _: DefTree => transform(stat, newInfo, current) - case Thicket(stats) => cpy.Thicket(stat)(stats mapConserve transformStat) - case _ => transform(stat, newInfo, current)(ctx.exprContext(stat, exprOwner)) - } - val newTrees = flatten(trees.mapconserve(transformStat)) - goStats(newTrees, newInfo.nx.nxTransStats(current))(ctx, newInfo) - } - - def transformTrees(trees: List[Tree], info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tree] = - flatten(trees mapConserve (x => transform(x, info, current))) - - def transformSub[Tr <: Tree](tree: Tr, info: TransformerInfo, current: Int)(implicit ctx: Context): Tr = - transform(tree, info, current).asInstanceOf[Tr] - - def transformSubTrees[Tr <: Tree](trees: List[Tr], info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tr] = - transformTrees(trees, info, current)(ctx).asInstanceOf[List[Tr]] - } -}