diff --git a/jode/jode/type/Type.java b/jode/jode/type/Type.java
index 0570fc9..92ec546 100644
--- a/jode/jode/type/Type.java
+++ b/jode/jode/type/Type.java
@@ -31,55 +31,15 @@ import java.util.Hashtable;
///#endif
/**
- * This is my type class. It differs from java.lang.class, in
- * that it maintains a type range. This type range may be implicit or
- * explicit.
+ * This is my type class. It differs from java.lang.class, in that it
+ * represents a set of types. Since most times this set is infinite, it
+ * needs a special representation.
*
- *
- * Think of this global type hierarchie:
- *
- * - * tUnknown - * / | \ - * / | \ - * tObject boolean int - * / \ / \ - * / tArray short char - * other | - * classes byte - *- * - * int implements the "interface" tBoolInt. boolean and byte - * implement the "interface" tBoolByte which extends tBoolInt.
getTop
). The
- * type tUInt is - * - * specialization chooses the common sub type of the two types. It - * is used to find the start point of the intersected interval.
- * - * generalization chooses the common super type of two types. It - * is used to find the end point of the intersected interval.
- *
- * When the new interval is created with createRangeType
- * the start and end points are adjusted so that they only consists of
- * possible types.
+ * The main operation on a type sets are tSuperType, tSubType and
+ * intersection.
*
* @author Jochen Hoenicke */
public class Type {
-
public static final int TC_BOOLEAN = 0;
public static final int TC_BYTE = 1;
public static final int TC_CHAR = 2;
@@ -111,38 +71,114 @@ public class Type {
private static final Hashtable methodHash = new Hashtable();
///#endif
+ /**
+ * This type represents the singleton set containing the boolean type.
+ */
public static final Type tBoolean = new IntegerType(IntegerType.IT_Z);
+ /**
+ * This type represents the singleton set containing the byte type.
+ */
public static final Type tByte = new IntegerType(IntegerType.IT_B);
+ /**
+ * This type represents the singleton set containing the char type.
+ */
public static final Type tChar = new IntegerType(IntegerType.IT_C);
+ /**
+ * This type represents the singleton set containing the short type.
+ */
public static final Type tShort = new IntegerType(IntegerType.IT_S);
+ /**
+ * This type represents the singleton set containing the int type.
+ */
public static final Type tInt = new IntegerType(IntegerType.IT_I);
+ /**
+ * This type represents the singleton set containing the long type.
+ */
public static final Type tLong = new Type(TC_LONG);
+ /**
+ * This type represents the singleton set containing the float type.
+ */
public static final Type tFloat = new Type(TC_FLOAT);
+ /**
+ * This type represents the singleton set containing the double type.
+ */
public static final Type tDouble = new Type(TC_DOUBLE);
+ /**
+ * This type represents the void type. It is really not a type at
+ * all.
+ */
public static final Type tVoid = new Type(TC_VOID);
+ /**
+ * This type represents the empty set, and probably means, that something
+ * has gone wrong.
+ */
public static final Type tError = new Type(TC_ERROR);
+ /**
+ * This type represents the set of all possible types.
+ */
public static final Type tUnknown = new Type(TC_UNKNOWN);
+ /**
+ * This type represents the set of all integer types, up to 32 bit.
+ */
public static final Type tUInt = new IntegerType(IntegerType.IT_I
| IntegerType.IT_B
| IntegerType.IT_C
| IntegerType.IT_S);
+ /**
+ * This type represents the set of the boolean and int type.
+ */
public static final Type tBoolInt = new IntegerType(IntegerType.IT_I
| IntegerType.IT_Z);
+ /**
+ * This type represents the set of boolean and all integer types,
+ * up to 32 bit.
+ */
public static final Type tBoolUInt= new IntegerType(IntegerType.IT_I
| IntegerType.IT_B
| IntegerType.IT_C
| IntegerType.IT_S
| IntegerType.IT_Z);
+ /**
+ * This type represents the set of the boolean and byte type.
+ */
public static final Type tBoolByte= new IntegerType(IntegerType.IT_B
| IntegerType.IT_Z);
+ /**
+ * This type represents the singleton set containing
+ * java.lang.Object
.
+ */
public static final ClassInterfacesType tObject =
tClass("java.lang.Object");
+ /**
+ * This type represents the singleton set containing the special
+ * null type (the type of null).
+ */
public static final ReferenceType tNull = new NullType();
+ /**
+ * This type represents the set of all reference types, including
+ * class types, array types, interface types and the null type.
+ */
public static final Type tUObject = tRange(tObject, tNull);
+ /**
+ * This type represents the singleton set containing
+ * java.lang.String
.
+ */
public static final Type tString = tClass("java.lang.String");
+ /**
+ * This type represents the singleton set containing
+ * java.lang.StringBuffer
.
+ */
public static final Type tStringBuffer = tClass("java.lang.StringBuffer");
+ /**
+ * This type represents the singleton set containing
+ * java.lang.Class
.
+ */
public static final Type tJavaLangClass = tClass("java.lang.Class");
+ /**
+ * This is a private method for generating the signature of a
+ * given type.
+ */
private static final StringBuffer appendSignature(StringBuffer sb,
Class javaType) {
if (javaType.isPrimitive()) {
@@ -175,10 +211,24 @@ public class Type {
}
}
+ /**
+ * Generate the signature for the given Class.
+ * @param clazz a java.lang.Class, this may also be a primitive or
+ * array type.
+ * @return the type signature (see section 4.3.2 Field Descriptors
+ * of the JVM specification)
+ */
public static String getSignature(Class clazz) {
return appendSignature(new StringBuffer(), clazz).toString();
}
+ /**
+ * Generate a method signature.
+ * @param paramT the java.lang.Class of the parameter types of the method.
+ * @param returnT the java.lang.Class of the return type of the method.
+ * @return the method signature (see section 4.3.3 Method Descriptors
+ * of the JVM specification)
+ */
public static String getSignature(Class paramT[], Class returnT) {
StringBuffer sig = new StringBuffer("(");
for (int i=0; i< paramT.length; i++)
@@ -186,6 +236,12 @@ public class Type {
return appendSignature(sig.append(')'), returnT).toString();
}
+ /**
+ * Generate the singleton set of the type represented by the given
+ * string.
+ * @param type the type signature (or method signature).
+ * @return a singleton set containing the given type.
+ */
public static final Type tType(String type) {
if (type == null || type.length() == 0)
return tError;
@@ -221,14 +277,33 @@ public class Type {
throw new AssertError("Unknown type signature: "+type);
}
+ /**
+ * Generate the singleton set of the type represented by the given
+ * class.
+ * @param javaType the type class.
+ * @return a singleton set containing the given type.
+ */
public static final Type tType(Class javaType) {
return Type.tType(getSignature(javaType));
}
+ /**
+ * Generate the singleton set of the type represented by the given
+ * class name.
+ * @param clazzname the full qualified name of the class.
+ * The packages may be separated by `.' or `/'.
+ * @return a singleton set containing the given type.
+ */
public static final ClassInterfacesType tClass(String clazzname) {
return tClass(ClassInfo.forName(clazzname.replace('/','.')));
}
+ /**
+ * Generate the singleton set of the type represented by the given
+ * class info.
+ * @param clazzinfo the jode.bytecode.ClassInfo.
+ * @return a singleton set containing the given type.
+ */
public static final ClassInterfacesType tClass(ClassInfo clazzinfo) {
///#ifdef JDK12
/// java.lang.ref.Reference died;
@@ -250,6 +325,12 @@ public class Type {
return (ClassInterfacesType) result;
}
+ /**
+ * Generate/look up the set of the array type whose element types
+ * are in the given type set.
+ * @param type the element types (which may be the empty set tError).
+ * @return the set of array types (which may be the empty set tError).
+ */
public static final Type tArray(Type type) {
if (type == tError)
return type;
@@ -273,6 +354,11 @@ public class Type {
return result;
}
+ /**
+ * Generate/look up the method type for the given signature
+ * @param signature the method decriptor.
+ * @return a method type (a singleton set).
+ */
public static MethodType tMethod(String signature) {
///#ifdef JDK12
/// java.lang.ref.Reference died;
@@ -293,23 +379,69 @@ public class Type {
}
return result;
}
+
+ /**
+ * Generate/look up the method type for the given class
+ * @param paramT the parameter types of the method.
+ * @param returnT the return type of the method.
+ * @return a method type (a singleton set).
+ */
public static MethodType tMethod(Class paramT[], Class returnT) {
return tMethod(getSignature(paramT, returnT));
}
+ /**
+ * Generate the range type from bottom to top. This should
+ * represent all reference types, that can be casted to bottom by
+ * a widening cast and where top can be casted to. You should not
+ * use this method directly; use tSubType, tSuperType and
+ * intersection instead, which is more general.
+ * @param bottom the bottom type.
+ * @param top the top type.
+ * @return the range type.
+ */
public static final Type tRange(ReferenceType bottom,
ReferenceType top) {
return new RangeType(bottom, top);
}
-
+
+ /**
+ * Generate the set of types, to which one of the types in type can
+ * be casted to by a widening cast. The following holds:
+ *
tError
or tUnknown
, and may lead
+ * to errors for certain range types.
+ * @return the hint type.
+ */
public Type getHint() {
+ return getCanonic();
+ }
+
+ /**
+ * Returns the canonic type of this type set. The intention is, to
+ * return for each expression the type, that the java compiler would
+ * assign to this expression.
+ * @return the canonic type.
+ */
+ public Type getCanonic() {
return this;
}
/**
- * @return the type code of the type.
+ * Returns the type code of this type. Don't use this; it is
+ * merily needed by the sub types (and the bytecode verifier, which
+ * has its own type merging methods).
+ * @return the type code of the type.
*/
public final int getTypeCode() {
return typecode;
}
+ /**
+ * Returns the number of stack/local entries an object of this type
+ * occupies.
+ * @return 0 for tVoid, 2 for tDouble and tLong and
+ * 1 for every other type.
+ */
public int stackSize()
{
switch(typecode) {
@@ -361,9 +519,10 @@ public class Type {
}
/**
- * Intersect this type with another type and return the new type.
- * @param type the other type.
- * @return the intersection, or tError, if a type conflict happens.
+ * Intersect this set of types with another type set and return the
+ * intersection.
+ * @param type the other type set.
+ * @return the intersection, tError, if the intersection is empty.
*/
public Type intersection(Type type) {
if (this == tError || type == tError)
@@ -372,6 +531,8 @@ public class Type {
return type;
if (type == tUnknown || this == type)
return this;
+ /* We have two different singleton sets now.
+ */
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0)
GlobalOptions.err.println("intersecting "+ this +" and "+ type
+ " to