aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/PrivateToStatic.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/transform/PrivateToStatic.scala')
-rw-r--r--src/dotty/tools/dotc/transform/PrivateToStatic.scala90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/transform/PrivateToStatic.scala b/src/dotty/tools/dotc/transform/PrivateToStatic.scala
new file mode 100644
index 000000000..17f176855
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/PrivateToStatic.scala
@@ -0,0 +1,90 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import DenotTransformers.SymTransformer
+import Contexts.Context
+import Symbols._
+import Scopes._
+import Flags._
+import StdNames._
+import SymDenotations._
+import Types._
+import collection.mutable
+import TreeTransforms._
+import Decorators._
+import ast.Trees._
+import TreeTransforms.TransformerInfo
+
+/** The preceding lambda lift and flatten phases move symbols to different scopes
+ * and rename them. This miniphase cleans up afterwards and makes sure that all
+ * class scopes contain the symbols defined in them.
+ */
+class PrivateToStatic extends MiniPhase with SymTransformer { thisTransform =>
+ import ast.tpd._
+ override def phaseName = "privateToStatic"
+ override def relaxedTyping = true
+
+ private val Immovable = Deferred | Accessor | JavaStatic
+
+ def shouldBeStatic(sd: SymDenotation)(implicit ctx: Context) =
+ sd.current(ctx.withPhase(thisTransform)).asInstanceOf[SymDenotation]
+ .is(PrivateMethod, butNot = Immovable) &&
+ (sd.owner.is(Trait) || sd.is(NotJavaPrivate))
+
+ override def transformSym(sd: SymDenotation)(implicit ctx: Context): SymDenotation =
+ if (shouldBeStatic(sd)) {
+ val mt @ MethodType(pnames, ptypes) = sd.info
+ sd.copySymDenotation(
+ initFlags = sd.flags | JavaStatic,
+ info = MethodType(nme.SELF :: pnames, sd.owner.thisType :: ptypes, mt.resultType))
+ }
+ else sd
+
+ val treeTransform = new Transform(NoSymbol)
+
+ class Transform(thisParam: Symbol) extends TreeTransform {
+ def phase = thisTransform
+ override def treeTransformPhase = thisTransform.next
+
+ override def prepareForDefDef(tree: DefDef)(implicit ctx: Context) =
+ if (shouldBeStatic(tree.symbol)) {
+ val selfParam = ctx.newSymbol(tree.symbol, nme.SELF, Param, tree.symbol.owner.thisType, coord = tree.pos)
+ new Transform(selfParam)
+ }
+ else this
+
+ override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo) =
+ if (shouldBeStatic(tree.symbol)) {
+ val thisParamDef = ValDef(thisParam.asTerm)
+ val vparams :: Nil = tree.vparamss
+ cpy.DefDef(tree)(
+ mods = tree.mods | JavaStatic,
+ vparamss = (thisParamDef :: vparams) :: Nil)
+ }
+ else tree
+
+ override def transformThis(tree: This)(implicit ctx: Context, info: TransformerInfo) =
+ if (shouldBeStatic(ctx.owner.enclosingMethod)) ref(thisParam).withPos(tree.pos)
+ else tree
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) =
+ tree.fun match {
+ case fun @ Select(qual, name) if shouldBeStatic(fun.symbol) =>
+ println(i"mapping $tree to ${cpy.Ident(fun)(name)} (${qual :: tree.args}%, %)")
+ cpy.Apply(tree)(ref(fun.symbol).withPos(fun.pos), qual :: tree.args)
+ case _ =>
+ tree
+ }
+
+ override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo) =
+ tree.meth match {
+ case meth @ Select(qual, name) if shouldBeStatic(meth.symbol) =>
+ cpy.Closure(tree)(
+ env = qual :: tree.env,
+ meth = ref(meth.symbol).withPos(meth.pos))
+ case _ =>
+ tree
+ }
+ }
+}