Skip to content

Commit 9cd9d97

Browse files
committed
Merge pull request #64 from DarkDimius/PostTyperTransformer
Post typer transformer
2 parents 194be91 + b6cb517 commit 9cd9d97

10 files changed

+421
-46
lines changed

src/dotty/tools/dotc/ast/tpd.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
278278
*/
279279
def ModuleDef(sym: TermSymbol, body: List[Tree])(implicit ctx: Context): tpd.Thicket = {
280280
val modcls = sym.moduleClass.asClass
281-
val constr = DefDef(modcls.primaryConstructor.asTerm, EmptyTree)
281+
val constrSym = modcls.primaryConstructor orElse ctx.newDefaultConstructor(modcls).entered
282+
val constr = DefDef(constrSym.asTerm, EmptyTree)
282283
val clsdef = ClassDef(modcls, constr, body)
283284
val valdef = ValDef(sym, New(modcls.typeRef))
284285
Thicket(valdef, clsdef)

src/dotty/tools/dotc/core/Flags.scala

+5-1
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,14 @@ object Flags {
395395
// --------- Combined Flag Sets and Conjunctions ----------------------
396396

397397
/** Flags representing source modifiers */
398-
final val ModifierFlags =
398+
final val SourceModifierFlags =
399399
commonFlags(Private, Protected, Abstract, Final,
400400
Sealed, Case, Implicit, Override, AbsOverride, Lazy)
401401

402+
/** Flags representing modifiers that can appear in trees */
403+
final val ModifierFlags =
404+
SourceModifierFlags | Trait | Module | Param | Synthetic | Package
405+
402406
/** Flags representing access rights */
403407
final val AccessFlags = Private | Protected | Local
404408

src/dotty/tools/dotc/core/Symbols.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ trait Symbols { this: Context =>
132132
infoFn(module, modcls), privateWithin)
133133
val mdenot = SymDenotation(
134134
module, owner, name, modFlags | ModuleCreationFlags,
135-
if (cdenot.isCompleted) TypeRef(owner.thisType, modclsName) withSym modcls
135+
if (cdenot.isCompleted) TypeRef.withSymAndName(owner.thisType, modcls, modclsName)
136136
else new ModuleCompleter(modcls))
137137
module.denot = mdenot
138138
modcls.denot = cdenot
@@ -157,7 +157,7 @@ trait Symbols { this: Context =>
157157
newModuleSymbol(
158158
owner, name, modFlags, clsFlags,
159159
(module, modcls) => ClassInfo(
160-
owner.thisType, modcls, parents, decls, TermRef(owner.thisType, name) withSym module),
160+
owner.thisType, modcls, parents, decls, TermRef.withSymAndName(owner.thisType, module, name)),
161161
privateWithin, coord, assocFile)
162162

163163
/** Create a package symbol with associated package class

src/dotty/tools/dotc/core/Types.scala

+8-4
Original file line numberDiff line numberDiff line change
@@ -1167,8 +1167,10 @@ object Types {
11671167
def apply(prefix: Type, name: TermName)(implicit ctx: Context): TermRef =
11681168
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TermRef]
11691169
def apply(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
1170-
if (prefix eq NoPrefix) unique(new NoPrefixTermRef(sym.name, sym))
1171-
else apply(prefix, sym.name) withSym sym
1170+
withSymAndName(prefix, sym, sym.name)
1171+
def withSymAndName(prefix: Type, sym: TermSymbol, name: TermName)(implicit ctx: Context): TermRef =
1172+
if (prefix eq NoPrefix) unique(new NoPrefixTermRef(name, sym))
1173+
else apply(prefix, name) withSym sym
11721174
def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef =
11731175
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm) else apply(prefix, name)) withDenot denot
11741176
def withSig(prefix: Type, name: TermName, sig: Signature)(implicit ctx: Context): TermRef =
@@ -1182,8 +1184,10 @@ object Types {
11821184
def apply(prefix: Type, name: TypeName)(implicit ctx: Context): TypeRef =
11831185
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TypeRef]
11841186
def apply(prefix: Type, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
1185-
if (prefix eq NoPrefix) unique(new NoPrefixTypeRef(sym.name, sym))
1186-
else apply(prefix, sym.name) withSym sym
1187+
withSymAndName(prefix, sym, sym.name)
1188+
def withSymAndName(prefix: Type, sym: TypeSymbol, name: TypeName)(implicit ctx: Context): TypeRef =
1189+
if (prefix eq NoPrefix) unique(new NoPrefixTypeRef(name, sym))
1190+
else apply(prefix, name) withSym sym
11871191
def apply(prefix: Type, name: TypeName, denot: Denotation)(implicit ctx: Context): TypeRef =
11881192
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asType) else apply(prefix, name)) withDenot denot
11891193
}

src/dotty/tools/dotc/printing/RefinedPrinter.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
1515

1616
override protected def recursionLimitExceeded() = {}
1717

18-
protected val PrintableFlags = (ModifierFlags | Label | Module).toCommonFlags
18+
protected val PrintableFlags = (SourceModifierFlags | Label | Module).toCommonFlags
1919

2020
/** The closest enclosing DefDef, TypeDef, or ClassDef node */
2121
private var currentOwner: untpd.Tree = untpd.EmptyTree
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer}
4+
import dotty.tools.dotc.ast.tpd
5+
import dotty.tools.dotc.core.Contexts.Context
6+
import scala.collection.mutable.ListBuffer
7+
import dotty.tools.dotc.core.{Scopes, Flags}
8+
import dotty.tools.dotc.core.Symbols.NoSymbol
9+
import scala.annotation.tailrec
10+
import dotty.tools.dotc.core._
11+
import Symbols._
12+
import scala.Some
13+
import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer}
14+
import dotty.tools.dotc.ast.tpd
15+
import dotty.tools.dotc.core.Contexts.Context
16+
import scala.collection.mutable
17+
import dotty.tools.dotc.core.Names.Name
18+
import NameOps._
19+
20+
/** A transformer that provides a convenient way to create companion objects
21+
*/
22+
abstract class CreateCompanionObjects(group: TreeTransformer, idx: Int) extends TreeTransform(group, idx) {
23+
24+
import tpd._
25+
26+
/** Given class definition should return true if companion object creation should be enforced
27+
*/
28+
def predicate(cls: TypeDef): Boolean
29+
30+
override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[tpd.Tree] = {
31+
@tailrec
32+
def transformStats0(trees: List[Tree], acc: ListBuffer[Tree]): List[Tree] = {
33+
trees match {
34+
case Nil => acc.toList
35+
case (claz: TypeDef) :: stats if claz.symbol.isClass && !(claz.symbol is Flags.Module) => {
36+
val moduleExists = !(claz.symbol.companionModule eq NoSymbol)
37+
if (moduleExists || !predicate(claz)) transformStats0(stats, acc += claz)
38+
else {
39+
val moduleSymbol = ctx.newCompleteModuleSymbol(claz.symbol.owner, claz.name.toTermName, Flags.Synthetic, Flags.Synthetic, List(defn.ObjectClass.typeRef), Scopes.newScope)
40+
if (moduleSymbol.owner.isClass) moduleSymbol.entered
41+
val companion = tpd.ModuleDef(moduleSymbol, List(EmptyTree))
42+
acc += claz
43+
acc += companion
44+
transformStats0(stats, acc)
45+
}
46+
}
47+
case stat :: stats => transformStats0(stats, acc += stat)
48+
}
49+
}
50+
51+
transformStats0(trees, ListBuffer())
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.core._
4+
import Symbols._
5+
import scala.Some
6+
import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer}
7+
import dotty.tools.dotc.ast.tpd
8+
import dotty.tools.dotc.core.Contexts.Context
9+
import scala.collection.mutable
10+
import dotty.tools.dotc.core.Names.Name
11+
import NameOps._
12+
13+
object PostTyperTransformers {
14+
15+
import tpd.{TreeTransformer => _, _}
16+
17+
18+
/** A trait that's assumed by the transformers that run right after typer.
19+
* Ensures that trees are normalized when seen by other transforms. This means:
20+
* (1) All module class definitions appear after their companion class definitions
21+
* (2) There are no import clauses or named arguments
22+
* (3) All trees designating types are instances of TypeTree
23+
*/
24+
abstract class PostTyperTransformer extends TreeTransformer {
25+
26+
/** Reorder statements so that module classes always come after their companion classes, add missing companion classes */
27+
def reorder(stats: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = {
28+
val moduleClassDefs = mutable.Map[Name, Tree]()
29+
def reorder0(stats: List[Tree]): List[Tree] = {
30+
stats match {
31+
case (stat: TypeDef) :: stats1 if stat.symbol.isClass =>
32+
if (stat.symbol is Flags.Module) {
33+
moduleClassDefs += (stat.name -> stat)
34+
val stats1r = reorder0(stats1)
35+
if (moduleClassDefs contains stat.name) stat :: stats1r else stats1r
36+
}
37+
else {
38+
val mclsName = stat.name.moduleClassName
39+
moduleClassDefs remove mclsName match {
40+
case Some(mcdef) => stat :: mcdef :: reorder0(stats1)
41+
case None => stat :: reorder0(stats1)
42+
}
43+
}
44+
case stat :: stats1 => stat :: reorder0(stats1)
45+
case Nil => Nil
46+
}
47+
}
48+
reorder0(stats)
49+
}
50+
51+
override def transformStats(trees: List[tpd.Tree], info: TransformerInfo, current: Int)(implicit ctx: Context): List[tpd.Tree] =
52+
super.transformStats(reorder(trees)(ctx, info), info, current)
53+
54+
override def transform(tree: tpd.Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): tpd.Tree = tree match {
55+
case tree: Import => EmptyTree
56+
case tree: NamedArg => super.transform(tree.arg, info, cur)
57+
case tree: TypeTree => super.transform(tree, info, cur)
58+
case tree => super.transform(if (tree.isType) TypeTree(tree.tpe) else tree, info, cur)
59+
}
60+
}
61+
62+
}

0 commit comments

Comments
 (0)