From 09d02bd3670b947da147aec40835822d894b17b0 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Mon, 17 Mar 2014 22:25:47 +0100 Subject: Allow MiniPhase to be DenotTransformer All MiniPhases now as are full-fledged phases, and are given their own periods and can register DenotTransformers. MiniPhases belonging to same group(list) will be squashed to single phase. --- src/dotty/tools/dotc/Compiler.scala | 12 +- src/dotty/tools/dotc/core/Contexts.scala | 11 +- src/dotty/tools/dotc/core/DenotTransformers.scala | 2 +- src/dotty/tools/dotc/core/Denotations.scala | 13 +- src/dotty/tools/dotc/core/Periods.scala | 6 +- src/dotty/tools/dotc/core/Phases.scala | 76 +++++++++-- .../dotc/transform/CreateCompanionObjects.scala | 4 +- src/dotty/tools/dotc/transform/SamplePhase.scala | 55 -------- src/dotty/tools/dotc/transform/TreeTransform.scala | 148 +++++++++++++++------ .../dotc/transform/UncurryTreeTransform.scala | 51 +++++++ 10 files changed, 252 insertions(+), 126 deletions(-) delete mode 100644 src/dotty/tools/dotc/transform/SamplePhase.scala create mode 100644 src/dotty/tools/dotc/transform/UncurryTreeTransform.scala (limited to 'src/dotty/tools/dotc') diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 132a25d0b..c2f21f639 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -8,14 +8,20 @@ import Symbols._ import typer.{FrontEnd, Typer, Mode, ImportInfo} import reporting.ConsoleReporter import dotty.tools.dotc.core.Phases.Phase -import dotty.tools.dotc.transform.{LazyValsCreateCompanionObjects, LazyValTranformContext} +import dotty.tools.dotc.transform.{UncurryTreeTransform, LazyValsCreateCompanionObjects, LazyValTranformContext} import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer} import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer +import dotty.tools.dotc.core.DenotTransformers.DenotTransformer +import dotty.tools.dotc.core.Denotations.SingleDenotation +import dotty.tools.dotc.transform.TreeTransforms.Separator class Compiler { - - def phases: List[Phase] = List(new FrontEnd, new transform.SamplePhase) + def phases: List[List[Phase]] = List( + List(new FrontEnd), List(new LazyValsCreateCompanionObjects), + //force separataion between lazyVals and LVCreateCO + List(new LazyValTranformContext().transformer, new UncurryTreeTransform) + ) var runId = 1 def nextRunId = { diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 38784ec0c..68daea440 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -25,7 +25,7 @@ import collection.immutable.BitSet import printing._ import config.{Settings, ScalaSettings, Platform, JavaPlatform} import language.implicitConversions - +import DenotTransformers.DenotTransformer object Contexts { /** A context is passed basically everywhere in dotc. @@ -387,7 +387,7 @@ object Contexts { def rootLoader(root: TermSymbol)(implicit ctx: Context): SymbolLoader = platform.rootLoader(root) // Set up some phases to get started */ - usePhases(SomePhase :: Nil) + usePhases(List(List(SomePhase))) /** The standard definitions */ val definitions = new Definitions @@ -460,8 +460,13 @@ object Contexts { /** Phases by id */ private[core] var phases: Array[Phase] = _ + /** Phases with consecutive Transforms groupped into a single phase */ + private [core] var squashedPhases: Array[Phase] = _ + /** Next denotation transformer id */ - private[core] var nextTransformerId: Array[Int] = _ + private[core] var nextDenotTransformerId: Array[Int] = _ + + private[core] var denotTransformers: Array[DenotTransformer] = _ // Printers state /** Number of recursive invocations of a show method on cuyrrent stack */ diff --git a/src/dotty/tools/dotc/core/DenotTransformers.scala b/src/dotty/tools/dotc/core/DenotTransformers.scala index be85b5877..e1ee355d8 100644 --- a/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -21,7 +21,7 @@ object DenotTransformers { trait DenotTransformer extends Phase { /** The last phase during which the transformed denotations are valid */ - def lastPhaseId(implicit ctx: Context) = ctx.nextTransformerId(id + 1) + def lastPhaseId(implicit ctx: Context) = ctx.nextDenotTransformerId(id + 1) /** The validity period of the transformer in the given context */ def validFor(implicit ctx: Context): Period = diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index b35647ead..e15c70637 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -501,6 +501,8 @@ object Denotations { def current(implicit ctx: Context): SingleDenotation = { val currentPeriod = ctx.period val valid = myValidFor + assert(valid.code > 0, s"negative period $valid: ${valid.code}") + if (valid.runId != currentPeriod.runId) bringForward.current else { var cur = this @@ -514,12 +516,15 @@ object Denotations { if (next.validFor.code > valid.code) { // in this case, next.validFor contains currentPeriod cur = next + cur } else { // not found, cur points to highest existing variant var startPid = cur.validFor.lastPhaseId + 1 - val transformer = ctx.phases(startPid - 1).asInstanceOf[DenotTransformer] + val nextTranformerId = ctx.nextDenotTransformerId(startPid) + val transformer = ctx.denotTransformers(nextTranformerId) //println(s"transforming with $transformer") - next = transformer.transform(cur).syncWithParents + if (currentPeriod.lastPhaseId > transformer.id) + next = transformer.transform(cur).syncWithParents if (next eq cur) startPid = cur.validFor.firstPhaseId else { @@ -534,6 +539,7 @@ object Denotations { cur.validFor = Period( currentPeriod.runId, startPid, transformer.lastPhaseId) //println(s"new denot: $cur, valid for ${cur.validFor}") + cur.current // multiple transformations could be required } } else { // currentPeriod < end of valid; in this case a version must exist @@ -545,8 +551,9 @@ object Denotations { cnt += 1 assert(cnt <= MaxPossiblePhaseId, s"seems to be a loop in Denotations for $this, currentPeriod = $currentPeriod") } + cur } - cur + } } diff --git a/src/dotty/tools/dotc/core/Periods.scala b/src/dotty/tools/dotc/core/Periods.scala index 1c9fbf0c6..61f395c7d 100644 --- a/src/dotty/tools/dotc/core/Periods.scala +++ b/src/dotty/tools/dotc/core/Periods.scala @@ -32,8 +32,8 @@ abstract class Periods extends DotClass { self: Context => */ def stablePeriod = { var first = phaseId - val nxTrans = ctx.base.nextTransformerId(first) - while (first - 1 > NoPhaseId && (ctx.base.nextTransformerId(first - 1) == nxTrans)) { + val nxTrans = ctx.base.nextDenotTransformerId(first) + while (first - 1 > NoPhaseId && (ctx.base.nextDenotTransformerId(first - 1) == nxTrans)) { first -= 1 } Period(runId, first, nxTrans) @@ -49,6 +49,8 @@ object Periods { * runid 21 bits * last phase id: 5 bits * #phases before last: 5 bits + * + * // Dmitry: sign == 0 isn't actually always true, in some cases phaseId == -1 is used for shifts, that easily creates code < 0 */ class Period(val code: Int) extends AnyVal { diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 81ab7acbf..c49d314bc 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -7,8 +7,15 @@ import util.DotClass import DenotTransformers._ import Denotations._ import config.Printers._ +import scala.collection.mutable.{ListBuffer, ArrayBuffer} +import dotty.tools.dotc.transform.TreeTransforms.{TreeTransformer, TreeTransform} +import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer +import dotty.tools.dotc.transform.TreeTransforms +import TreeTransforms.Separator + +trait Phases { + self: Context => -trait Phases { self: Context => import Phases._ def phase: Phase = base.phases(period.phaseId) @@ -32,9 +39,13 @@ trait Phases { self: Context => object Phases { - trait PhasesBase { this: ContextBase => + trait PhasesBase { + this: ContextBase => + + // drop NoPhase at beginning + def allPhases = squashedPhases.tail + - def allPhases = phases.tail // drop NoPhase at beginning object NoPhase extends Phase { override def exists = false @@ -62,10 +73,12 @@ object Phases { /** Use the following phases in the order they are given. * The list should never contain NoPhase. + * if squashing is enabled, phases in same subgroup will be squashed to single phase. */ - def usePhases(phases: List[Phase]) = { - this.phases = (NoPhase :: phases ::: new TerminalPhase :: Nil).toArray - this.nextTransformerId = new Array[Int](this.phases.length) + def usePhases(phases: List[List[Phase]], squash: Boolean = true) = { + this.phases = (NoPhase :: phases.flatten ::: new TerminalPhase :: Nil).toArray + this.nextDenotTransformerId = new Array[Int](this.phases.length) + this.denotTransformers = new Array[DenotTransformer](this.phases.length) var i = 0 while (i < this.phases.length) { this.phases(i)._id = i @@ -74,11 +87,48 @@ object Phases { var lastTransformerId = i while (i > 0) { i -= 1 - if (this.phases(i).isInstanceOf[DenotTransformer]) lastTransformerId = i - nextTransformerId(i) = lastTransformerId + this.phases(i) match { + case transformer: DenotTransformer => + lastTransformerId = i + denotTransformers(i) = transformer + case _ => + } + nextDenotTransformerId(i) = lastTransformerId } + + if (squash) { + val squashedPhases = ListBuffer[Phase]() + var postTyperEmmited = false + var i = 0 + while (i < phases.length) { + if (phases(i).length > 1) { + assert(phases(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed") + + val transforms = phases(i).asInstanceOf[List[TreeTransform]] + val block = + if (!postTyperEmmited) { + postTyperEmmited = true + new PostTyperTransformer { + override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") + override protected def transformations: Array[TreeTransform] = transforms.toArray + } + } else new TreeTransformer { + override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") + override protected def transformations: Array[TreeTransform] = transforms.toArray + } + squashedPhases += block + block._id = phases(i).head.id + } else squashedPhases += phases(i).head + i += 1 + } + this.squashedPhases = (NoPhase::squashedPhases.toList :::new TerminalPhase :: Nil).toArray + } else { + this.squashedPhases = this.phases + } + config.println(s"Phases = ${this.phases.deep}") - config.println(s"nextTransformId = ${nextTransformerId.deep}") + config.println(s"squashedPhases = ${this.squashedPhases.deep}") + config.println(s"nextDenotTransformerId = ${nextDenotTransformerId.deep}") } final val typerName = "typer" @@ -110,12 +160,12 @@ object Phases { private[Phases] var _id = -1 /** The sequence position of this phase in the given context where 0 - * is reserved for NoPhase and the first real phase is at position 1. - * -1 if the phase is not installed in the context. + * is reserved for NoPhase and the first real phase is at position 1. + * -1 if the phase is not installed in the context. */ def id = _id - final def <= (that: Phase)(implicit ctx: Context) = + final def <=(that: Phase)(implicit ctx: Context) = exists && id <= that.id final def prev(implicit ctx: Context): Phase = @@ -131,7 +181,7 @@ object Phases { final def erasedTypes(implicit ctx: Context): Boolean = ctx.erasurePhase <= this final def flatClasses(implicit ctx: Context): Boolean = ctx.flattenPhase <= this - final def refChecked (implicit ctx: Context): Boolean = ctx.refchecksPhase <= this + final def refChecked(implicit ctx: Context): Boolean = ctx.refchecksPhase <= this override def toString = name } diff --git a/src/dotty/tools/dotc/transform/CreateCompanionObjects.scala b/src/dotty/tools/dotc/transform/CreateCompanionObjects.scala index 8560b6f6d..f1131b3f2 100644 --- a/src/dotty/tools/dotc/transform/CreateCompanionObjects.scala +++ b/src/dotty/tools/dotc/transform/CreateCompanionObjects.scala @@ -19,13 +19,13 @@ import NameOps._ /** A transformer that provides a convenient way to create companion objects */ -abstract class CreateCompanionObjects(group: TreeTransformer, idx: Int) extends TreeTransform(group, idx) { +abstract class CreateCompanionObjects extends TreeTransform { import tpd._ /** Given class definition should return true if companion object creation should be enforced */ - def predicate(cls: TypeDef)(implicit ctx:Context): Boolean + def predicate(cls: TypeDef)(implicit ctx: Context): Boolean override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[tpd.Tree] = { @tailrec diff --git a/src/dotty/tools/dotc/transform/SamplePhase.scala b/src/dotty/tools/dotc/transform/SamplePhase.scala deleted file mode 100644 index ed4ac113f..000000000 --- a/src/dotty/tools/dotc/transform/SamplePhase.scala +++ /dev/null @@ -1,55 +0,0 @@ -package dotty.tools.dotc -package transform - -import TreeTransforms._ -import core.DenotTransformers._ -import core.Denotations._ -import core.SymDenotations._ -import core.Contexts._ -import core.Types._ -import ast.Trees._ -import ast.tpd.{Apply, Tree, cpy} - -class SamplePhase extends TreeTransformer with DenotTransformer { - def name = "sample" - def transformations = Array(new UncurryTreeTransform(_, _)) - - def uncurry(tp: Type)(implicit ctx: Context): Type = tp match { - case tp @ MethodType(pnames1, ptypes1) => - tp.resultType match { - case rt @ MethodType(pnames2, ptypes2) => - tp.derivedMethodType(pnames1 ++ pnames2, ptypes1 ++ ptypes2, rt.resultType) - case _ => - tp - } - case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramBounds, uncurry(tp.resultType)) - case _ => - tp - } - - def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = { - val info1 = uncurry(ref.info) - if (info1 eq ref.info) ref - else ref match { - case ref: SymDenotation => ref.copySymDenotation(info = info1) - case _ => ref.derivedSingleDenotation(ref.symbol, info1) - } - } -} - -class UncurryTreeTransform(group: TreeTransformer, idx: Int) extends TreeTransform(group, idx) { - - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = - ctx.traceIndented(s"transforming ${tree.show}", show = true) { - tree.fun match { - case Apply(fn, args) => - def showType(implicit ctx: Context) = - ctx.log(s"at ${ctx.phase} ${fn.symbol} has type ${fn.symbol.info.widen.show}") - showType - ctx.atNextPhase(showType(_)) - showType - cpy.Apply(tree, fn, args ++ tree.args) - case _ => tree - }} -} \ No newline at end of file diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala index 3e29af0e4..6455b6062 100644 --- a/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -46,7 +46,10 @@ object TreeTransforms { * (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. */ - class TreeTransform(group: TreeTransformer, idx: Int) { + abstract class TreeTransform extends Phase { + + /** id of this treeTransform in group */ + var idx: Int = _ def prepareForIdent(tree: Ident) = this def prepareForSelect(tree: Select) = this @@ -100,7 +103,7 @@ object TreeTransforms { def transformTry(tree: Try)(implicit ctx: Context, info: TransformerInfo): Tree = tree def transformThrow(tree: Throw)(implicit ctx: Context, info: TransformerInfo): Tree = tree def transformSeqLiteral(tree: SeqLiteral)(implicit ctx: Context, info: TransformerInfo): Tree = tree - def transformTypeTree(tree: TypeTree)(implicit ctx: Context): Tree = tree + def transformTypeTree(tree: TypeTree)(implicit ctx: Context, info: TransformerInfo): Tree = tree def transformSelectFromTypeTree(tree: SelectFromTypeTree)(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 @@ -113,23 +116,42 @@ object TreeTransforms { def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = trees /** Transform tree using all transforms of current group (including this one) */ - def transform(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = group.transform(tree, info, 0) + 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 = group.transform(tree, info, idx + 1) + def transformFollowingDeep(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = info.group.transform(tree, info, 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 = group.transformSingle(tree, idx + 1) + def transformFollowing(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = info.group.transformSingle(tree, idx + 1) /** perform context-dependant initialization */ - def init(implicit ctx:Context): Unit = {} + def init(implicit ctx:Context, info: TransformerInfo): Unit = {} + + protected def mkTreeTransformer = new TreeTransformer { + override def name: String = TreeTransform.this.name + override protected def transformations = Array(TreeTransform.this) + } + + override def run(implicit ctx: Context): Unit = { + mkTreeTransformer.run + } } - val NoTransform = new TreeTransform(null, -1) + val NoTransform = new TreeTransform { + override def name: String = "NoTransform" + idx = -1 + } + + class Separator extends TreeTransform { + override def name: String = "Separator" + idx = -1 + } type Mutator[T] = (TreeTransform, T) => TreeTransform - class TransformerInfo(val transformers: Array[TreeTransform], val nx: NXTransformations) {} + class TransformerInfo(val transformers: Array[TreeTransform], val nx: NXTransformations, val group:TreeTransformer, val contexts:Array[Context]) { + assert(transformers.size == contexts.size) + } /** * This class maintains track of which methods are redefined in MiniPhases and creates execution plans for transformXXX and prepareXXX @@ -392,7 +414,7 @@ object TreeTransforms { /** A group of tree transforms that are applied in sequence during the same phase */ abstract class TreeTransformer extends Phase { - protected def transformations: Array[(TreeTransformer, Int) => TreeTransform] + protected def transformations: Array[TreeTransform] override def run(implicit ctx: Context): Unit = { val curTree = ctx.compilationUnit.tpdTree @@ -425,7 +447,7 @@ object TreeTransforms { } if (allDone) null else if (!transformersCopied) info - else new TransformerInfo(result, resultNX) + else new TransformerInfo(result, resultNX, info.group, info.contexts) } val prepForIdent: Mutator[Ident] = (trans, tree) => trans.prepareForIdent(tree) @@ -461,15 +483,23 @@ object TreeTransforms { val prepForStats: Mutator[List[Tree]]= (trans, trees) => trans.prepareForStats(trees) def transform(t: Tree)(implicit ctx: Context): Tree = { - val initialTransformations = transformations.zipWithIndex.map(x => x._1(this, x._2)) - initialTransformations.foreach(_.init) - transform(t, new TransformerInfo(initialTransformations, new NXTransformations(initialTransformations)), 0) + val initialTransformations = transformations + val contexts = initialTransformations.map(tr => ctx.fresh.withPhase(tr).ctx) + val info = new TransformerInfo(initialTransformations, new NXTransformations(initialTransformations), this, contexts) + initialTransformations.zipWithIndex.foreach{ + case (transform, id) => + transform.idx = id + transform.init(ctx, info) + } + transform(t, info, 0) } @tailrec final private[TreeTransforms] def goIdent(tree: Ident, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformIdent(tree) match { + val trans = info.transformers(cur) + + trans.transformIdent(tree)(info.contexts(cur), info) match { case t: Ident => goIdent(t, info.nx.nxTransIdent(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -479,7 +509,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goSelect(tree: Select, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformSelect(tree) match { + val trans = info.transformers(cur) + trans.transformSelect(tree)(info.contexts(cur), info) match { case t: Select => goSelect(t, info.nx.nxTransSelect(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -489,7 +520,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goThis(tree: This, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformThis(tree) match { + val trans = info.transformers(cur) + trans.transformThis(tree)(info.contexts(cur), info) match { case t: This => goThis(t, info.nx.nxTransThis(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -499,7 +531,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goSuper(tree: Super, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformSuper(tree) match { + val trans = info.transformers(cur) + trans.transformSuper(tree)(info.contexts(cur), info) match { case t: Super => goSuper(t, info.nx.nxTransSuper(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -509,7 +542,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goApply(tree: Apply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformApply(tree) match { + val trans = info.transformers(cur) + trans.transformApply(tree)(info.contexts(cur), info) match { case t: Apply => goApply(t, info.nx.nxTransApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -519,7 +553,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goTypeApply(tree: TypeApply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformTypeApply(tree) match { + val trans = info.transformers(cur) + trans.transformTypeApply(tree)(info.contexts(cur), info) match { case t: TypeApply => goTypeApply(t, info.nx.nxTransTypeApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -529,7 +564,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goNew(tree: New, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformNew(tree) match { + val trans = info.transformers(cur) + trans.transformNew(tree)(info.contexts(cur), info) match { case t: New => goNew(t, info.nx.nxTransNew(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -539,7 +575,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goPair(tree: Pair, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformPair(tree) match { + val trans = info.transformers(cur) + trans.transformPair(tree)(info.contexts(cur), info) match { case t: Pair => goPair(t, info.nx.nxTransPair(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -549,7 +586,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goTyped(tree: Typed, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformTyped(tree) match { + val trans = info.transformers(cur) + trans.transformTyped(tree)(info.contexts(cur), info) match { case t: Typed => goTyped(t, info.nx.nxTransTyped(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -559,7 +597,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goAssign(tree: Assign, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformAssign(tree) match { + val trans = info.transformers(cur) + trans.transformAssign(tree)(info.contexts(cur), info) match { case t: Assign => goAssign(t, info.nx.nxTransAssign(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -569,7 +608,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goLiteral(tree: Literal, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformLiteral(tree) match { + val trans = info.transformers(cur) + trans.transformLiteral(tree)(info.contexts(cur), info) match { case t: Literal => goLiteral(t, info.nx.nxTransLiteral(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -579,7 +619,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goBlock(tree: Block, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformBlock(tree) match { + val trans = info.transformers(cur) + trans.transformBlock(tree)(info.contexts(cur), info) match { case t: Block => goBlock(t, info.nx.nxTransBlock(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -589,7 +630,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goIf(tree: If, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformIf(tree) match { + val trans = info.transformers(cur) + trans.transformIf(tree)(info.contexts(cur), info) match { case t: If => goIf(t, info.nx.nxTransIf(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -599,7 +641,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goClosure(tree: Closure, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformClosure(tree) match { + val trans = info.transformers(cur) + trans.transformClosure(tree)(info.contexts(cur), info) match { case t: Closure => goClosure(t, info.nx.nxTransClosure(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -609,7 +652,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goMatch(tree: Match, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformMatch(tree) match { + val trans = info.transformers(cur) + trans.transformMatch(tree)(info.contexts(cur), info) match { case t: Match => goMatch(t, info.nx.nxTransMatch(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -619,7 +663,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goCaseDef(tree: CaseDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformCaseDef(tree) match { + val trans = info.transformers(cur) + trans.transformCaseDef(tree)(info.contexts(cur), info) match { case t: CaseDef => goCaseDef(t, info.nx.nxTransCaseDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -629,7 +674,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goReturn(tree: Return, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformReturn(tree) match { + val trans = info.transformers(cur) + trans.transformReturn(tree)(info.contexts(cur), info) match { case t: Return => goReturn(t, info.nx.nxTransReturn(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -639,7 +685,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goTry(tree: Try, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformTry(tree) match { + val trans = info.transformers(cur) + trans.transformTry(tree)(info.contexts(cur), info) match { case t: Try => goTry(t, info.nx.nxTransTry(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -649,7 +696,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goThrow(tree: Throw, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformThrow(tree) match { + val trans = info.transformers(cur) + trans.transformThrow(tree)(info.contexts(cur), info) match { case t: Throw => goThrow(t, info.nx.nxTransThrow(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -659,7 +707,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goSeqLiteral(tree: SeqLiteral, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformSeqLiteral(tree) match { + val trans = info.transformers(cur) + trans.transformSeqLiteral(tree)(info.contexts(cur), info) match { case t: SeqLiteral => goSeqLiteral(t, info.nx.nxTransSeqLiteral(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -669,7 +718,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goTypeTree(tree: TypeTree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformTypeTree(tree) match { + val trans = info.transformers(cur) + trans.transformTypeTree(tree)(info.contexts(cur), info) match { case t: TypeTree => goTypeTree(t, info.nx.nxTransTypeTree(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -679,7 +729,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goSelectFromTypeTree(tree: SelectFromTypeTree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformSelectFromTypeTree(tree) match { + val trans = info.transformers(cur) + trans.transformSelectFromTypeTree(tree)(info.contexts(cur), info) match { case t: SelectFromTypeTree => goSelectFromTypeTree(t, info.nx.nxTransSelectFromTypeTree(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -689,7 +740,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goBind(tree: Bind, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformBind(tree) match { + val trans = info.transformers(cur) + trans.transformBind(tree)(info.contexts(cur), info) match { case t: Bind => goBind(t, info.nx.nxTransBind(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -699,7 +751,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goAlternative(tree: Alternative, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformAlternative(tree) match { + val trans = info.transformers(cur) + trans.transformAlternative(tree)(info.contexts(cur), info) match { case t: Alternative => goAlternative(t, info.nx.nxTransAlternative(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -709,7 +762,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goValDef(tree: ValDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformValDef(tree) match { + val trans = info.transformers(cur) + trans.transformValDef(tree)(info.contexts(cur), info) match { case t: ValDef => goValDef(t, info.nx.nxTransValDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -719,7 +773,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goDefDef(tree: DefDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformDefDef(tree) match { + val trans = info.transformers(cur) + trans.transformDefDef(tree)(info.contexts(cur), info) match { case t: DefDef => goDefDef(t, info.nx.nxTransDefDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -729,7 +784,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goUnApply(tree: UnApply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformUnApply(tree) match { + val trans = info.transformers(cur) + trans.transformUnApply(tree)(info.contexts(cur), info) match { case t: UnApply => goUnApply(t, info.nx.nxTransUnApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -739,7 +795,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goTypeDef(tree: TypeDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformTypeDef(tree) match { + val trans = info.transformers(cur) + trans.transformTypeDef(tree)(info.contexts(cur), info) match { case t: TypeDef => goTypeDef(t, info.nx.nxTransTypeDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -749,7 +806,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goTemplate(tree: Template, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformTemplate(tree) match { + val trans = info.transformers(cur) + trans.transformTemplate(tree)(info.contexts(cur), info) match { case t: Template => goTemplate(t, info.nx.nxTransTemplate(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -759,7 +817,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goPackageDef(tree: PackageDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { - info.transformers(cur).transformPackageDef(tree) match { + val trans = info.transformers(cur) + trans.transformPackageDef(tree)(info.contexts(cur), info) match { case t: PackageDef => goPackageDef(t, info.nx.nxTransPackageDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -1069,7 +1128,8 @@ object TreeTransforms { @tailrec final private[TreeTransforms] def goStats(trees: List[Tree], cur: Int)(implicit ctx: Context, info: TransformerInfo): List[Tree] = { if (cur < info.transformers.length) { - val stats = info.transformers(cur).transformStats(trees) + val trans = info.transformers(cur) + val stats = trans.transformStats(trees) goStats(stats, info.nx.nxTransStats(cur + 1)) } else trees } diff --git a/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala b/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala new file mode 100644 index 000000000..fe50e41cd --- /dev/null +++ b/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala @@ -0,0 +1,51 @@ +package dotty.tools.dotc +package transform + +import TreeTransforms._ +import core.DenotTransformers._ +import core.Denotations._ +import core.SymDenotations._ +import core.Contexts._ +import core.Types._ +import ast.Trees._ +import ast.tpd.{Apply, Tree, cpy} + +class UncurryTreeTransform extends TreeTransform with DenotTransformer { + + override def name: String = "uncurry" + override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = + ctx.traceIndented(s"transforming ${tree.show}", show = true) { + tree.fun match { + case Apply(fn, args) => + def showType(implicit ctx: Context) = + ctx.log(s"at ${ctx.phase} ${fn.symbol} has type ${fn.symbol.info.widen.show}") + showType + ctx.atNextPhase(showType(_)) + showType + cpy.Apply(tree, fn, args ++ tree.args) + case _ => tree + }} + + def uncurry(tp: Type)(implicit ctx: Context): Type = tp match { + case tp @ MethodType(pnames1, ptypes1) => + tp.resultType match { + case rt @ MethodType(pnames2, ptypes2) => + tp.derivedMethodType(pnames1 ++ pnames2, ptypes1 ++ ptypes2, rt.resultType) + case _ => + tp + } + case tp: PolyType => + tp.derivedPolyType(tp.paramNames, tp.paramBounds, uncurry(tp.resultType)) + case _ => + tp + } + + def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = { + val info1 = uncurry(ref.info) + if (info1 eq ref.info) ref + else ref match { + case ref: SymDenotation => ref.copySymDenotation(info = info1) + case _ => ref.derivedSingleDenotation(ref.symbol, info1) + } + } +} \ No newline at end of file -- cgit v1.2.3