aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-05-29 12:23:19 +0200
committerMartin Odersky <odersky@gmail.com>2015-06-01 15:04:45 +0200
commit71067e64900b212068328d114edc741c6e12049b (patch)
tree6f20f215fec695897dbc059f8a73fe3ce206f3db /src/dotty/tools/dotc/transform
parent4f50e8fa5b48b5a931224d40b7c6fc0aed3da44b (diff)
downloaddotty-71067e64900b212068328d114edc741c6e12049b.tar.gz
dotty-71067e64900b212068328d114edc741c6e12049b.tar.bz2
dotty-71067e64900b212068328d114edc741c6e12049b.zip
New phase: AugmentScala2Traits
Diffstat (limited to 'src/dotty/tools/dotc/transform')
-rw-r--r--src/dotty/tools/dotc/transform/AugmentScala2Traits.scala96
-rw-r--r--src/dotty/tools/dotc/transform/ResolveSuper.scala3
-rw-r--r--src/dotty/tools/dotc/transform/SymUtils.scala6
3 files changed, 101 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
new file mode 100644
index 000000000..939b4105b
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
@@ -0,0 +1,96 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import TreeTransforms._
+import Contexts.Context
+import Flags._
+import SymUtils._
+import Symbols._
+import SymDenotations._
+import Types._
+import Decorators._
+import DenotTransformers._
+import StdNames._
+import NameOps._
+import ast.Trees._
+
+/** This phase augments Scala2 traits with implementation classes and with additional members
+ * needed for mixin composition.
+ * These symbols would have been added between Unpickling and Mixin in the Scala2 pipeline.
+ * Specifcally, it adds
+ *
+ * - an implementation class which defines a trait constructor and trait method implementations
+ * - trait setters for vals defined in traits
+ *
+ * Furthermore, it expands the names of all private getters and setters in the trait and makes
+ * them not-private.
+ */
+class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransformer with FullParameterization { thisTransform =>
+ import ast.tpd._
+
+ override def phaseName: String = "augmentScala2Traits"
+
+ override def rewiredTarget(referenced: Symbol, derived: Symbol)(implicit ctx: Context) = NoSymbol
+
+ override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = {
+ val cls = impl.symbol.owner.asClass
+ for (mixin <- cls.mixins)
+ if (mixin.is(Scala2x))
+ augmentScala2Trait(mixin, cls)
+ impl
+ }
+
+ private def augmentScala2Trait(mixin: ClassSymbol, cls: ClassSymbol)(implicit ctx: Context): Unit = {
+ if (mixin.implClass.is(Scala2x)) () // nothing to do, mixin was already augmented
+ else {
+ //println(i"creating new implclass for $mixin ${mixin.implClass}")
+ val ops = new MixinOps(cls, thisTransform)
+ import ops._
+
+ val implClass = ctx.newCompleteClassSymbol(
+ owner = mixin.owner,
+ name = mixin.name.implClassName,
+ flags = Abstract | Scala2x,
+ parents = defn.ObjectClass.typeRef :: Nil,
+ assocFile = mixin.assocFile).enteredAfter(thisTransform)
+
+ def implMethod(meth: TermSymbol): Symbol = {
+ val mold =
+ if (meth.isConstructor)
+ meth.copySymDenotation(
+ name = nme.IMPLCLASS_CONSTRUCTOR,
+ info = MethodType(Nil, defn.UnitType))
+ else meth.ensureNotPrivate
+ meth.copy(
+ owner = implClass,
+ name = mold.name.asTermName,
+ flags = Method | JavaStatic | mold.flags & ExpandedName,
+ info = fullyParameterizedType(mold.info, mixin))
+ }
+
+ def traitSetter(getter: TermSymbol) = {
+ val separator = if (getter.is(Private)) nme.EXPAND_SEPARATOR else nme.TRAIT_SETTER_SEPARATOR
+ val expandedGetterName =
+ if (getter.is(ExpandedName)) getter.name
+ else getter.name.expandedName(getter.owner, separator)
+ getter.copy(
+ name = expandedGetterName.setterName,
+ flags = Method | Accessor | ExpandedName,
+ info = MethodType(getter.info.resultType :: Nil, defn.UnitType))
+ }
+
+ for (sym <- mixin.info.decls) {
+ if (needsForwarder(sym) || sym.isConstructor || sym.isGetter && sym.is(Lazy))
+ implClass.enter(implMethod(sym.asTerm))
+ if (sym.isGetter && !sym.is(LazyOrDeferred) && !sym.setter.exists)
+ traitSetter(sym.asTerm).enteredAfter(thisTransform)
+ if (sym.is(PrivateAccessor, butNot = ExpandedName) &&
+ (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set.
+ sym.ensureNotPrivate.installAfter(thisTransform)
+ }
+ ctx.log(i"Scala2x trait decls of $mixin = ${mixin.info.decls.toList.map(_.showDcl)}%\n %")
+ ctx.log(i"Scala2x impl decls of $mixin = ${implClass.info.decls.toList.map(_.showDcl)}%\n %")
+ }
+ }
+}
diff --git a/src/dotty/tools/dotc/transform/ResolveSuper.scala b/src/dotty/tools/dotc/transform/ResolveSuper.scala
index d23e81ab3..27387bca4 100644
--- a/src/dotty/tools/dotc/transform/ResolveSuper.scala
+++ b/src/dotty/tools/dotc/transform/ResolveSuper.scala
@@ -48,7 +48,8 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
override def phaseName: String = "resolveSuper"
- override def runsAfter = Set(classOf[ElimByName]) // verified empirically, need to figure out what the reason is.
+ override def runsAfter = Set(classOf[ElimByName], // verified empirically, need to figure out what the reason is.
+ classOf[AugmentScala2Traits])
/** Returns the symbol that is accessed by a super-accessor in a mixin composition.
*
diff --git a/src/dotty/tools/dotc/transform/SymUtils.scala b/src/dotty/tools/dotc/transform/SymUtils.scala
index df3b183a9..d3e029a74 100644
--- a/src/dotty/tools/dotc/transform/SymUtils.scala
+++ b/src/dotty/tools/dotc/transform/SymUtils.scala
@@ -85,9 +85,9 @@ class SymUtils(val self: Symbol) extends AnyVal {
def field(implicit ctx: Context): Symbol =
self.owner.info.decl(self.asTerm.name.fieldName).suchThat(!_.is(Method)).symbol
- def initializer(implicit ctx: Context): TermSymbol =
- self.owner.info.decl(InitializerName(self.asTerm.name)).symbol.asTerm
-
def isField(implicit ctx: Context): Boolean =
self.isTerm && !self.is(Method)
+
+ def implClass(implicit ctx: Context): Symbol =
+ self.owner.info.decl(self.name.implClassName).symbol
}