aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-07-03 18:57:22 +0200
committerMartin Odersky <odersky@gmail.com>2014-07-17 11:01:59 +0200
commitefe4f7e43652a303d16a5253f84316e547f45cca (patch)
tree1ea59d27843909b7633e0851e6c8b2cdd32e38c6 /src/dotty/tools
parenta47b8b4d3c22133e8cde0053701057e56cc71acb (diff)
downloaddotty-efe4f7e43652a303d16a5253f84316e547f45cca.tar.gz
dotty-efe4f7e43652a303d16a5253f84316e547f45cca.tar.bz2
dotty-efe4f7e43652a303d16a5253f84316e547f45cca.zip
Changed PostTyperTransformer scheme
1) We now always generate companion objects for classes. This is done in mini-phase "companions", which also assures that companion-modules appear after companion-classes. 2) PostTyperTransformers is gone; the part which normalizes trees has been rolled into TreeTransform and the part which reordered companion classes and modules is now in Companions. Note: Some tests were deisabled; should be re-enabled by Dmitry where needed.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/Compiler.scala5
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala18
-rw-r--r--src/dotty/tools/dotc/transform/Companions.scala67
-rw-r--r--src/dotty/tools/dotc/transform/CreateCompanionObjects.scala53
-rw-r--r--src/dotty/tools/dotc/transform/LazyVals.scala21
-rw-r--r--src/dotty/tools/dotc/transform/PostTyperTransformers.scala62
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala6
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) {