summaryrefslogtreecommitdiff
path: root/sources/scalac/transformer/ErasurePhase.java
blob: b7ca13b6708374c900aacc5e7d9e684d5a04aa3e (plain) (blame)
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
136
137
138
139
140
141
142
143
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    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.Unit;
import scalac.backend.Primitive;
import scalac.backend.Primitives;
import scalac.checkers.Checker;
import scalac.checkers.CheckOwners;
import scalac.checkers.CheckSymbols;
import scalac.checkers.CheckTypes;
import scalac.checkers.CheckNames;
import scalac.symtab.Definitions;
import scalac.symtab.Scope;
import scalac.symtab.Symbol;
import scalac.symtab.Type;
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(Unit[] 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();
        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);
        case Primitive.AS__ARRAY:
            return Type.MethodType(Symbol.EMPTY_ARRAY, definitions.ANY_CLASS.nextType());
        default           : return tp.erasure();
        }
    }

    public Checker[] postCheckers(Global global) {
        return new Checker[] {
            new CheckSymbols(global),
            new CheckTypes(global),
            new CheckOwners(global),
            new CheckNames(global)
        };
    }

    //########################################################################
    // 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);
        }
    }

    //########################################################################
}