KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > type > Type


1 /* Type Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; see the file COPYING. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: Type.java.in,v 4.1.2.1 2002/05/28 17:34:22 hoenicke Exp $
18  */

19
20 package jode.type;
21 import jode.AssertError;
22 import jode.GlobalOptions;
23 import jode.bytecode.ClassInfo;
24 import jode.util.UnifyHash;
25
26 import java.util.Iterator JavaDoc;
27
28 /**
29  * This is my type class. It differs from java.lang.class, in that it
30  * represents a set of types. Since most times this set is infinite, it
31  * needs a special representation. <br>
32  *
33  * The main operation on a type sets are tSuperType, tSubType and
34  * intersection.
35  *
36  * @author Jochen Hoenicke */

37 public class Type {
38     public static final int TC_BOOLEAN = 0;
39     public static final int TC_BYTE = 1;
40     public static final int TC_CHAR = 2;
41     public static final int TC_SHORT = 3;
42     public static final int TC_INT = 4;
43     public static final int TC_LONG = 5;
44     public static final int TC_FLOAT = 6;
45     public static final int TC_DOUBLE = 7;
46     public static final int TC_NULL = 8;
47     public static final int TC_ARRAY = 9;
48     public static final int TC_CLASS = 10;
49     public static final int TC_VOID = 11;
50     public static final int TC_METHOD = 12;
51     public static final int TC_ERROR = 13;
52     public static final int TC_UNKNOWN = 101;
53     public static final int TC_RANGE = 103;
54     public static final int TC_INTEGER = 107;
55
56     private static final UnifyHash classHash = new UnifyHash();
57     private static final UnifyHash arrayHash = new UnifyHash();
58     private static final UnifyHash methodHash = new UnifyHash();
59
60     /**
61      * This type represents the singleton set containing the boolean type.
62      */

63     public static final Type tBoolean = new IntegerType(IntegerType.IT_Z);
64     /**
65      * This type represents the singleton set containing the byte type.
66      */

67     public static final Type tByte = new IntegerType(IntegerType.IT_B);
68     /**
69      * This type represents the singleton set containing the char type.
70      */

71     public static final Type tChar = new IntegerType(IntegerType.IT_C);
72     /**
73      * This type represents the singleton set containing the short type.
74      */

75     public static final Type tShort = new IntegerType(IntegerType.IT_S);
76     /**
77      * This type represents the singleton set containing the int type.
78      */

79     public static final Type tInt = new IntegerType(IntegerType.IT_I);
80     /**
81      * This type represents the singleton set containing the long type.
82      */

83     public static final Type tLong = new Type(TC_LONG);
84     /**
85      * This type represents the singleton set containing the float type.
86      */

87     public static final Type tFloat = new Type(TC_FLOAT);
88     /**
89      * This type represents the singleton set containing the double type.
90      */

91     public static final Type tDouble = new Type(TC_DOUBLE);
92     /**
93      * This type represents the void type. It is really not a type at
94      * all.
95      */

96     public static final Type tVoid = new Type(TC_VOID);
97     /**
98      * This type represents the empty set, and probably means, that something
99      * has gone wrong.
100      */

101     public static final Type tError = new Type(TC_ERROR);
102     /**
103      * This type represents the set of all possible types.
104      */

105     public static final Type tUnknown = new Type(TC_UNKNOWN);
106     /**
107      * This type represents the set of all integer types, up to 32 bit.
108      */

109     public static final Type tUInt = new IntegerType(IntegerType.IT_I
110                             | IntegerType.IT_B
111                             | IntegerType.IT_C
112                             | IntegerType.IT_S);
113     /**
114      * This type represents the set of the boolean and int type.
115      */

116     public static final Type tBoolInt = new IntegerType(IntegerType.IT_I
117                             | IntegerType.IT_Z);
118     /**
119      * This type represents the set of boolean and all integer types,
120      * up to 32 bit.
121      */

122     public static final Type tBoolUInt= new IntegerType(IntegerType.IT_I
123                             | IntegerType.IT_B
124                             | IntegerType.IT_C
125                             | IntegerType.IT_S
126                             | IntegerType.IT_Z);
127     /**
128      * This type represents the set of the boolean and byte type.
129      */

130     public static final Type tBoolByte= new IntegerType(IntegerType.IT_B
131                             | IntegerType.IT_Z);
132     /**
133      * This type represents the singleton set containing
134      * <code>java.lang.Object</code>.
135      */

136     public static final ClassInterfacesType tObject =
137     tClass("java.lang.Object");
138     /**
139      * This type represents the singleton set containing the special
140      * null type (the type of null).
141      */

142     public static final ReferenceType tNull = new NullType();
143     /**
144      * This type represents the set of all reference types, including
145      * class types, array types, interface types and the null type.
146      */

147     public static final Type tUObject = tRange(tObject, tNull);
148     /**
149      * This type represents the singleton set containing
150      * <code>java.lang.String</code>.
151      */

152     public static final Type tString = tClass("java.lang.String");
153     /**
154      * This type represents the singleton set containing
155      * <code>java.lang.StringBuffer</code>.
156      */

157     public static final Type tStringBuffer = tClass("java.lang.StringBuffer");
158     /**
159      * This type represents the singleton set containing
160      * <code>java.lang.Class</code>.
161      */

162     public static final Type tJavaLangClass = tClass("java.lang.Class");
163
164     /**
165      * Generate the singleton set of the type represented by the given
166      * string.
167      * @param type the type signature (or method signature).
168      * @return a singleton set containing the given type.
169      */

170     public static final Type tType(String JavaDoc type) {
171         if (type == null || type.length() == 0)
172             return tError;
173         switch(type.charAt(0)) {
174         case 'Z':
175             return tBoolean;
176         case 'B':
177             return tByte;
178         case 'C':
179             return tChar;
180         case 'S':
181             return tShort;
182         case 'I':
183             return tInt;
184         case 'F':
185             return tFloat;
186         case 'J':
187             return tLong;
188         case 'D':
189             return tDouble;
190         case 'V':
191             return tVoid;
192         case '[':
193             return tArray(tType(type.substring(1)));
194         case 'L':
195             int index = type.indexOf(';');
196             if (index != type.length()-1)
197                 return tError;
198             return tClass(type.substring(1, index));
199     case '(':
200         return tMethod(type);
201         }
202         throw new AssertError("Unknown type signature: "+type);
203     }
204
205     /**
206      * Generate the singleton set of the type represented by the given
207      * class name.
208      * @param clazzname the full qualified name of the class.
209      * The packages may be separated by `.' or `/'.
210      * @return a singleton set containing the given type.
211      */

212     public static final ClassInterfacesType tClass(String JavaDoc clazzname) {
213     return tClass(ClassInfo.forName(clazzname.replace('/','.')));
214     }
215
216     /**
217      * Generate the singleton set of the type represented by the given
218      * class info.
219      * @param clazzinfo the jode.bytecode.ClassInfo.
220      * @return a singleton set containing the given type.
221      */

222     public static final ClassInterfacesType tClass(ClassInfo clazzinfo) {
223     int hash = clazzinfo.hashCode();
224     Iterator JavaDoc iter = classHash.iterateHashCode(hash);
225     while (iter.hasNext()) {
226         ClassInterfacesType type = (ClassInterfacesType) iter.next();
227         if (type.getClassInfo() == clazzinfo)
228         return type;
229     }
230     ClassInterfacesType type = new ClassInterfacesType(clazzinfo);
231     classHash.put(hash, type);
232         return type;
233     }
234
235     /**
236      * Generate/look up the set of the array type whose element types
237      * are in the given type set.
238      * @param type the element types (which may be the empty set tError).
239      * @return the set of array types (which may be the empty set tError).
240      */

241     public static final Type tArray(Type type) {
242         if (type == tError)
243             return type;
244
245     int hash = type.hashCode();
246     Iterator JavaDoc iter = arrayHash.iterateHashCode(hash);
247     while (iter.hasNext()) {
248         ArrayType arrType = (ArrayType) iter.next();
249         if (arrType.getElementType().equals(type))
250         return arrType;
251     }
252     ArrayType arrType = new ArrayType(type);
253     arrayHash.put(hash, arrType);
254         return arrType;
255     }
256
257     /**
258      * Generate/look up the method type for the given signature
259      * @param signature the method decriptor.
260      * @return a method type (a singleton set).
261      */

262     public static MethodType tMethod(String JavaDoc signature) {
263     int hash = signature.hashCode();
264     Iterator JavaDoc iter = methodHash.iterateHashCode(hash);
265     while (iter.hasNext()) {
266         MethodType methodType = (MethodType) iter.next();
267         if (methodType.getTypeSignature().equals(signature))
268         return methodType;
269     }
270     MethodType methodType = new MethodType(signature);
271     methodHash.put(hash, methodType);
272         return methodType;
273     }
274
275     /**
276      * Generate the range type from bottom to top. This should
277      * represent all reference types, that can be casted to bottom by
278      * a widening cast and where top can be casted to. You should not
279      * use this method directly; use tSubType, tSuperType and
280      * intersection instead, which is more general.
281      * @param bottom the bottom type.
282      * @param top the top type.
283      * @return the range type.
284      */

285     public static final Type tRange(ReferenceType bottom,
286                     ReferenceType top) {
287         return new RangeType(bottom, top);
288     }
289      
290     /**
291      * Generate the set of types, to which one of the types in type can
292      * be casted to by a widening cast. The following holds:
293      * <ul><li>tSuperType(tObject) = tObject </li>
294      * <li>tSuperType(tError) = tError </li>
295      * <li>type.intersection(tSuperType(type)).equals(type)
296      * (this means type is a subset of tSuperType(type).</li>
297      * <li>tSuperType(tNull) = tUObject</li>
298      * <li>tSuperType(tChar) = {tChar, tInt } </li></ul>
299      * @param type a set of types.
300      * @return the super types of type.
301      */

302     public static Type tSuperType(Type type) {
303     return type.getSuperType();
304     }
305
306     /**
307      * Generate the set of types, which can be casted to one of the
308      * types in type by a widening cast. The following holds:
309      * <ul><li>tSubType(tObject) = tUObject </li>
310      * <li>tSubType(tError) = tError </li>
311      * <li>type.intersection(tSubType(type)).equals(type)
312      * (this means type is a subset of tSubType(type).</li>
313      * <li>tSuperType(tSubType(type)) is a subset of type </li>
314      * <li>tSubType(tSuperType(type)) is a subset of type </li>
315      * <li>tSubType(tNull) = tNull</li>
316      * <li>tSubType(tBoolean, tShort) = { tBoolean, tByte, tShort }</li></ul>
317      * @param type a set of types.
318      * @return the sub types of type.
319      */

320     public static Type tSubType(Type type) {
321         return type.getSubType();
322     }
323
324     /**
325      * The typecode of this type. This should be one of the TC_ constants.
326      */

327     final int typecode;
328
329     /**
330      * Create a new type with the given type code.
331      */

332     protected Type(int tc) {
333         typecode = tc;
334     }
335
336     /**
337      * The sub types of this type.
338      * @return tSubType(this).
339      */

340     public Type getSubType() {
341         return this;
342     }
343
344     /**
345      * The super types of this type.
346      * @return tSuperType(this).
347      */

348     public Type getSuperType() {
349         return this;
350     }
351
352     /**
353      * Returns the hint type of this type set. This returns the singleton
354      * set containing only the `most likely' type in this set. This doesn't
355      * work for <code>tError</code> or <code>tUnknown</code>, and may lead
356      * to errors for certain range types.
357      * @return the hint type.
358      */

359     public Type getHint() {
360     return getCanonic();
361     }
362
363     /**
364      * Returns the canonic type of this type set. The intention is, to
365      * return for each expression the type, that the java compiler would
366      * assign to this expression.
367      * @return the canonic type.
368      */

369     public Type getCanonic() {
370     return this;
371     }
372
373     /**
374      * Returns the type code of this type. Don't use this; it is
375      * merily needed by the sub types (and the bytecode verifier, which
376      * has its own type merging methods).
377      * @return the type code of the type.
378      */

379     public final int getTypeCode() {
380         return typecode;
381     }
382
383     /**
384      * Returns the number of stack/local entries an object of this type
385      * occupies.
386      * @return 0 for tVoid, 2 for tDouble and tLong and
387      * 1 for every other type.
388      */

389     public int stackSize()
390     {
391         switch(typecode) {
392         case TC_VOID:
393             return 0;
394         case TC_ERROR:
395         default:
396             return 1;
397         case TC_DOUBLE:
398         case TC_LONG:
399             return 2;
400         }
401     }
402
403     /**
404      * Intersect this set of types with another type set and return the
405      * intersection.
406      * @param type the other type set.
407      * @return the intersection, tError, if the intersection is empty.
408      */

409     public Type intersection(Type type) {
410     if (this == tError || type == tError)
411         return tError;
412     if (this == tUnknown)
413         return type;
414     if (type == tUnknown || this == type)
415         return this;
416     /* We have two different singleton sets now.
417      */

418     if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0)
419         GlobalOptions.err.println("intersecting "+ this +" and "+ type
420                    + " to <error>");
421     return tError;
422     }
423
424     /**
425      * Checks if we need to cast to a middle type, before we can cast from
426      * fromType to this type. For example it is impossible to cast a
427      * String to a StringBuffer, but if we cast to Object in between this
428      * is allowed (it doesn't make much sense though).
429      * @return the middle type, or null if it is not necessary.
430      */

431     public Type getCastHelper(Type fromType) {
432     return null;
433     }
434
435     /**
436      * Checks if this type represents a valid singleton type.
437      */

438     public boolean isValidType() {
439     return typecode <= TC_DOUBLE;
440     }
441
442     /**
443      * Checks if this is a class or array type (but not a null type).
444      * @XXX remove this?
445      * @return true if this is a class or array type.
446      */

447     public boolean isClassType() {
448         return false;
449     }
450
451     /**
452      * Check if this type set and the other type set are not disjunct.
453      * @param type the other type set.
454      * @return true if this they aren't disjunct.
455      */

456     public boolean isOfType(Type type) {
457     return this.intersection(type) != Type.tError;
458     }
459
460     /**
461      * Generates the default name, that is the `natural' choice for
462      * local of this type.
463      * @return the default name of a local of this type.
464      */

465     public String JavaDoc getDefaultName() {
466         switch (typecode) {
467         case TC_LONG:
468             return "l";
469         case TC_FLOAT:
470             return "f";
471         case TC_DOUBLE:
472             return "d";
473         default:
474             return "local";
475         }
476     }
477
478     /**
479      * Generates the default value, that is the initial value of a field
480      * of this type.
481      * @return the default value of a field of this type.
482      */

483     public Object JavaDoc getDefaultValue() {
484         switch (typecode) {
485         case TC_LONG:
486             return new Long JavaDoc(0);
487         case TC_FLOAT:
488             return new Float JavaDoc(0);
489         case TC_DOUBLE:
490             return new Double JavaDoc(0);
491         default:
492             return null;
493         }
494     }
495
496     /**
497      * Returns the type signature of this type. You should only call
498      * this on singleton types.
499      * @return the type (or method) signature of this type.
500      */

501     public String JavaDoc getTypeSignature() {
502         switch (typecode) {
503         case TC_LONG:
504             return "J";
505         case TC_FLOAT:
506             return "F";
507         case TC_DOUBLE:
508             return "D";
509         default:
510             return "?";
511         }
512     }
513
514     /**
515      * Returns the java.lang.Class representing this type. You should
516      * only call this on singleton types.
517      * @return the Class object representing this type.
518      */

519     public Class JavaDoc getTypeClass() throws ClassNotFoundException JavaDoc {
520         switch (typecode) {
521         case TC_LONG:
522             return Long.TYPE;
523         case TC_FLOAT:
524             return Float.TYPE;
525         case TC_DOUBLE:
526             return Double.TYPE;
527         default:
528         throw new AssertError("getTypeClass() called on illegal type");
529         }
530     }
531     
532     /**
533      * Returns a string representation describing this type set.
534      * @return a string representation describing this type set.
535      */

536     public String JavaDoc toString() {
537         switch (typecode) {
538         case TC_LONG:
539             return "long";
540         case TC_FLOAT:
541             return "float";
542         case TC_DOUBLE:
543             return "double";
544         case TC_NULL:
545             return "null";
546         case TC_VOID:
547             return "void";
548         case TC_UNKNOWN:
549             return "<unknown>";
550         case TC_ERROR:
551         default:
552             return "<error>";
553         }
554     }
555 }
556
Popular Tags