aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-11-02 11:08:28 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:07 +0100
commit8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch)
treea8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
parent6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff)
downloaddotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform/FirstTransform.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FirstTransform.scala193
1 files changed, 193 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
new file mode 100644
index 000000000..597146514
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -0,0 +1,193 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import Names._
+import dotty.tools.dotc.ast.tpd
+import dotty.tools.dotc.core.Phases.NeedsCompanions
+import dotty.tools.dotc.transform.TreeTransforms._
+import ast.Trees._
+import Flags._
+import Types._
+import Constants.Constant
+import Contexts.Context
+import Symbols._
+import SymDenotations._
+import Decorators._
+import dotty.tools.dotc.core.Annotations.ConcreteAnnotation
+import dotty.tools.dotc.core.Denotations.SingleDenotation
+import scala.collection.mutable
+import DenotTransformers._
+import typer.Checking
+import Names.Name
+import NameOps._
+import StdNames._
+
+
+/** The first tree transform
+ * - ensures there are companion objects for all classes except module classes
+ * - eliminates some kinds of trees: Imports, NamedArgs
+ * - stubs out native methods
+ * - eliminates self tree in Template and self symbol in ClassInfo
+ * - collapsess all type trees to trees of class TypeTree
+ * - converts idempotent expressions with constant types
+ */
+class FirstTransform extends MiniPhaseTransform with InfoTransformer with AnnotationTransformer { thisTransformer =>
+ import ast.tpd._
+
+ override def phaseName = "firstTransform"
+
+ private var addCompanionPhases: List[NeedsCompanions] = _
+
+ def needsCompanion(cls: ClassSymbol)(implicit ctx: Context) =
+ addCompanionPhases.exists(_.isCompanionNeeded(cls))
+
+ override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
+ addCompanionPhases = ctx.phasePlan.flatMap(_ collect { case p: NeedsCompanions => p })
+ this
+ }
+
+ /** eliminate self symbol in ClassInfo */
+ override def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp match {
+ case tp @ ClassInfo(_, _, _, _, self: Symbol) =>
+ tp.derivedClassInfo(selfInfo = self.info)
+ case _ =>
+ tp
+ }
+
+ /*
+ tp match {
+ //create companions for value classes that are not from currently compiled source file
+ case tp@ClassInfo(_, cls, _, decls, _)
+ if (ValueClasses.isDerivedValueClass(cls)) &&
+ !sym.isDefinedInCurrentRun && sym.scalacLinkedClass == NoSymbol =>
+ val newDecls = decls.cloneScope
+ val (modul, mcMethod, symMethod) = newCompanion(sym.name.toTermName, sym)
+ modul.entered
+ mcMethod.entered
+ newDecls.enter(symMethod)
+ tp.derivedClassInfo(decls = newDecls)
+ case _ => tp
+ }
+ }
+ */
+
+ override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
+ tree match {
+ case Select(qual, name) if !name.isOuterSelect && tree.symbol.exists =>
+ assert(qual.tpe derivesFrom tree.symbol.owner, i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe} in $tree")
+ case _: TypeTree =>
+ case _: Import | _: NamedArg | _: TypTree =>
+ assert(false, i"illegal tree: $tree")
+ case _ =>
+ }
+ }
+
+ /** 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 registerCompanion(name: TermName, forClass: Symbol): TermSymbol = {
+ val (modul, mcCompanion, classCompanion) = newCompanion(name, forClass)
+ if (ctx.owner.isClass) modul.enteredAfter(thisTransformer)
+ mcCompanion.enteredAfter(thisTransformer)
+ classCompanion.enteredAfter(thisTransformer)
+ modul
+ }
+
+ def addMissingCompanions(stats: List[Tree]): List[Tree] = stats map {
+ case stat: TypeDef if (singleClassDefs contains stat.name) && needsCompanion(stat.symbol.asClass) =>
+ val objName = stat.name.toTermName
+ val nameClash = stats.exists {
+ case other: MemberDef =>
+ other.name == objName && other.symbol.info.isParameterless
+ case _ =>
+ false
+ }
+ val uniqueName = if (nameClash) objName.avoidClashName else objName
+ Thicket(stat :: ModuleDef(registerCompanion(uniqueName, stat.symbol), Nil).trees)
+ case stat => stat
+ }
+
+ addMissingCompanions(reorder(stats))
+ }
+
+ private def newCompanion(name: TermName, forClass: Symbol)(implicit ctx: Context) = {
+ val modul = ctx.newCompleteModuleSymbol(forClass.owner, name, Synthetic, Synthetic,
+ defn.ObjectType :: Nil, Scopes.newScope, assocFile = forClass.asClass.assocFile)
+ val mc = modul.moduleClass
+
+ val mcComp = ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, forClass, mc)
+ val classComp = ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, mc, forClass)
+ (modul, mcComp, classComp)
+ }
+
+ /** elimiate self in Template */
+ override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ cpy.Template(impl)(self = EmptyValDef)
+ }
+
+ override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
+ if (ddef.symbol.hasAnnotation(defn.NativeAnnot)) {
+ ddef.symbol.resetFlag(Deferred)
+ DefDef(ddef.symbol.asTerm,
+ _ => ref(defn.Sys_errorR).withPos(ddef.pos)
+ .appliedTo(Literal(Constant("native method stub"))))
+ } else ddef
+ }
+
+ override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] =
+ ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisTransformer.next)))
+
+ override def transformOther(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = tree match {
+ case tree: Import => EmptyTree
+ case tree: NamedArg => transform(tree.arg)
+ case tree => if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
+ }
+
+ override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) =
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ else constToLiteral(tree)
+
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ else constToLiteral(tree)
+
+ override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
+ override def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
+ override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
+ // invariants: all modules have companion objects
+ // all types are TypeTrees
+ // all this types are explicit
+}