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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */
// $OldId: ErasurePhase.java,v 1.13 2002/11/14 15:58:22 schinz Exp $
// $Id$
package scalac.transformer;
import scalac.Global;
import scalac.Phase;
import scalac.PhaseDescriptor;
import scalac.CompilationUnit;
import scalac.backend.Primitive;
import scalac.backend.Primitives;
import scalac.symtab.Definitions;
import scalac.symtab.Modifiers;
import scalac.symtab.Scope;
import scalac.symtab.Symbol;
import scalac.symtab.Type;
import scalac.util.Name;
import scalac.util.Debug;
public class ErasurePhase extends Phase {
//########################################################################
// Private Fields
private final Definitions definitions;
private final Primitives primitives;
private final Erasure erasure;
//########################################################################
// Public Constructors
public ErasurePhase(Global global, PhaseDescriptor descriptor) {
super(global, descriptor);
this.definitions = global.definitions;
this.primitives = global.primitives;
this.erasure = new Erasure(global);
}
//########################################################################
// Public Methods
public void apply(CompilationUnit[] units) {
erasure.apply(units);
}
public Type transformInfo(Symbol sym, Type tp) {
if (sym.isConstructor() && sym.constructorClass().isSubClass(definitions.ANYVAL_CLASS)) return tp;
if (sym.isClass()) {
if (sym == definitions.ANY_CLASS) return tp;
if (sym.isJava() && sym.isModuleClass()) return tp;
if (sym.isSubClass(definitions.ANYVAL_CLASS))
if (sym != definitions.ANYVAL_CLASS) return tp;
switch (tp) {
case CompoundType(Type[] parents, Scope members):
assert parents.length != 0: Debug.show(sym) + " -- " + tp;
if (sym.isInterface()) {
Symbol superclass = parents[0].symbol();
if (superclass.isJava() && !superclass.isInterface()) {
parents = Type.cloneArray(parents);
parents[0] = definitions.ANYREF_TYPE();
tp = Type.compoundType(parents, members, sym);
}
}
return Type.erasureMap.map(tp);
default:
throw Debug.abort("illegal case", tp);
}
}
if (sym.isTerm() && sym.isParameter()) {
if (primitives.getPrimitive(sym.owner()) == Primitive.BOX)
return eraseUnboxMethodType(tp);
if (primitives.getPrimitive(sym.owner()) == Primitive.UNBOX)
return eraseBoxMethodType(tp);
}
if (sym.isType()) return tp;
if (sym.isThisSym()) return sym.owner().nextType();
// if (sym == definitions.NULL) return tp.resultType().erasure();
if (global.target == global.TARGET_INT && sym ==primitives.NEW_OARRAY){
// !!! hack for interpreter
Name name = Name.fromString("element").toTypeName();
Symbol tparam = sym.newTParam(sym.pos, 0, name, definitions.ANY_TYPE());
return Type.PolyType(new Symbol[]{tparam}, tp);
}
switch (primitives.getPrimitive(sym)) {
case Primitive.IS : return Type.PolyType(tp.typeParams(), Type.MethodType(tp.valueParams(), tp.resultType().erasure()));
case Primitive.AS : return tp;
case Primitive.BOX: return eraseBoxMethodType(tp);
case Primitive.UNBOX: return eraseUnboxMethodType(tp);
default : return tp.erasure();
}
}
//########################################################################
// Private Methods
private Type eraseBoxMethodType(Type type) {
switch (type) {
case PolyType(_, Type result):
return eraseBoxMethodType(result);
case MethodType(Symbol[] params, Type result):
return Type.MethodType(params, eraseBoxMethodType(result));
case TypeRef(Type prefix, Symbol clasz, Type[] args):
return Type.typeRef(prefix, clasz, Type.EMPTY_ARRAY);
default:
throw Debug.abort("illegal case", type);
}
}
private Type eraseUnboxMethodType(Type type) {
switch (type) {
case PolyType(_, Type result):
return eraseUnboxMethodType(result);
case MethodType(Symbol[] params, Type result):
return Type.MethodType(params, eraseUnboxMethodType(result));
case TypeRef(_, Symbol clasz, Type[] args):
if (clasz == definitions.ARRAY_CLASS) {
Symbol element = args[0].symbol();
if (element.isAbstractType())
if (element.info().symbol() == definitions.ANY_CLASS)
return definitions.ANYREF_CLASS.nextType();
}
return type.fullErasure();
default:
throw Debug.abort("illegal case", type);
}
}
//########################################################################
}
|