diff options
author | Martin Odersky <odersky@gmail.com> | 2015-05-29 12:23:19 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-06-01 15:04:45 +0200 |
commit | 71067e64900b212068328d114edc741c6e12049b (patch) | |
tree | 6f20f215fec695897dbc059f8a73fe3ce206f3db /src/dotty/tools/dotc/transform | |
parent | 4f50e8fa5b48b5a931224d40b7c6fc0aed3da44b (diff) | |
download | dotty-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.scala | 96 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ResolveSuper.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/SymUtils.scala | 6 |
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 } |