diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Phases.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Companions.scala | 67 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/CreateCompanionObjects.scala | 53 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/LazyVals.scala | 21 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/PostTyperTransformers.scala | 62 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/TreeTransform.scala | 6 |
7 files changed, 79 insertions, 153 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 55452d6ff..bf8cf4182 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -11,7 +11,6 @@ import reporting.ConsoleReporter import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.transform._ 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 @@ -20,9 +19,9 @@ class Compiler { def phases: List[List[Phase]] = List( List(new FrontEnd), + List(new Companions), List(new SuperAccessors), - List(new LazyValsCreateCompanionObjects, - new TailRec), //force separataion between lazyVals and LVCreateCO + List(new TailRec), List(new PatternMatcher, new LazyValTranformContext().transformer, new Splitter), diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 7bc5f3052..aabde4cf9 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -9,7 +9,6 @@ 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 import Periods._ @@ -72,12 +71,10 @@ object Phases { /** Squash TreeTransform's beloning to same sublist to a single TreeTransformer * Each TreeTransform gets own period, * whereas a combined TreeTransformer gets period equal to union of periods of it's TreeTransforms - * first TreeTransformer emitted is PostTyperTransformer that simplifies trees, see it's documentation */ private def squashPhases(phasess: List[List[Phase]]): Array[Phase] = { val squashedPhases = ListBuffer[Phase]() var prevPhases: Set[String] = Set.empty - var postTyperEmmited = false var i = 0 while (i < phasess.length) { if (phasess(i).length > 1) { @@ -95,17 +92,10 @@ object Phases { } } val transforms = phasess(i).asInstanceOf[List[TreeTransform]] - val block = - if (!postTyperEmmited) { - postTyperEmmited = true - new PostTyperTransformer { - override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") - override def transformations: Array[TreeTransform] = transforms.toArray - } - } else new TreeTransformer { - override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") - override def transformations: Array[TreeTransform] = transforms.toArray - } + val block = new TreeTransformer { + override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") + override def transformations: Array[TreeTransform] = transforms.toArray + } squashedPhases += block prevPhases ++= phasess(i).map(_.name) block.init(this, phasess(i).head.id, phasess(i).last.id) diff --git a/src/dotty/tools/dotc/transform/Companions.scala b/src/dotty/tools/dotc/transform/Companions.scala new file mode 100644 index 000000000..0e31b511d --- /dev/null +++ b/src/dotty/tools/dotc/transform/Companions.scala @@ -0,0 +1,67 @@ +package dotty.tools.dotc +package transform + +import core._ +import Names._ +import TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer} +import ast.Trees.flatten +import Flags._ +import Contexts.Context +import Symbols._ +import scala.collection.mutable +import DenotTransformers._ +import Names.Name +import NameOps._ + + +/** A transformer that provides a convenient way to create companion objects + */ +class Companions extends TreeTransform with IdentityDenotTransformer { thisTransformer => + import ast.tpd._ + + override def name = "companions" + + /** Reorder statements so that module classes always come after their companion classes, add missing companion classes */ + private def reorderAndComplete(stats: List[Tree])(implicit ctx: Context): List[Tree] = { + val moduleClassDefs, singleClassDefs = mutable.Map[Name, Tree]() + + def reorder(stats: List[Tree]): List[Tree] = stats match { + case (stat: TypeDef) :: stats1 if stat.symbol.isClass => + if (stat.symbol is Flags.Module) { + moduleClassDefs += (stat.name -> stat) + singleClassDefs -= stat.name.stripModuleClassSuffix + val stats1r = reorder(stats1) + if (moduleClassDefs contains stat.name) stat :: stats1r else stats1r + } else { + def stats1r = reorder(stats1) + val normalized = moduleClassDefs remove stat.name.moduleClassName match { + case Some(mcdef) => + mcdef :: stats1r + case None => + singleClassDefs += (stat.name -> stat) + stats1r + } + stat :: normalized + } + case stat :: stats1 => stat :: reorder(stats1) + case Nil => Nil + } + + def newCompanion(name: TermName): Thicket = { + val modul = ctx.newCompleteModuleSymbol(ctx.owner, name, Synthetic, Synthetic, + defn.ObjectClass.typeRef :: Nil, Scopes.newScope) + if (ctx.owner.isClass) modul.enteredAfter(thisTransformer) + ModuleDef(modul, Nil) + } + + def addMissingCompanions(stats: List[Tree]): List[Tree] = stats map { + case stat: TypeDef if singleClassDefs contains stat.name => + Thicket(stat :: newCompanion(stat.name.toTermName).trees) + case stat => stat + } + addMissingCompanions(reorder(stats)) + } + + override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = + ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisTransformer.next))) +} diff --git a/src/dotty/tools/dotc/transform/CreateCompanionObjects.scala b/src/dotty/tools/dotc/transform/CreateCompanionObjects.scala deleted file mode 100644 index b1cc8ea52..000000000 --- a/src/dotty/tools/dotc/transform/CreateCompanionObjects.scala +++ /dev/null @@ -1,53 +0,0 @@ -package dotty.tools.dotc.transform - -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer} -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Contexts.Context -import scala.collection.mutable.ListBuffer -import dotty.tools.dotc.core.{Scopes, Flags} -import dotty.tools.dotc.core.Symbols.NoSymbol -import scala.annotation.tailrec -import dotty.tools.dotc.core._ -import Symbols._ -import scala.Some -import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer} -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Contexts.Context -import scala.collection.mutable -import dotty.tools.dotc.core.Names.Name -import NameOps._ - -/** A transformer that provides a convenient way to create companion objects - */ -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 - - override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[tpd.Tree] = { - @tailrec - def transformStats0(trees: List[Tree], acc: ListBuffer[Tree]): List[Tree] = { - trees match { - case Nil => acc.toList - case (claz: TypeDef) :: stats if claz.symbol.isClass && !(claz.symbol is Flags.Module) => { - val moduleExists = !(claz.symbol.companionModule eq NoSymbol) - if (moduleExists || !predicate(claz)) transformStats0(stats, acc += claz) - else { - val moduleSymbol = ctx.newCompleteModuleSymbol(claz.symbol.owner, claz.name.toTermName, Flags.Synthetic, Flags.Synthetic, List(defn.ObjectClass.typeRef), Scopes.newScope) - if (moduleSymbol.owner.isClass) moduleSymbol.entered - val companion = tpd.ModuleDef(moduleSymbol, List(EmptyTree)).withPos(claz.pos) - acc += claz - acc += companion - transformStats0(stats, acc) - } - } - case stat :: stats => transformStats0(stats, acc += stat) - } - } - - transformStats0(trees, ListBuffer()) - } -} diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index fe6c3e2e4..ecd94a211 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -19,25 +19,6 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation import dotty.tools.dotc.core.SymDenotations.SymDenotation import dotty.tools.dotc.core.DenotTransformers.DenotTransformer - -class LazyValsCreateCompanionObjects extends CreateCompanionObjects { - import tpd._ - - - override def name: String = "lazyValsModules" - - /** Companion classes are required to hold offsets for volatile lazy vals */ - override def predicate(forClass: tpd.TypeDef)(implicit ctx: Context): Boolean = { - (!(forClass.symbol is Flags.Module)) && forClass.rhs.isInstanceOf[Template] && { - val body = forClass.rhs.asInstanceOf[Template].body - body.exists { - case x: ValDef => - (x.mods is Flags.Lazy) && x.symbol.hasAnnotation(defn.VolatileAnnot) - case _ => false - } - } - } -} class LazyValTranformContext { import tpd._ @@ -67,7 +48,7 @@ class LazyValTranformContext { /** List of names of phases that should have finished their processing of all compilation units * before this phase starts */ - override def runsAfterGroupsOf: Set[String] = Set("lazyValsModules") + /** List of names of phases that should have finished their processing of all compilation units * before this phase starts */ diff --git a/src/dotty/tools/dotc/transform/PostTyperTransformers.scala b/src/dotty/tools/dotc/transform/PostTyperTransformers.scala deleted file mode 100644 index 25f122cf5..000000000 --- a/src/dotty/tools/dotc/transform/PostTyperTransformers.scala +++ /dev/null @@ -1,62 +0,0 @@ -package dotty.tools.dotc.transform - -import dotty.tools.dotc.core._ -import Symbols._ -import scala.Some -import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer} -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Contexts.Context -import scala.collection.mutable -import dotty.tools.dotc.core.Names.Name -import NameOps._ - -object PostTyperTransformers { - - import tpd._ - - - /** A trait that's assumed by the transformers that run right after typer. - * Ensures that trees are normalized when seen by other transforms. This means: - * (1) All module class definitions appear after their companion class definitions - * (2) There are no import clauses or named arguments - * (3) All trees designating types are instances of TypeTree - */ - abstract class PostTyperTransformer extends TreeTransformer { - - /** Reorder statements so that module classes always come after their companion classes, add missing companion classes */ - def reorder(stats: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = { - val moduleClassDefs = mutable.Map[Name, Tree]() - def reorder0(stats: List[Tree]): List[Tree] = { - stats match { - case (stat: TypeDef) :: stats1 if stat.symbol.isClass => - if (stat.symbol is Flags.Module) { - moduleClassDefs += (stat.name -> stat) - val stats1r = reorder0(stats1) - if (moduleClassDefs contains stat.name) stat :: stats1r else stats1r - } - else { - val mclsName = stat.name.moduleClassName - moduleClassDefs remove mclsName match { - case Some(mcdef) => stat :: mcdef :: reorder0(stats1) - case None => stat :: reorder0(stats1) - } - } - case stat :: stats1 => stat :: reorder0(stats1) - case Nil => Nil - } - } - reorder0(stats) - } - - override def transformStats(trees: List[tpd.Tree], exprOwner: Symbol, info: TransformerInfo, current: Int)(implicit ctx: Context): List[tpd.Tree] = - super.transformStats(reorder(trees)(ctx, info), exprOwner, info, current) - - override def transform(tree: tpd.Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): tpd.Tree = tree match { - case tree: Import => EmptyTree - case tree: NamedArg => super.transform(tree.arg, info, cur) - case tree: TypeTree => super.transform(tree, info, cur) - case tree => super.transform(if (tree.isType) TypeTree(tree.tpe) else tree, info, cur) - } - } - -}
\ 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 347762678..2bc733465 100644 --- a/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -1124,8 +1124,12 @@ object TreeTransforms { val stats = transformStats(tree.stats, tree.symbol, mutatedInfo, cur)(nestedCtx) goPackageDef(cpy.PackageDef(tree, pid, stats), mutatedInfo.nx.nxTransPackageDef(cur)) } + case tree: Import => EmptyTree + case tree: NamedArg => transform(tree.arg, info, cur) case Thicket(trees) => cpy.Thicket(tree, transformTrees(trees, info, cur)) - case tree => tree + case tree => + if (tree.isType) transform(TypeTree(tree.tpe).withPos(tree.pos), info, cur) + else tree } def transform(tree: Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = ctx.traceIndented(s"transforming ${tree.show} at ${ctx.phase}", transforms, show = true) { |