1 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 ; 27 28 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 63 public static final Type tBoolean = new IntegerType(IntegerType.IT_Z); 64 67 public static final Type tByte = new IntegerType(IntegerType.IT_B); 68 71 public static final Type tChar = new IntegerType(IntegerType.IT_C); 72 75 public static final Type tShort = new IntegerType(IntegerType.IT_S); 76 79 public static final Type tInt = new IntegerType(IntegerType.IT_I); 80 83 public static final Type tLong = new Type(TC_LONG); 84 87 public static final Type tFloat = new Type(TC_FLOAT); 88 91 public static final Type tDouble = new Type(TC_DOUBLE); 92 96 public static final Type tVoid = new Type(TC_VOID); 97 101 public static final Type tError = new Type(TC_ERROR); 102 105 public static final Type tUnknown = new Type(TC_UNKNOWN); 106 109 public static final Type tUInt = new IntegerType(IntegerType.IT_I 110 | IntegerType.IT_B 111 | IntegerType.IT_C 112 | IntegerType.IT_S); 113 116 public static final Type tBoolInt = new IntegerType(IntegerType.IT_I 117 | IntegerType.IT_Z); 118 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 130 public static final Type tBoolByte= new IntegerType(IntegerType.IT_B 131 | IntegerType.IT_Z); 132 136 public static final ClassInterfacesType tObject = 137 tClass("java.lang.Object"); 138 142 public static final ReferenceType tNull = new NullType(); 143 147 public static final Type tUObject = tRange(tObject, tNull); 148 152 public static final Type tString = tClass("java.lang.String"); 153 157 public static final Type tStringBuffer = tClass("java.lang.StringBuffer"); 158 162 public static final Type tJavaLangClass = tClass("java.lang.Class"); 163 164 170 public static final Type tType(String 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 212 public static final ClassInterfacesType tClass(String clazzname) { 213 return tClass(ClassInfo.forName(clazzname.replace('/','.'))); 214 } 215 216 222 public static final ClassInterfacesType tClass(ClassInfo clazzinfo) { 223 int hash = clazzinfo.hashCode(); 224 Iterator 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 241 public static final Type tArray(Type type) { 242 if (type == tError) 243 return type; 244 245 int hash = type.hashCode(); 246 Iterator 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 262 public static MethodType tMethod(String signature) { 263 int hash = signature.hashCode(); 264 Iterator 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 285 public static final Type tRange(ReferenceType bottom, 286 ReferenceType top) { 287 return new RangeType(bottom, top); 288 } 289 290 302 public static Type tSuperType(Type type) { 303 return type.getSuperType(); 304 } 305 306 320 public static Type tSubType(Type type) { 321 return type.getSubType(); 322 } 323 324 327 final int typecode; 328 329 332 protected Type(int tc) { 333 typecode = tc; 334 } 335 336 340 public Type getSubType() { 341 return this; 342 } 343 344 348 public Type getSuperType() { 349 return this; 350 } 351 352 359 public Type getHint() { 360 return getCanonic(); 361 } 362 363 369 public Type getCanonic() { 370 return this; 371 } 372 373 379 public final int getTypeCode() { 380 return typecode; 381 } 382 383 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 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 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 431 public Type getCastHelper(Type fromType) { 432 return null; 433 } 434 435 438 public boolean isValidType() { 439 return typecode <= TC_DOUBLE; 440 } 441 442 447 public boolean isClassType() { 448 return false; 449 } 450 451 456 public boolean isOfType(Type type) { 457 return this.intersection(type) != Type.tError; 458 } 459 460 465 public String 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 483 public Object getDefaultValue() { 484 switch (typecode) { 485 case TC_LONG: 486 return new Long (0); 487 case TC_FLOAT: 488 return new Float (0); 489 case TC_DOUBLE: 490 return new Double (0); 491 default: 492 return null; 493 } 494 } 495 496 501 public String 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 519 public Class getTypeClass() throws ClassNotFoundException { 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 536 public String 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 |