TypeTag.java revision 3850:8e69054abeeb
1/*
2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.javac.code;
27
28import com.sun.source.tree.Tree.Kind;
29
30import javax.lang.model.type.TypeKind;
31
32import static com.sun.tools.javac.code.TypeTag.NumericClasses.*;
33
34/** An interface for type tag values, which distinguish between different
35 *  sorts of types.
36 *
37 *  <p><b>This is NOT part of any supported API.
38 *  If you write code that depends on this, you do so at your own risk.
39 *  This code and its internal interfaces are subject to change or
40 *  deletion without notice.</b>
41 */
42public enum TypeTag {
43    /** The tag of the basic type `byte'.
44     */
45    BYTE(BYTE_CLASS, BYTE_SUPERCLASSES, true),
46
47    /** The tag of the basic type `char'.
48     */
49    CHAR(CHAR_CLASS, CHAR_SUPERCLASSES, true),
50
51    /** The tag of the basic type `short'.
52     */
53    SHORT(SHORT_CLASS, SHORT_SUPERCLASSES, true),
54
55    /** The tag of the basic type `long'.
56     */
57    LONG(LONG_CLASS, LONG_SUPERCLASSES, true),
58
59    /** The tag of the basic type `float'.
60     */
61    FLOAT(FLOAT_CLASS, FLOAT_SUPERCLASSES, true),
62    /** The tag of the basic type `int'.
63     */
64    INT(INT_CLASS, INT_SUPERCLASSES, true),
65    /** The tag of the basic type `double'.
66     */
67    DOUBLE(DOUBLE_CLASS, DOUBLE_CLASS, true),
68    /** The tag of the basic type `boolean'.
69     */
70    BOOLEAN(0, 0, true),
71
72    /** The tag of the type `void'.
73     */
74    VOID,
75
76    /** The tag of all class and interface types.
77     */
78    CLASS,
79
80    /** The tag of all array types.
81     */
82    ARRAY,
83
84    /** The tag of all (monomorphic) method types.
85     */
86    METHOD,
87
88    /** The tag of all package "types".
89     */
90    PACKAGE,
91
92    /** The tag of all module "types".
93     */
94    MODULE,
95
96    /** The tag of all (source-level) type variables.
97     */
98    TYPEVAR,
99
100    /** The tag of all type arguments.
101     */
102    WILDCARD,
103
104    /** The tag of all polymorphic (method-) types.
105     */
106    FORALL,
107
108    /** The tag of deferred expression types in method context
109     */
110    DEFERRED,
111
112    /** The tag of the bottom type {@code <null>}.
113     */
114    BOT,
115
116    /** The tag of a missing type.
117     */
118    NONE,
119
120    /** The tag of the error type.
121     */
122    ERROR,
123
124    /** The tag of an unknown type
125     */
126    UNKNOWN,
127
128    /** The tag of all instantiatable type variables.
129     */
130    UNDETVAR,
131
132    /** Pseudo-types, these are special tags
133     */
134    UNINITIALIZED_THIS,
135
136    UNINITIALIZED_OBJECT;
137
138    final int superClasses;
139    final int numericClass;
140    final boolean isPrimitive;
141
142    private TypeTag() {
143        this(0, 0, false);
144    }
145
146    private TypeTag(int numericClass, int superClasses, boolean isPrimitive) {
147        this.superClasses = superClasses;
148        this.numericClass = numericClass;
149        this.isPrimitive = isPrimitive;
150    }
151
152    public static class NumericClasses {
153        public static final int BYTE_CLASS = 1;
154        public static final int CHAR_CLASS = 2;
155        public static final int SHORT_CLASS = 4;
156        public static final int INT_CLASS = 8;
157        public static final int LONG_CLASS = 16;
158        public static final int FLOAT_CLASS = 32;
159        public static final int DOUBLE_CLASS = 64;
160
161        static final int BYTE_SUPERCLASSES = BYTE_CLASS | SHORT_CLASS | INT_CLASS |
162                LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
163
164        static final int CHAR_SUPERCLASSES = CHAR_CLASS | INT_CLASS |
165                LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
166
167        static final int SHORT_SUPERCLASSES = SHORT_CLASS | INT_CLASS |
168                LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
169
170        static final int INT_SUPERCLASSES = INT_CLASS | LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
171
172        static final int LONG_SUPERCLASSES = LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
173
174        static final int FLOAT_SUPERCLASSES = FLOAT_CLASS | DOUBLE_CLASS;
175    }
176
177    public boolean isStrictSubRangeOf(TypeTag tag) {
178        /*  Please don't change the implementation of this method to call method
179         *  isSubRangeOf. Both methods are called from hotspot code, the current
180         *  implementation is better performance-wise than the commented modification.
181         */
182        return (this.superClasses & tag.numericClass) != 0 && this != tag;
183    }
184
185    public boolean isSubRangeOf(TypeTag tag) {
186        return (this.superClasses & tag.numericClass) != 0;
187    }
188
189    /** Returns the number of type tags.
190     */
191    public static int getTypeTagCount() {
192        // last two tags are not included in the total as long as they are pseudo-types
193        return (UNDETVAR.ordinal() + 1);
194    }
195
196    public Kind getKindLiteral() {
197        switch (this) {
198        case INT:
199            return Kind.INT_LITERAL;
200        case LONG:
201            return Kind.LONG_LITERAL;
202        case FLOAT:
203            return Kind.FLOAT_LITERAL;
204        case DOUBLE:
205            return Kind.DOUBLE_LITERAL;
206        case BOOLEAN:
207            return Kind.BOOLEAN_LITERAL;
208        case CHAR:
209            return Kind.CHAR_LITERAL;
210        case CLASS:
211            return Kind.STRING_LITERAL;
212        case BOT:
213            return Kind.NULL_LITERAL;
214        default:
215            throw new AssertionError("unknown literal kind " + this);
216        }
217    }
218
219    public TypeKind getPrimitiveTypeKind() {
220        switch (this) {
221        case BOOLEAN:
222            return TypeKind.BOOLEAN;
223        case BYTE:
224            return TypeKind.BYTE;
225        case SHORT:
226            return TypeKind.SHORT;
227        case INT:
228            return TypeKind.INT;
229        case LONG:
230            return TypeKind.LONG;
231        case CHAR:
232            return TypeKind.CHAR;
233        case FLOAT:
234            return TypeKind.FLOAT;
235        case DOUBLE:
236            return TypeKind.DOUBLE;
237        case VOID:
238            return TypeKind.VOID;
239        default:
240            throw new AssertionError("unknown primitive type " + this);
241        }
242    }
243
244    /** Returns true if the given value is within the allowed range for this type. */
245    public boolean checkRange(int value) {
246        switch (this) {
247            case BOOLEAN:
248                return 0 <= value && value <= 1;
249            case BYTE:
250                return Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE;
251            case CHAR:
252                return Character.MIN_VALUE <= value && value <= Character.MAX_VALUE;
253            case SHORT:
254                return Short.MIN_VALUE <= value && value <= Short.MAX_VALUE;
255            case INT:
256                return true;
257            default:
258                throw new AssertionError();
259        }
260    }
261}
262