1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/* NSC -- new scala compiler
* Copyright 2005 LAMP/EPFL
* @author
*/
// $Id$
package scala.tools.nsc.transform;
import symtab._;
import Flags._;
import util.ListBuffer;
import collection.mutable.HashMap;
abstract class Flatten extends InfoTransform {
import global._;
import definitions._;
import posAssigner.atPos;
/** the following two members override abstract members in Transform */
val phaseName: String = "flatten";
private def liftClass(sym: Symbol): unit =
if (!(sym hasFlag LIFTED)) {
sym setFlag LIFTED;
atPhase(phase.next) {
if (settings.debug.value) log("re-enter " + sym + " in " + sym.owner);
assert(sym.owner.isPackageClass, sym);//debug
val scope = sym.owner.info.decls;
val old = scope lookup sym.name;
if (old != NoSymbol) scope unlink old;
scope enter sym;
}
}
private val flattened = new TypeMap {
def apply(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) if (pre.symbol.isClass && !pre.symbol.isPackageClass) =>
assert(args.isEmpty);
typeRef(sym.toplevelClass.owner.thisType, sym, args)
case ClassInfoType(parents, decls, clazz) =>
var parents1 = parents;
val decls1 = new Scope();
if (clazz.isPackageClass) {
atPhase(phase.next)(decls.toList foreach (decls1 enter));
} else {
val oldowner = clazz.owner;
atPhase(phase.next)(oldowner.info);
parents1 = List.mapConserve(parents)(this);
for (val sym <- decls.toList) {
if (sym.isTerm && !sym.isStaticModule) {
decls1 enter sym;
if (sym.isModule) sym.moduleClass setFlag LIFTED;
} else if (sym.isClass) {
liftClass(sym);
if (sym.needsImplClass) liftClass(erasure.implClass(sym))
}
}
}
ClassInfoType(parents1, decls1, clazz)
case PolyType(tparams, restp) =>
val restp1 = apply(restp);
if (restp1 eq restp) tp else PolyType(tparams, restp1)
case _ =>
mapOver(tp)
}
}
def transformInfo(sym: Symbol, tp: Type): Type = flattened(tp);
protected def newTransformer(unit: CompilationUnit): Transformer = new Flattener;
class Flattener extends Transformer {
/** Buffers for lifted out classes */
private val liftedDefs = new HashMap[Symbol, ListBuffer[Tree]];
override def transform(tree: Tree): Tree = {
tree match {
case PackageDef(_, _) =>
liftedDefs(tree.symbol.moduleClass) = new ListBuffer;
case _ =>
}
postTransform(super.transform(tree))
}
private def postTransform(tree: Tree): Tree = {
val sym = tree.symbol;
val tree1 = tree match {
case ClassDef(_, _, _, _, _) if sym.isNestedClass =>
liftedDefs(sym.toplevelClass.owner) += tree;
EmptyTree
case Select(qual, name) if (sym.isStaticModule && !sym.owner.isPackageClass) =>
atPhase(phase.next) {
atPos(tree.pos) {
gen.mkRef(sym)
}
}
case _ =>
tree
}
tree1 setType flattened(tree1.tpe)
}
/** Transform statements and add lifted definitions to them. */
override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
val stats1 = super.transformStats(stats, exprOwner);
if (currentOwner.isPackageClass && liftedDefs(currentOwner).hasNext)
stats1 ::: liftedDefs(currentOwner).toList
else
stats1
}
}
}
|