Mercurial > lasercutter
comparison src/clojure/asm/Type.java @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
1 /*** | |
2 * ASM: a very small and fast Java bytecode manipulation framework | |
3 * Copyright (c) 2000-2005 INRIA, France Telecom | |
4 * All rights reserved. | |
5 * | |
6 * Redistribution and use in source and binary forms, with or without | |
7 * modification, are permitted provided that the following conditions | |
8 * are met: | |
9 * 1. Redistributions of source code must retain the above copyright | |
10 * notice, this list of conditions and the following disclaimer. | |
11 * 2. Redistributions in binary form must reproduce the above copyright | |
12 * notice, this list of conditions and the following disclaimer in the | |
13 * documentation and/or other materials provided with the distribution. | |
14 * 3. Neither the name of the copyright holders nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
28 * THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 package clojure.asm; | |
31 | |
32 import java.lang.reflect.Constructor; | |
33 import java.lang.reflect.Method; | |
34 | |
35 /** | |
36 * A Java type. This class can be used to make it easier to manipulate type and | |
37 * method descriptors. | |
38 * | |
39 * @author Eric Bruneton | |
40 * @author Chris Nokleberg | |
41 */ | |
42 public class Type{ | |
43 | |
44 /** | |
45 * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. | |
46 */ | |
47 public final static int VOID = 0; | |
48 | |
49 /** | |
50 * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. | |
51 */ | |
52 public final static int BOOLEAN = 1; | |
53 | |
54 /** | |
55 * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. | |
56 */ | |
57 public final static int CHAR = 2; | |
58 | |
59 /** | |
60 * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. | |
61 */ | |
62 public final static int BYTE = 3; | |
63 | |
64 /** | |
65 * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. | |
66 */ | |
67 public final static int SHORT = 4; | |
68 | |
69 /** | |
70 * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. | |
71 */ | |
72 public final static int INT = 5; | |
73 | |
74 /** | |
75 * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. | |
76 */ | |
77 public final static int FLOAT = 6; | |
78 | |
79 /** | |
80 * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. | |
81 */ | |
82 public final static int LONG = 7; | |
83 | |
84 /** | |
85 * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. | |
86 */ | |
87 public final static int DOUBLE = 8; | |
88 | |
89 /** | |
90 * The sort of array reference types. See {@link #getSort getSort}. | |
91 */ | |
92 public final static int ARRAY = 9; | |
93 | |
94 /** | |
95 * The sort of object reference type. See {@link #getSort getSort}. | |
96 */ | |
97 public final static int OBJECT = 10; | |
98 | |
99 /** | |
100 * The <tt>void</tt> type. | |
101 */ | |
102 public final static Type VOID_TYPE = new Type(VOID); | |
103 | |
104 /** | |
105 * The <tt>boolean</tt> type. | |
106 */ | |
107 public final static Type BOOLEAN_TYPE = new Type(BOOLEAN); | |
108 | |
109 /** | |
110 * The <tt>char</tt> type. | |
111 */ | |
112 public final static Type CHAR_TYPE = new Type(CHAR); | |
113 | |
114 /** | |
115 * The <tt>byte</tt> type. | |
116 */ | |
117 public final static Type BYTE_TYPE = new Type(BYTE); | |
118 | |
119 /** | |
120 * The <tt>short</tt> type. | |
121 */ | |
122 public final static Type SHORT_TYPE = new Type(SHORT); | |
123 | |
124 /** | |
125 * The <tt>int</tt> type. | |
126 */ | |
127 public final static Type INT_TYPE = new Type(INT); | |
128 | |
129 /** | |
130 * The <tt>float</tt> type. | |
131 */ | |
132 public final static Type FLOAT_TYPE = new Type(FLOAT); | |
133 | |
134 /** | |
135 * The <tt>long</tt> type. | |
136 */ | |
137 public final static Type LONG_TYPE = new Type(LONG); | |
138 | |
139 /** | |
140 * The <tt>double</tt> type. | |
141 */ | |
142 public final static Type DOUBLE_TYPE = new Type(DOUBLE); | |
143 | |
144 // ------------------------------------------------------------------------ | |
145 // Fields | |
146 // ------------------------------------------------------------------------ | |
147 | |
148 /** | |
149 * The sort of this Java type. | |
150 */ | |
151 private final int sort; | |
152 | |
153 /** | |
154 * A buffer containing the descriptor of this Java type. This field is only | |
155 * used for reference types. | |
156 */ | |
157 private char[] buf; | |
158 | |
159 /** | |
160 * The offset of the descriptor of this Java type in {@link #buf buf}. This | |
161 * field is only used for reference types. | |
162 */ | |
163 private int off; | |
164 | |
165 /** | |
166 * The length of the descriptor of this Java type. | |
167 */ | |
168 private int len; | |
169 | |
170 // ------------------------------------------------------------------------ | |
171 // Constructors | |
172 // ------------------------------------------------------------------------ | |
173 | |
174 /** | |
175 * Constructs a primitive type. | |
176 * | |
177 * @param sort the sort of the primitive type to be constructed. | |
178 */ | |
179 private Type(final int sort){ | |
180 this.sort = sort; | |
181 this.len = 1; | |
182 } | |
183 | |
184 /** | |
185 * Constructs a reference type. | |
186 * | |
187 * @param sort the sort of the reference type to be constructed. | |
188 * @param buf a buffer containing the descriptor of the previous type. | |
189 * @param off the offset of this descriptor in the previous buffer. | |
190 * @param len the length of this descriptor. | |
191 */ | |
192 private Type(final int sort, final char[] buf, final int off, final int len){ | |
193 this.sort = sort; | |
194 this.buf = buf; | |
195 this.off = off; | |
196 this.len = len; | |
197 } | |
198 | |
199 /** | |
200 * Returns the Java type corresponding to the given type descriptor. | |
201 * | |
202 * @param typeDescriptor a type descriptor. | |
203 * @return the Java type corresponding to the given type descriptor. | |
204 */ | |
205 public static Type getType(final String typeDescriptor){ | |
206 return getType(typeDescriptor.toCharArray(), 0); | |
207 } | |
208 | |
209 /** | |
210 * Returns the Java type corresponding to the given class. | |
211 * | |
212 * @param c a class. | |
213 * @return the Java type corresponding to the given class. | |
214 */ | |
215 public static Type getType(final Class c){ | |
216 if(c.isPrimitive()) | |
217 { | |
218 if(c == Integer.TYPE) | |
219 { | |
220 return INT_TYPE; | |
221 } | |
222 else if(c == Void.TYPE) | |
223 { | |
224 return VOID_TYPE; | |
225 } | |
226 else if(c == Boolean.TYPE) | |
227 { | |
228 return BOOLEAN_TYPE; | |
229 } | |
230 else if(c == Byte.TYPE) | |
231 { | |
232 return BYTE_TYPE; | |
233 } | |
234 else if(c == Character.TYPE) | |
235 { | |
236 return CHAR_TYPE; | |
237 } | |
238 else if(c == Short.TYPE) | |
239 { | |
240 return SHORT_TYPE; | |
241 } | |
242 else if(c == Double.TYPE) | |
243 { | |
244 return DOUBLE_TYPE; | |
245 } | |
246 else if(c == Float.TYPE) | |
247 { | |
248 return FLOAT_TYPE; | |
249 } | |
250 else /* if (c == Long.TYPE) */ | |
251 { | |
252 return LONG_TYPE; | |
253 } | |
254 } | |
255 else | |
256 { | |
257 return getType(getDescriptor(c)); | |
258 } | |
259 } | |
260 | |
261 /** | |
262 * Returns the {@link Type#OBJECT} type for the given internal class name. | |
263 * This is a shortcut method for <code>Type.getType("L"+name+";")</code>. | |
264 * <i>Note that opposed to {@link Type#getType(String)}, this method takes | |
265 * internal class names and not class descriptor.</i> | |
266 * | |
267 * @param name an internal class name. | |
268 * @return the the {@link Type#OBJECT} type for the given class name. | |
269 */ | |
270 public static Type getObjectType(String name){ | |
271 int l = name.length(); | |
272 char[] buf = new char[l + 2]; | |
273 buf[0] = 'L'; | |
274 buf[l + 1] = ';'; | |
275 name.getChars(0, l, buf, 1); | |
276 return new Type(OBJECT, buf, 0, l + 2); | |
277 } | |
278 | |
279 /** | |
280 * Returns the Java types corresponding to the argument types of the given | |
281 * method descriptor. | |
282 * | |
283 * @param methodDescriptor a method descriptor. | |
284 * @return the Java types corresponding to the argument types of the given | |
285 * method descriptor. | |
286 */ | |
287 public static Type[] getArgumentTypes(final String methodDescriptor){ | |
288 char[] buf = methodDescriptor.toCharArray(); | |
289 int off = 1; | |
290 int size = 0; | |
291 while(true) | |
292 { | |
293 char car = buf[off++]; | |
294 if(car == ')') | |
295 { | |
296 break; | |
297 } | |
298 else if(car == 'L') | |
299 { | |
300 while(buf[off++] != ';') | |
301 { | |
302 } | |
303 ++size; | |
304 } | |
305 else if(car != '[') | |
306 { | |
307 ++size; | |
308 } | |
309 } | |
310 Type[] args = new Type[size]; | |
311 off = 1; | |
312 size = 0; | |
313 while(buf[off] != ')') | |
314 { | |
315 args[size] = getType(buf, off); | |
316 off += args[size].len; | |
317 size += 1; | |
318 } | |
319 return args; | |
320 } | |
321 | |
322 /** | |
323 * Returns the Java types corresponding to the argument types of the given | |
324 * method. | |
325 * | |
326 * @param method a method. | |
327 * @return the Java types corresponding to the argument types of the given | |
328 * method. | |
329 */ | |
330 public static Type[] getArgumentTypes(final Method method){ | |
331 Class[] classes = method.getParameterTypes(); | |
332 Type[] types = new Type[classes.length]; | |
333 for(int i = classes.length - 1; i >= 0; --i) | |
334 { | |
335 types[i] = getType(classes[i]); | |
336 } | |
337 return types; | |
338 } | |
339 | |
340 /** | |
341 * Returns the Java type corresponding to the return type of the given | |
342 * method descriptor. | |
343 * | |
344 * @param methodDescriptor a method descriptor. | |
345 * @return the Java type corresponding to the return type of the given | |
346 * method descriptor. | |
347 */ | |
348 public static Type getReturnType(final String methodDescriptor){ | |
349 char[] buf = methodDescriptor.toCharArray(); | |
350 return getType(buf, methodDescriptor.indexOf(')') + 1); | |
351 } | |
352 | |
353 /** | |
354 * Returns the Java type corresponding to the return type of the given | |
355 * method. | |
356 * | |
357 * @param method a method. | |
358 * @return the Java type corresponding to the return type of the given | |
359 * method. | |
360 */ | |
361 public static Type getReturnType(final Method method){ | |
362 return getType(method.getReturnType()); | |
363 } | |
364 | |
365 /** | |
366 * Returns the Java type corresponding to the given type descriptor. | |
367 * | |
368 * @param buf a buffer containing a type descriptor. | |
369 * @param off the offset of this descriptor in the previous buffer. | |
370 * @return the Java type corresponding to the given type descriptor. | |
371 */ | |
372 private static Type getType(final char[] buf, final int off){ | |
373 int len; | |
374 switch(buf[off]) | |
375 { | |
376 case'V': | |
377 return VOID_TYPE; | |
378 case'Z': | |
379 return BOOLEAN_TYPE; | |
380 case'C': | |
381 return CHAR_TYPE; | |
382 case'B': | |
383 return BYTE_TYPE; | |
384 case'S': | |
385 return SHORT_TYPE; | |
386 case'I': | |
387 return INT_TYPE; | |
388 case'F': | |
389 return FLOAT_TYPE; | |
390 case'J': | |
391 return LONG_TYPE; | |
392 case'D': | |
393 return DOUBLE_TYPE; | |
394 case'[': | |
395 len = 1; | |
396 while(buf[off + len] == '[') | |
397 { | |
398 ++len; | |
399 } | |
400 if(buf[off + len] == 'L') | |
401 { | |
402 ++len; | |
403 while(buf[off + len] != ';') | |
404 { | |
405 ++len; | |
406 } | |
407 } | |
408 return new Type(ARRAY, buf, off, len + 1); | |
409 // case 'L': | |
410 default: | |
411 len = 1; | |
412 while(buf[off + len] != ';') | |
413 { | |
414 ++len; | |
415 } | |
416 return new Type(OBJECT, buf, off, len + 1); | |
417 } | |
418 } | |
419 | |
420 // ------------------------------------------------------------------------ | |
421 // Accessors | |
422 // ------------------------------------------------------------------------ | |
423 | |
424 /** | |
425 * Returns the sort of this Java type. | |
426 * | |
427 * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, | |
428 * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT}, | |
429 * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG}, | |
430 * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or | |
431 * {@link #OBJECT OBJECT}. | |
432 */ | |
433 public int getSort(){ | |
434 return sort; | |
435 } | |
436 | |
437 /** | |
438 * Returns the number of dimensions of this array type. This method should | |
439 * only be used for an array type. | |
440 * | |
441 * @return the number of dimensions of this array type. | |
442 */ | |
443 public int getDimensions(){ | |
444 int i = 1; | |
445 while(buf[off + i] == '[') | |
446 { | |
447 ++i; | |
448 } | |
449 return i; | |
450 } | |
451 | |
452 /** | |
453 * Returns the type of the elements of this array type. This method should | |
454 * only be used for an array type. | |
455 * | |
456 * @return Returns the type of the elements of this array type. | |
457 */ | |
458 public Type getElementType(){ | |
459 return getType(buf, off + getDimensions()); | |
460 } | |
461 | |
462 /** | |
463 * Returns the name of the class corresponding to this type. | |
464 * | |
465 * @return the fully qualified name of the class corresponding to this type. | |
466 */ | |
467 public String getClassName(){ | |
468 switch(sort) | |
469 { | |
470 case VOID: | |
471 return "void"; | |
472 case BOOLEAN: | |
473 return "boolean"; | |
474 case CHAR: | |
475 return "char"; | |
476 case BYTE: | |
477 return "byte"; | |
478 case SHORT: | |
479 return "short"; | |
480 case INT: | |
481 return "int"; | |
482 case FLOAT: | |
483 return "float"; | |
484 case LONG: | |
485 return "long"; | |
486 case DOUBLE: | |
487 return "double"; | |
488 case ARRAY: | |
489 StringBuffer b = new StringBuffer(getElementType().getClassName()); | |
490 for(int i = getDimensions(); i > 0; --i) | |
491 { | |
492 b.append("[]"); | |
493 } | |
494 return b.toString(); | |
495 // case OBJECT: | |
496 default: | |
497 return new String(buf, off + 1, len - 2).replace('/', '.'); | |
498 } | |
499 } | |
500 | |
501 /** | |
502 * Returns the internal name of the class corresponding to this object type. | |
503 * The internal name of a class is its fully qualified name, where '.' are | |
504 * replaced by '/'. This method should only be used for an object type. | |
505 * | |
506 * @return the internal name of the class corresponding to this object type. | |
507 */ | |
508 public String getInternalName(){ | |
509 return new String(buf, off + 1, len - 2); | |
510 } | |
511 | |
512 // ------------------------------------------------------------------------ | |
513 // Conversion to type descriptors | |
514 // ------------------------------------------------------------------------ | |
515 | |
516 /** | |
517 * Returns the descriptor corresponding to this Java type. | |
518 * | |
519 * @return the descriptor corresponding to this Java type. | |
520 */ | |
521 public String getDescriptor(){ | |
522 StringBuffer buf = new StringBuffer(); | |
523 getDescriptor(buf); | |
524 return buf.toString(); | |
525 } | |
526 | |
527 /** | |
528 * Returns the descriptor corresponding to the given argument and return | |
529 * types. | |
530 * | |
531 * @param returnType the return type of the method. | |
532 * @param argumentTypes the argument types of the method. | |
533 * @return the descriptor corresponding to the given argument and return | |
534 * types. | |
535 */ | |
536 public static String getMethodDescriptor( | |
537 final Type returnType, | |
538 final Type[] argumentTypes){ | |
539 StringBuffer buf = new StringBuffer(); | |
540 buf.append('('); | |
541 for(int i = 0; i < argumentTypes.length; ++i) | |
542 { | |
543 argumentTypes[i].getDescriptor(buf); | |
544 } | |
545 buf.append(')'); | |
546 returnType.getDescriptor(buf); | |
547 return buf.toString(); | |
548 } | |
549 | |
550 /** | |
551 * Appends the descriptor corresponding to this Java type to the given | |
552 * string buffer. | |
553 * | |
554 * @param buf the string buffer to which the descriptor must be appended. | |
555 */ | |
556 private void getDescriptor(final StringBuffer buf){ | |
557 switch(sort) | |
558 { | |
559 case VOID: | |
560 buf.append('V'); | |
561 return; | |
562 case BOOLEAN: | |
563 buf.append('Z'); | |
564 return; | |
565 case CHAR: | |
566 buf.append('C'); | |
567 return; | |
568 case BYTE: | |
569 buf.append('B'); | |
570 return; | |
571 case SHORT: | |
572 buf.append('S'); | |
573 return; | |
574 case INT: | |
575 buf.append('I'); | |
576 return; | |
577 case FLOAT: | |
578 buf.append('F'); | |
579 return; | |
580 case LONG: | |
581 buf.append('J'); | |
582 return; | |
583 case DOUBLE: | |
584 buf.append('D'); | |
585 return; | |
586 // case ARRAY: | |
587 // case OBJECT: | |
588 default: | |
589 buf.append(this.buf, off, len); | |
590 } | |
591 } | |
592 | |
593 // ------------------------------------------------------------------------ | |
594 // Direct conversion from classes to type descriptors, | |
595 // without intermediate Type objects | |
596 // ------------------------------------------------------------------------ | |
597 | |
598 /** | |
599 * Returns the internal name of the given class. The internal name of a | |
600 * class is its fully qualified name, where '.' are replaced by '/'. | |
601 * | |
602 * @param c an object class. | |
603 * @return the internal name of the given class. | |
604 */ | |
605 public static String getInternalName(final Class c){ | |
606 return c.getName().replace('.', '/'); | |
607 } | |
608 | |
609 /** | |
610 * Returns the descriptor corresponding to the given Java type. | |
611 * | |
612 * @param c an object class, a primitive class or an array class. | |
613 * @return the descriptor corresponding to the given class. | |
614 */ | |
615 public static String getDescriptor(final Class c){ | |
616 StringBuffer buf = new StringBuffer(); | |
617 getDescriptor(buf, c); | |
618 return buf.toString(); | |
619 } | |
620 | |
621 /** | |
622 * Returns the descriptor corresponding to the given constructor. | |
623 * | |
624 * @param c a {@link Constructor Constructor} object. | |
625 * @return the descriptor of the given constructor. | |
626 */ | |
627 public static String getConstructorDescriptor(final Constructor c){ | |
628 Class[] parameters = c.getParameterTypes(); | |
629 StringBuffer buf = new StringBuffer(); | |
630 buf.append('('); | |
631 for(int i = 0; i < parameters.length; ++i) | |
632 { | |
633 getDescriptor(buf, parameters[i]); | |
634 } | |
635 return buf.append(")V").toString(); | |
636 } | |
637 | |
638 /** | |
639 * Returns the descriptor corresponding to the given method. | |
640 * | |
641 * @param m a {@link Method Method} object. | |
642 * @return the descriptor of the given method. | |
643 */ | |
644 public static String getMethodDescriptor(final Method m){ | |
645 Class[] parameters = m.getParameterTypes(); | |
646 StringBuffer buf = new StringBuffer(); | |
647 buf.append('('); | |
648 for(int i = 0; i < parameters.length; ++i) | |
649 { | |
650 getDescriptor(buf, parameters[i]); | |
651 } | |
652 buf.append(')'); | |
653 getDescriptor(buf, m.getReturnType()); | |
654 return buf.toString(); | |
655 } | |
656 | |
657 /** | |
658 * Appends the descriptor of the given class to the given string buffer. | |
659 * | |
660 * @param buf the string buffer to which the descriptor must be appended. | |
661 * @param c the class whose descriptor must be computed. | |
662 */ | |
663 private static void getDescriptor(final StringBuffer buf, final Class c){ | |
664 Class d = c; | |
665 while(true) | |
666 { | |
667 if(d.isPrimitive()) | |
668 { | |
669 char car; | |
670 if(d == Integer.TYPE) | |
671 { | |
672 car = 'I'; | |
673 } | |
674 else if(d == Void.TYPE) | |
675 { | |
676 car = 'V'; | |
677 } | |
678 else if(d == Boolean.TYPE) | |
679 { | |
680 car = 'Z'; | |
681 } | |
682 else if(d == Byte.TYPE) | |
683 { | |
684 car = 'B'; | |
685 } | |
686 else if(d == Character.TYPE) | |
687 { | |
688 car = 'C'; | |
689 } | |
690 else if(d == Short.TYPE) | |
691 { | |
692 car = 'S'; | |
693 } | |
694 else if(d == Double.TYPE) | |
695 { | |
696 car = 'D'; | |
697 } | |
698 else if(d == Float.TYPE) | |
699 { | |
700 car = 'F'; | |
701 } | |
702 else /* if (d == Long.TYPE) */ | |
703 { | |
704 car = 'J'; | |
705 } | |
706 buf.append(car); | |
707 return; | |
708 } | |
709 else if(d.isArray()) | |
710 { | |
711 buf.append('['); | |
712 d = d.getComponentType(); | |
713 } | |
714 else | |
715 { | |
716 buf.append('L'); | |
717 String name = d.getName(); | |
718 int len = name.length(); | |
719 for(int i = 0; i < len; ++i) | |
720 { | |
721 char car = name.charAt(i); | |
722 buf.append(car == '.' ? '/' : car); | |
723 } | |
724 buf.append(';'); | |
725 return; | |
726 } | |
727 } | |
728 } | |
729 | |
730 // ------------------------------------------------------------------------ | |
731 // Corresponding size and opcodes | |
732 // ------------------------------------------------------------------------ | |
733 | |
734 /** | |
735 * Returns the size of values of this type. | |
736 * | |
737 * @return the size of values of this type, i.e., 2 for <tt>long</tt> and | |
738 * <tt>double</tt>, and 1 otherwise. | |
739 */ | |
740 public int getSize(){ | |
741 return sort == LONG || sort == DOUBLE ? 2 : 1; | |
742 } | |
743 | |
744 /** | |
745 * Returns a JVM instruction opcode adapted to this Java type. | |
746 * | |
747 * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD, | |
748 * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL, | |
749 * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. | |
750 * @return an opcode that is similar to the given opcode, but adapted to | |
751 * this Java type. For example, if this type is <tt>float</tt> and | |
752 * <tt>opcode</tt> is IRETURN, this method returns FRETURN. | |
753 */ | |
754 public int getOpcode(final int opcode){ | |
755 if(opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) | |
756 { | |
757 switch(sort) | |
758 { | |
759 case BOOLEAN: | |
760 case BYTE: | |
761 return opcode + 5; | |
762 case CHAR: | |
763 return opcode + 6; | |
764 case SHORT: | |
765 return opcode + 7; | |
766 case INT: | |
767 return opcode; | |
768 case FLOAT: | |
769 return opcode + 2; | |
770 case LONG: | |
771 return opcode + 1; | |
772 case DOUBLE: | |
773 return opcode + 3; | |
774 // case ARRAY: | |
775 // case OBJECT: | |
776 default: | |
777 return opcode + 4; | |
778 } | |
779 } | |
780 else | |
781 { | |
782 switch(sort) | |
783 { | |
784 case VOID: | |
785 return opcode + 5; | |
786 case BOOLEAN: | |
787 case CHAR: | |
788 case BYTE: | |
789 case SHORT: | |
790 case INT: | |
791 return opcode; | |
792 case FLOAT: | |
793 return opcode + 2; | |
794 case LONG: | |
795 return opcode + 1; | |
796 case DOUBLE: | |
797 return opcode + 3; | |
798 // case ARRAY: | |
799 // case OBJECT: | |
800 default: | |
801 return opcode + 4; | |
802 } | |
803 } | |
804 } | |
805 | |
806 // ------------------------------------------------------------------------ | |
807 // Equals, hashCode and toString | |
808 // ------------------------------------------------------------------------ | |
809 | |
810 /** | |
811 * Tests if the given object is equal to this type. | |
812 * | |
813 * @param o the object to be compared to this type. | |
814 * @return <tt>true</tt> if the given object is equal to this type. | |
815 */ | |
816 public boolean equals(final Object o){ | |
817 if(this == o) | |
818 { | |
819 return true; | |
820 } | |
821 if(!(o instanceof Type)) | |
822 { | |
823 return false; | |
824 } | |
825 Type t = (Type) o; | |
826 if(sort != t.sort) | |
827 { | |
828 return false; | |
829 } | |
830 if(sort == Type.OBJECT || sort == Type.ARRAY) | |
831 { | |
832 if(len != t.len) | |
833 { | |
834 return false; | |
835 } | |
836 for(int i = off, j = t.off, end = i + len; i < end; i++, j++) | |
837 { | |
838 if(buf[i] != t.buf[j]) | |
839 { | |
840 return false; | |
841 } | |
842 } | |
843 } | |
844 return true; | |
845 } | |
846 | |
847 /** | |
848 * Returns a hash code value for this type. | |
849 * | |
850 * @return a hash code value for this type. | |
851 */ | |
852 public int hashCode(){ | |
853 int hc = 13 * sort; | |
854 if(sort == Type.OBJECT || sort == Type.ARRAY) | |
855 { | |
856 for(int i = off, end = i + len; i < end; i++) | |
857 { | |
858 hc = 17 * (hc + buf[i]); | |
859 } | |
860 } | |
861 return hc; | |
862 } | |
863 | |
864 /** | |
865 * Returns a string representation of this type. | |
866 * | |
867 * @return the descriptor of this type. | |
868 */ | |
869 public String toString(){ | |
870 return getDescriptor(); | |
871 } | |
872 } |