1 4 package gnu.bytecode; 5 import java.util.*; 6 7 public abstract class Type { 8 String signature; 9 String this_name; 11 14 int size; 15 16 ArrayType array_type; 17 18 protected Type () { } 19 20 27 public Type getImplementationType() 28 { 29 return this; 30 } 31 32 34 35 37 static WeakHashMap mapClassToType; 38 39 40 42 43 44 45 47 static java.util.Hashtable mapNameToType; 48 49 50 public static Type lookupType (String name) 51 { 52 53 56 return (Type) mapNameToType.get(name); 57 58 } 59 60 65 public static Type getType (String name) 66 { 67 68 70 java.util.Hashtable map = mapNameToType; 71 72 synchronized (map) 73 { 74 Type type = (Type) map.get(name); 75 if (type == null) 76 { 77 if (name.endsWith("[]")) 78 type = ArrayType.make(name); 79 else 80 { 81 ClassType cl = new ClassType(name); 82 cl.flags |= ClassType.EXISTING_CLASS; 83 type = cl; 84 } 85 map.put(name, type); 86 } 87 return type; 88 } 89 } 90 91 92 public synchronized static void registerTypeForClass(Class clas, Type type) 93 { 94 95 96 100 WeakHashMap map = mapClassToType; 101 if (map == null) 102 mapClassToType = map = new WeakHashMap(100); 103 104 105 109 map.put(clas, type); 110 type.reflectClass = clas; 111 } 112 113 public synchronized static Type make(Class reflectClass) 114 { 115 Type type; 116 117 if (mapClassToType != null) 118 { 119 Object t = mapClassToType.get(reflectClass); 120 if (t != null) 121 return (Type) t; 122 } 123 if (reflectClass.isArray()) 124 type = ArrayType.make(Type.make(reflectClass.getComponentType())); 125 else if (reflectClass.isPrimitive()) 126 throw new Error ("internal error - primitive type not found"); 127 else 128 { 129 String name = reflectClass.getName(); 130 131 133 java.util.Hashtable map = mapNameToType; 134 135 synchronized (map) 136 { 137 type = (Type) map.get(name); 138 if (type == null 139 || (type.reflectClass != reflectClass 140 && type.reflectClass != null)) 141 { 142 ClassType cl = new ClassType(name); 143 cl.flags |= ClassType.EXISTING_CLASS; 144 type = cl; 145 mapNameToType.put(name, type); 146 } 147 } 148 } 149 registerTypeForClass(reflectClass, type); 150 return type; 151 } 152 153 public final String getSignature () { return signature; } 154 protected void setSignature(String sig) { this.signature = sig; } 155 156 Type (String nam, String sig) { 157 this_name = nam; 158 signature = sig; 159 } 160 161 public Type (Type type) 162 { 163 this_name = type.this_name; 164 signature = type.signature; 165 size = type.size; 166 reflectClass = type.reflectClass; 167 } 168 169 public Type promote () { 170 return size < 4 ? int_type : this; 171 } 172 173 public final int getSize() { return size; } 174 public int getSizeInWords () { return size > 4 ? 2 : 1; } 175 176 public final boolean isVoid () { return size == 0; } 177 178 180 public static PrimType signatureToPrimitive(char sig) 181 { 182 switch(sig) 183 { 184 case 'B': return Type.byte_type; 185 case 'C': return Type.char_type; 186 case 'D': return Type.double_type; 187 case 'F': return Type.float_type; 188 case 'S': return Type.short_type; 189 case 'I': return Type.int_type; 190 case 'J': return Type.long_type; 191 case 'Z': return Type.boolean_type; 192 case 'V': return Type.void_type; 193 } 194 return null; 195 } 196 197 198 public static Type signatureToType(String sig, int off, int len) 199 { 200 if (len == 0) 201 return null; 202 char c = sig.charAt(off); 203 Type type; 204 if (len == 1) 205 { 206 type = signatureToPrimitive(c); 207 if (type != null) 208 return type; 209 } 210 if (c == '[') 211 { 212 type = signatureToType(sig, off+1, len-1); 213 return type == null ? null : ArrayType.make(type); 214 } 215 if (c == 'L' && len > 2 && sig.indexOf(';', off) == len-1+off) 216 return ClassType.make(sig.substring(off+1,len-1+off).replace('/', '.')); 217 return null; 218 } 219 220 221 public static Type signatureToType(String sig) 222 { 223 return signatureToType(sig, 0, sig.length()); 224 } 225 226 228 public static int signatureLength (String sig, int pos) 229 { 230 int len = sig.length(); 231 if (len <= pos) 232 return -1; 233 char c = sig.charAt(pos); 234 int arrays = 0; 235 while (c == '[') 236 { 237 arrays++; 238 pos++; 239 c = sig.charAt(pos); 240 } 241 if (signatureToPrimitive(c) != null) 242 return arrays+1; 243 if (c == 'L') 244 { 245 int end = sig.indexOf(';', pos); 246 if (end > 0) 247 return arrays + end + 1 - pos; 248 } 249 return -1; 250 } 251 252 public static int signatureLength (String sig) 253 { 254 return signatureLength(sig, 0); 255 } 256 257 259 public static String signatureToName(String sig) 260 { 261 int len = sig.length(); 262 if (len == 0) 263 return null; 264 char c = sig.charAt(0); 265 Type type; 266 if (len == 1) 267 { 268 type = signatureToPrimitive(c); 269 if (type != null) 270 return type.getName(); 271 } 272 if (c == '[') 273 { 274 int arrays = 1; 275 if (arrays < len && sig.charAt(arrays) == '[') 276 arrays++; 277 sig = signatureToName(sig.substring(arrays)); 278 if (sig == null) 279 return null; 280 StringBuffer buf = new StringBuffer (50); 281 buf.append(sig); 282 while (--arrays >= 0) 283 buf.append("[]"); 284 return buf.toString(); 285 } 286 if (c == 'L' && len > 2 && sig.indexOf(';') == len-1) 287 return sig.substring(1,len-1).replace('/', '.'); 288 return null; 289 } 290 291 public final String getName () 292 { 293 return this_name; 294 } 295 296 protected void setName (String name) 297 { 298 this_name = name; 299 } 300 301 public static boolean isValidJavaTypeName (String name) 302 { 303 boolean in_name = false; 304 int i; 305 int len = name.length(); 306 while (len > 2 && name.charAt(len-1) == ']' 307 && name.charAt(len-2) == '[') 308 len -= 2; 309 for (i = 0; i < len; i++) 310 { 311 char ch = name.charAt(i); 312 if (ch == '.') 313 { 314 if (in_name) 315 in_name = false; 316 else 317 return false; 318 } 319 else if (in_name ? Character.isJavaIdentifierPart(ch) 320 : Character.isJavaIdentifierStart(ch)) 321 in_name = true; 322 else 323 return false; 324 } 325 return i == len; 326 } 327 328 public boolean isInstance (Object obj) 329 { 330 return getReflectClass().isInstance(obj); 331 } 332 333 334 public final boolean isSubtype (Type other) 335 { 336 int comp = compare(other); 337 return comp == -1 || comp == 0; 338 } 339 340 351 public static Type lowestCommonSuperType(Type t1, Type t2) 352 { 353 if (t1 == neverReturnsType) 354 return t2; 355 if (t2 == neverReturnsType) 356 return t1; 357 if (t1 == null || t2 == null) 358 return null; 359 360 if (t1.isSubtype(t2)) 361 return t2; 362 else if (t2.isSubtype(t1)) 363 return t1; 364 else 365 { 366 if (!(t1 instanceof ClassType && t2 instanceof ClassType)) 368 return null; 369 ClassType c1 = (ClassType) t1; 370 ClassType c2 = (ClassType) t2; 371 if (c1.isInterface()) 372 return Type.pointer_type; 373 if (c2.isInterface()) 374 return Type.pointer_type; 375 376 return lowestCommonSuperType(c1.getSuperclass(), c2.getSuperclass()); 377 } 378 } 379 380 401 public abstract int compare(Type other); 402 403 404 protected static int swappedCompareResult(int code) 405 { 406 return code == 1 ? -1 : code == -1 ? 1 : code; 407 } 408 409 410 public static boolean isMoreSpecific (Type[] t1, Type[] t2) 411 { 412 if (t1.length != t2.length) 413 return false; 414 for (int i = t1.length; --i >= 0; ) 415 { 416 if (! t1[i].isSubtype(t2[i])) 417 return false; 418 } 419 return true; 420 } 421 422 public void emitIsInstance (CodeAttr code) 423 { 424 code.emitInstanceof(this); 425 } 426 427 429 public abstract Object coerceFromObject (Object obj); 430 431 public Object coerceToObject (Object obj) 432 { 433 return obj; 434 } 435 436 437 public void emitCoerceToObject (CodeAttr code) 438 { 439 } 440 441 442 public void emitCoerceFromObject (CodeAttr code) 443 { 444 throw new Error ("unimplemented emitCoerceFromObject for "+this); 445 } 446 447 public static final PrimType byte_type 448 = new PrimType ("byte", "B", 1, java.lang.Byte.TYPE); 449 public static final PrimType short_type 450 = new PrimType ("short", "S", 2, java.lang.Short.TYPE); 451 public static final PrimType int_type 452 = new PrimType ("int", "I", 4, java.lang.Integer.TYPE); 453 public static final PrimType long_type 454 = new PrimType ("long", "J", 8, java.lang.Long.TYPE); 455 public static final PrimType float_type 456 = new PrimType ("float", "F", 4, java.lang.Float.TYPE); 457 public static final PrimType double_type 458 = new PrimType ("double", "D", 8, java.lang.Double.TYPE); 459 public static final PrimType boolean_type 460 = new PrimType ("boolean", "Z", 1, java.lang.Boolean.TYPE); 461 public static final PrimType char_type 462 = new PrimType ("char", "C", 2, java.lang.Character.TYPE); 463 public static final PrimType void_type 464 = new PrimType ("void", "V", 0, java.lang.Void.TYPE); 465 466 static 467 { 468 469 471 mapNameToType = new java.util.Hashtable (); 472 473 mapNameToType.put("byte", byte_type); 474 mapNameToType.put("short", short_type); 475 mapNameToType.put("int", int_type); 476 mapNameToType.put("long", long_type); 477 mapNameToType.put("float", float_type); 478 mapNameToType.put("double", double_type); 479 mapNameToType.put("boolean", boolean_type); 480 mapNameToType.put("char", char_type); 481 mapNameToType.put("void", void_type); 482 } 483 484 485 public static final PrimType neverReturnsType = new PrimType (void_type); 486 static { neverReturnsType.this_name = "(never-returns)"; } 487 488 489 public static final ObjectType nullType = new ObjectType("(type of null)"); 490 491 static public ClassType string_type = ClassType.make("java.lang.String"); 492 493 public static final ClassType tostring_type 494 = new ClassType("java.lang.String"); 495 496 public static final ClassType pointer_type 497 = ClassType.make("java.lang.Object"); 498 public static final ClassType boolean_ctype 499 = ClassType.make("java.lang.Boolean"); 500 public static final ClassType throwable_type 501 = ClassType.make("java.lang.Throwable"); 502 public static final Type[] typeArray0 = new Type[0]; 503 public static final Method toString_method 504 = pointer_type.getDeclaredMethod("toString", 0); 505 public static final ClassType number_type 506 = ClassType.make("java.lang.Number"); 507 public static final Method intValue_method 508 = number_type.addMethod("intValue", typeArray0, 509 int_type, Access.PUBLIC); 510 public static final Method longValue_method 511 = number_type.addMethod("longValue", typeArray0, 512 long_type, Access.PUBLIC); 513 public static final Method floatValue_method 514 = number_type.addMethod("floatValue", typeArray0, 515 float_type, Access.PUBLIC); 516 public static final Method doubleValue_method 517 = number_type.addMethod("doubleValue", typeArray0, 518 double_type, Access.PUBLIC); 519 public static final Method booleanValue_method 520 = boolean_ctype.addMethod("booleanValue", typeArray0, 521 boolean_type, Access.PUBLIC); 522 public static final ClassType java_lang_Class_type 523 = ClassType.make("java.lang.Class"); 524 525 protected Class reflectClass; 526 527 528 public java.lang.Class getReflectClass() 529 { 530 return reflectClass; 531 } 532 533 public void setReflectClass(java.lang.Class rclass) 534 { 535 reflectClass = rclass; 536 } 537 538 public String toString() 539 { 540 return "Type " + getName(); 541 } 542 543 public int hashCode() 544 { 545 String name = toString(); 546 return name == null ? 0 : name.hashCode (); 547 } 548 } 549 | Popular Tags |