001: /* Type Copyright (C) 1998-2002 Jochen Hoenicke.
002: *
003: * This program is free software; you can redistribute it and/or modify
004: * it under the terms of the GNU General Public License as published by
005: * the Free Software Foundation; either version 2, or (at your option)
006: * any later version.
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU General Public License for more details.
012: *
013: * You should have received a copy of the GNU General Public License
014: * along with this program; see the file COPYING. If not, write to
015: * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
016: *
017: * $Id: Type.java.in,v 4.1.2.1 2002/05/28 17:34:22 hoenicke Exp $
018: */
019:
020: package jode.type;
021:
022: import jode.AssertError;
023: import jode.GlobalOptions;
024: import jode.bytecode.ClassInfo;
025: import jode.util.UnifyHash;
026:
027: import java.util.Iterator;
028:
029: /**
030: * This is my type class. It differs from java.lang.class, in that it
031: * represents a set of types. Since most times this set is infinite, it
032: * needs a special representation. <br>
033: *
034: * The main operation on a type sets are tSuperType, tSubType and
035: * intersection.
036: *
037: * @author Jochen Hoenicke */
038: public class Type {
039: public static final int TC_BOOLEAN = 0;
040: public static final int TC_BYTE = 1;
041: public static final int TC_CHAR = 2;
042: public static final int TC_SHORT = 3;
043: public static final int TC_INT = 4;
044: public static final int TC_LONG = 5;
045: public static final int TC_FLOAT = 6;
046: public static final int TC_DOUBLE = 7;
047: public static final int TC_NULL = 8;
048: public static final int TC_ARRAY = 9;
049: public static final int TC_CLASS = 10;
050: public static final int TC_VOID = 11;
051: public static final int TC_METHOD = 12;
052: public static final int TC_ERROR = 13;
053: public static final int TC_UNKNOWN = 101;
054: public static final int TC_RANGE = 103;
055: public static final int TC_INTEGER = 107;
056:
057: private static final UnifyHash classHash = new UnifyHash();
058: private static final UnifyHash arrayHash = new UnifyHash();
059: private static final UnifyHash methodHash = new UnifyHash();
060:
061: /**
062: * This type represents the singleton set containing the boolean type.
063: */
064: public static final Type tBoolean = new IntegerType(
065: IntegerType.IT_Z);
066: /**
067: * This type represents the singleton set containing the byte type.
068: */
069: public static final Type tByte = new IntegerType(IntegerType.IT_B);
070: /**
071: * This type represents the singleton set containing the char type.
072: */
073: public static final Type tChar = new IntegerType(IntegerType.IT_C);
074: /**
075: * This type represents the singleton set containing the short type.
076: */
077: public static final Type tShort = new IntegerType(IntegerType.IT_S);
078: /**
079: * This type represents the singleton set containing the int type.
080: */
081: public static final Type tInt = new IntegerType(IntegerType.IT_I);
082: /**
083: * This type represents the singleton set containing the long type.
084: */
085: public static final Type tLong = new Type(TC_LONG);
086: /**
087: * This type represents the singleton set containing the float type.
088: */
089: public static final Type tFloat = new Type(TC_FLOAT);
090: /**
091: * This type represents the singleton set containing the double type.
092: */
093: public static final Type tDouble = new Type(TC_DOUBLE);
094: /**
095: * This type represents the void type. It is really not a type at
096: * all.
097: */
098: public static final Type tVoid = new Type(TC_VOID);
099: /**
100: * This type represents the empty set, and probably means, that something
101: * has gone wrong.
102: */
103: public static final Type tError = new Type(TC_ERROR);
104: /**
105: * This type represents the set of all possible types.
106: */
107: public static final Type tUnknown = new Type(TC_UNKNOWN);
108: /**
109: * This type represents the set of all integer types, up to 32 bit.
110: */
111: public static final Type tUInt = new IntegerType(IntegerType.IT_I
112: | IntegerType.IT_B | IntegerType.IT_C | 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(
117: IntegerType.IT_I | 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(
123: IntegerType.IT_I | IntegerType.IT_B | IntegerType.IT_C
124: | IntegerType.IT_S | IntegerType.IT_Z);
125: /**
126: * This type represents the set of the boolean and byte type.
127: */
128: public static final Type tBoolByte = new IntegerType(
129: IntegerType.IT_B | IntegerType.IT_Z);
130: /**
131: * This type represents the singleton set containing
132: * <code>java.lang.Object</code>.
133: */
134: public static final ClassInterfacesType tObject = tClass("java.lang.Object");
135: /**
136: * This type represents the singleton set containing the special
137: * null type (the type of null).
138: */
139: public static final ReferenceType tNull = new NullType();
140: /**
141: * This type represents the set of all reference types, including
142: * class types, array types, interface types and the null type.
143: */
144: public static final Type tUObject = tRange(tObject, tNull);
145: /**
146: * This type represents the singleton set containing
147: * <code>java.lang.String</code>.
148: */
149: public static final Type tString = tClass("java.lang.String");
150: /**
151: * This type represents the singleton set containing
152: * <code>java.lang.StringBuffer</code>.
153: */
154: public static final Type tStringBuffer = tClass("java.lang.StringBuffer");
155: /**
156: * This type represents the singleton set containing
157: * <code>java.lang.Class</code>.
158: */
159: public static final Type tJavaLangClass = tClass("java.lang.Class");
160:
161: /**
162: * Generate the singleton set of the type represented by the given
163: * string.
164: * @param type the type signature (or method signature).
165: * @return a singleton set containing the given type.
166: */
167: public static final Type tType(String type) {
168: if (type == null || type.length() == 0)
169: return tError;
170: switch (type.charAt(0)) {
171: case 'Z':
172: return tBoolean;
173: case 'B':
174: return tByte;
175: case 'C':
176: return tChar;
177: case 'S':
178: return tShort;
179: case 'I':
180: return tInt;
181: case 'F':
182: return tFloat;
183: case 'J':
184: return tLong;
185: case 'D':
186: return tDouble;
187: case 'V':
188: return tVoid;
189: case '[':
190: return tArray(tType(type.substring(1)));
191: case 'L':
192: int index = type.indexOf(';');
193: if (index != type.length() - 1)
194: return tError;
195: return tClass(type.substring(1, index));
196: case '(':
197: return tMethod(type);
198: }
199: throw new AssertError("Unknown type signature: " + type);
200: }
201:
202: /**
203: * Generate the singleton set of the type represented by the given
204: * class name.
205: * @param clazzname the full qualified name of the class.
206: * The packages may be separated by `.' or `/'.
207: * @return a singleton set containing the given type.
208: */
209: public static final ClassInterfacesType tClass(String clazzname) {
210: return tClass(ClassInfo.forName(clazzname.replace('/', '.')));
211: }
212:
213: /**
214: * Generate the singleton set of the type represented by the given
215: * class info.
216: * @param clazzinfo the jode.bytecode.ClassInfo.
217: * @return a singleton set containing the given type.
218: */
219: public static final ClassInterfacesType tClass(ClassInfo clazzinfo) {
220: int hash = clazzinfo.hashCode();
221: Iterator iter = classHash.iterateHashCode(hash);
222: while (iter.hasNext()) {
223: ClassInterfacesType type = (ClassInterfacesType) iter
224: .next();
225: if (type.getClassInfo() == clazzinfo)
226: return type;
227: }
228: ClassInterfacesType type = new ClassInterfacesType(clazzinfo);
229: classHash.put(hash, type);
230: return type;
231: }
232:
233: /**
234: * Generate/look up the set of the array type whose element types
235: * are in the given type set.
236: * @param type the element types (which may be the empty set tError).
237: * @return the set of array types (which may be the empty set tError).
238: */
239: public static final Type tArray(Type type) {
240: if (type == tError)
241: return type;
242:
243: int hash = type.hashCode();
244: Iterator iter = arrayHash.iterateHashCode(hash);
245: while (iter.hasNext()) {
246: ArrayType arrType = (ArrayType) iter.next();
247: if (arrType.getElementType().equals(type))
248: return arrType;
249: }
250: ArrayType arrType = new ArrayType(type);
251: arrayHash.put(hash, arrType);
252: return arrType;
253: }
254:
255: /**
256: * Generate/look up the method type for the given signature
257: * @param signature the method decriptor.
258: * @return a method type (a singleton set).
259: */
260: public static MethodType tMethod(String signature) {
261: int hash = signature.hashCode();
262: Iterator iter = methodHash.iterateHashCode(hash);
263: while (iter.hasNext()) {
264: MethodType methodType = (MethodType) iter.next();
265: if (methodType.getTypeSignature().equals(signature))
266: return methodType;
267: }
268: MethodType methodType = new MethodType(signature);
269: methodHash.put(hash, methodType);
270: return methodType;
271: }
272:
273: /**
274: * Generate the range type from bottom to top. This should
275: * represent all reference types, that can be casted to bottom by
276: * a widening cast and where top can be casted to. You should not
277: * use this method directly; use tSubType, tSuperType and
278: * intersection instead, which is more general.
279: * @param bottom the bottom type.
280: * @param top the top type.
281: * @return the range type.
282: */
283: public static final Type tRange(ReferenceType bottom,
284: ReferenceType top) {
285: return new RangeType(bottom, top);
286: }
287:
288: /**
289: * Generate the set of types, to which one of the types in type can
290: * be casted to by a widening cast. The following holds:
291: * <ul><li>tSuperType(tObject) = tObject </li>
292: * <li>tSuperType(tError) = tError </li>
293: * <li>type.intersection(tSuperType(type)).equals(type)
294: * (this means type is a subset of tSuperType(type).</li>
295: * <li>tSuperType(tNull) = tUObject</li>
296: * <li>tSuperType(tChar) = {tChar, tInt } </li></ul>
297: * @param type a set of types.
298: * @return the super types of type.
299: */
300: public static Type tSuperType(Type type) {
301: return type.getSuperType();
302: }
303:
304: /**
305: * Generate the set of types, which can be casted to one of the
306: * types in type by a widening cast. The following holds:
307: * <ul><li>tSubType(tObject) = tUObject </li>
308: * <li>tSubType(tError) = tError </li>
309: * <li>type.intersection(tSubType(type)).equals(type)
310: * (this means type is a subset of tSubType(type).</li>
311: * <li>tSuperType(tSubType(type)) is a subset of type </li>
312: * <li>tSubType(tSuperType(type)) is a subset of type </li>
313: * <li>tSubType(tNull) = tNull</li>
314: * <li>tSubType(tBoolean, tShort) = { tBoolean, tByte, tShort }</li></ul>
315: * @param type a set of types.
316: * @return the sub types of type.
317: */
318: public static Type tSubType(Type type) {
319: return type.getSubType();
320: }
321:
322: /**
323: * The typecode of this type. This should be one of the TC_ constants.
324: */
325: final int typecode;
326:
327: /**
328: * Create a new type with the given type code.
329: */
330: protected Type(int tc) {
331: typecode = tc;
332: }
333:
334: /**
335: * The sub types of this type.
336: * @return tSubType(this).
337: */
338: public Type getSubType() {
339: return this ;
340: }
341:
342: /**
343: * The super types of this type.
344: * @return tSuperType(this).
345: */
346: public Type getSuperType() {
347: return this ;
348: }
349:
350: /**
351: * Returns the hint type of this type set. This returns the singleton
352: * set containing only the `most likely' type in this set. This doesn't
353: * work for <code>tError</code> or <code>tUnknown</code>, and may lead
354: * to errors for certain range types.
355: * @return the hint type.
356: */
357: public Type getHint() {
358: return getCanonic();
359: }
360:
361: /**
362: * Returns the canonic type of this type set. The intention is, to
363: * return for each expression the type, that the java compiler would
364: * assign to this expression.
365: * @return the canonic type.
366: */
367: public Type getCanonic() {
368: return this ;
369: }
370:
371: /**
372: * Returns the type code of this type. Don't use this; it is
373: * merily needed by the sub types (and the bytecode verifier, which
374: * has its own type merging methods).
375: * @return the type code of the type.
376: */
377: public final int getTypeCode() {
378: return typecode;
379: }
380:
381: /**
382: * Returns the number of stack/local entries an object of this type
383: * occupies.
384: * @return 0 for tVoid, 2 for tDouble and tLong and
385: * 1 for every other type.
386: */
387: public int stackSize() {
388: switch (typecode) {
389: case TC_VOID:
390: return 0;
391: case TC_ERROR:
392: default:
393: return 1;
394: case TC_DOUBLE:
395: case TC_LONG:
396: return 2;
397: }
398: }
399:
400: /**
401: * Intersect this set of types with another type set and return the
402: * intersection.
403: * @param type the other type set.
404: * @return the intersection, tError, if the intersection is empty.
405: */
406: public Type intersection(Type type) {
407: if (this == tError || type == tError)
408: return tError;
409: if (this == tUnknown)
410: return type;
411: if (type == tUnknown || this == type)
412: return this ;
413: /* We have two different singleton sets now.
414: */
415: if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0)
416: GlobalOptions.err.println("intersecting " + this + " and "
417: + type + " to <error>");
418: return tError;
419: }
420:
421: /**
422: * Checks if we need to cast to a middle type, before we can cast from
423: * fromType to this type. For example it is impossible to cast a
424: * String to a StringBuffer, but if we cast to Object in between this
425: * is allowed (it doesn't make much sense though).
426: * @return the middle type, or null if it is not necessary.
427: */
428: public Type getCastHelper(Type fromType) {
429: return null;
430: }
431:
432: /**
433: * Checks if this type represents a valid singleton type.
434: */
435: public boolean isValidType() {
436: return typecode <= TC_DOUBLE;
437: }
438:
439: /**
440: * Checks if this is a class or array type (but not a null type).
441: * @XXX remove this?
442: * @return true if this is a class or array type.
443: */
444: public boolean isClassType() {
445: return false;
446: }
447:
448: /**
449: * Check if this type set and the other type set are not disjunct.
450: * @param type the other type set.
451: * @return true if this they aren't disjunct.
452: */
453: public boolean isOfType(Type type) {
454: return this .intersection(type) != Type.tError;
455: }
456:
457: /**
458: * Generates the default name, that is the `natural' choice for
459: * local of this type.
460: * @return the default name of a local of this type.
461: */
462: public String getDefaultName() {
463: switch (typecode) {
464: case TC_LONG:
465: return "l";
466: case TC_FLOAT:
467: return "f";
468: case TC_DOUBLE:
469: return "d";
470: default:
471: return "local";
472: }
473: }
474:
475: /**
476: * Generates the default value, that is the initial value of a field
477: * of this type.
478: * @return the default value of a field of this type.
479: */
480: public Object getDefaultValue() {
481: switch (typecode) {
482: case TC_LONG:
483: return new Long(0);
484: case TC_FLOAT:
485: return new Float(0);
486: case TC_DOUBLE:
487: return new Double(0);
488: default:
489: return null;
490: }
491: }
492:
493: /**
494: * Returns the type signature of this type. You should only call
495: * this on singleton types.
496: * @return the type (or method) signature of this type.
497: */
498: public String getTypeSignature() {
499: switch (typecode) {
500: case TC_LONG:
501: return "J";
502: case TC_FLOAT:
503: return "F";
504: case TC_DOUBLE:
505: return "D";
506: default:
507: return "?";
508: }
509: }
510:
511: /**
512: * Returns the java.lang.Class representing this type. You should
513: * only call this on singleton types.
514: * @return the Class object representing this type.
515: */
516: public Class getTypeClass() throws ClassNotFoundException {
517: switch (typecode) {
518: case TC_LONG:
519: return Long.TYPE;
520: case TC_FLOAT:
521: return Float.TYPE;
522: case TC_DOUBLE:
523: return Double.TYPE;
524: default:
525: throw new AssertError(
526: "getTypeClass() called on illegal type");
527: }
528: }
529:
530: /**
531: * Returns a string representation describing this type set.
532: * @return a string representation describing this type set.
533: */
534: public String toString() {
535: switch (typecode) {
536: case TC_LONG:
537: return "long";
538: case TC_FLOAT:
539: return "float";
540: case TC_DOUBLE:
541: return "double";
542: case TC_NULL:
543: return "null";
544: case TC_VOID:
545: return "void";
546: case TC_UNKNOWN:
547: return "<unknown>";
548: case TC_ERROR:
549: default:
550: return "<error>";
551: }
552: }
553: }
|