diff options
Diffstat (limited to 'samples/Java/clojure-type.java')
| -rw-r--r-- | samples/Java/clojure-type.java | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/samples/Java/clojure-type.java b/samples/Java/clojure-type.java new file mode 100644 index 0000000..4cde14a --- /dev/null +++ b/samples/Java/clojure-type.java @@ -0,0 +1,872 @@ +/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package clojure.asm;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * A Java type. This class can be used to make it easier to manipulate type and
+ * method descriptors.
+ *
+ * @author Eric Bruneton
+ * @author Chris Nokleberg
+ */
+public class Type{
+
+/**
+ * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
+ */
+public final static int VOID = 0;
+
+/**
+ * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
+ */
+public final static int BOOLEAN = 1;
+
+/**
+ * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
+ */
+public final static int CHAR = 2;
+
+/**
+ * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
+ */
+public final static int BYTE = 3;
+
+/**
+ * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
+ */
+public final static int SHORT = 4;
+
+/**
+ * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
+ */
+public final static int INT = 5;
+
+/**
+ * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
+ */
+public final static int FLOAT = 6;
+
+/**
+ * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
+ */
+public final static int LONG = 7;
+
+/**
+ * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
+ */
+public final static int DOUBLE = 8;
+
+/**
+ * The sort of array reference types. See {@link #getSort getSort}.
+ */
+public final static int ARRAY = 9;
+
+/**
+ * The sort of object reference type. See {@link #getSort getSort}.
+ */
+public final static int OBJECT = 10;
+
+/**
+ * The <tt>void</tt> type.
+ */
+public final static Type VOID_TYPE = new Type(VOID);
+
+/**
+ * The <tt>boolean</tt> type.
+ */
+public final static Type BOOLEAN_TYPE = new Type(BOOLEAN);
+
+/**
+ * The <tt>char</tt> type.
+ */
+public final static Type CHAR_TYPE = new Type(CHAR);
+
+/**
+ * The <tt>byte</tt> type.
+ */
+public final static Type BYTE_TYPE = new Type(BYTE);
+
+/**
+ * The <tt>short</tt> type.
+ */
+public final static Type SHORT_TYPE = new Type(SHORT);
+
+/**
+ * The <tt>int</tt> type.
+ */
+public final static Type INT_TYPE = new Type(INT);
+
+/**
+ * The <tt>float</tt> type.
+ */
+public final static Type FLOAT_TYPE = new Type(FLOAT);
+
+/**
+ * The <tt>long</tt> type.
+ */
+public final static Type LONG_TYPE = new Type(LONG);
+
+/**
+ * The <tt>double</tt> type.
+ */
+public final static Type DOUBLE_TYPE = new Type(DOUBLE);
+
+// ------------------------------------------------------------------------
+// Fields
+// ------------------------------------------------------------------------
+
+/**
+ * The sort of this Java type.
+ */
+private final int sort;
+
+/**
+ * A buffer containing the descriptor of this Java type. This field is only
+ * used for reference types.
+ */
+private char[] buf;
+
+/**
+ * The offset of the descriptor of this Java type in {@link #buf buf}. This
+ * field is only used for reference types.
+ */
+private int off;
+
+/**
+ * The length of the descriptor of this Java type.
+ */
+private int len;
+
+// ------------------------------------------------------------------------
+// Constructors
+// ------------------------------------------------------------------------
+
+/**
+ * Constructs a primitive type.
+ *
+ * @param sort the sort of the primitive type to be constructed.
+ */
+private Type(final int sort){
+ this.sort = sort;
+ this.len = 1;
+}
+
+/**
+ * Constructs a reference type.
+ *
+ * @param sort the sort of the reference type to be constructed.
+ * @param buf a buffer containing the descriptor of the previous type.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @param len the length of this descriptor.
+ */
+private Type(final int sort, final char[] buf, final int off, final int len){
+ this.sort = sort;
+ this.buf = buf;
+ this.off = off;
+ this.len = len;
+}
+
+/**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param typeDescriptor a type descriptor.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+public static Type getType(final String typeDescriptor){
+ return getType(typeDescriptor.toCharArray(), 0);
+}
+
+/**
+ * Returns the Java type corresponding to the given class.
+ *
+ * @param c a class.
+ * @return the Java type corresponding to the given class.
+ */
+public static Type getType(final Class c){
+ if(c.isPrimitive())
+ {
+ if(c == Integer.TYPE)
+ {
+ return INT_TYPE;
+ }
+ else if(c == Void.TYPE)
+ {
+ return VOID_TYPE;
+ }
+ else if(c == Boolean.TYPE)
+ {
+ return BOOLEAN_TYPE;
+ }
+ else if(c == Byte.TYPE)
+ {
+ return BYTE_TYPE;
+ }
+ else if(c == Character.TYPE)
+ {
+ return CHAR_TYPE;
+ }
+ else if(c == Short.TYPE)
+ {
+ return SHORT_TYPE;
+ }
+ else if(c == Double.TYPE)
+ {
+ return DOUBLE_TYPE;
+ }
+ else if(c == Float.TYPE)
+ {
+ return FLOAT_TYPE;
+ }
+ else /* if (c == Long.TYPE) */
+ {
+ return LONG_TYPE;
+ }
+ }
+ else
+ {
+ return getType(getDescriptor(c));
+ }
+}
+
+/**
+ * Returns the {@link Type#OBJECT} type for the given internal class name.
+ * This is a shortcut method for <code>Type.getType("L"+name+";")</code>.
+ * <i>Note that opposed to {@link Type#getType(String)}, this method takes
+ * internal class names and not class descriptor.</i>
+ *
+ * @param name an internal class name.
+ * @return the the {@link Type#OBJECT} type for the given class name.
+ */
+public static Type getObjectType(String name){
+ int l = name.length();
+ char[] buf = new char[l + 2];
+ buf[0] = 'L';
+ buf[l + 1] = ';';
+ name.getChars(0, l, buf, 1);
+ return new Type(OBJECT, buf, 0, l + 2);
+}
+
+/**
+ * Returns the Java types corresponding to the argument types of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java types corresponding to the argument types of the given
+ * method descriptor.
+ */
+public static Type[] getArgumentTypes(final String methodDescriptor){
+ char[] buf = methodDescriptor.toCharArray();
+ int off = 1;
+ int size = 0;
+ while(true)
+ {
+ char car = buf[off++];
+ if(car == ')')
+ {
+ break;
+ }
+ else if(car == 'L')
+ {
+ while(buf[off++] != ';')
+ {
+ }
+ ++size;
+ }
+ else if(car != '[')
+ {
+ ++size;
+ }
+ }
+ Type[] args = new Type[size];
+ off = 1;
+ size = 0;
+ while(buf[off] != ')')
+ {
+ args[size] = getType(buf, off);
+ off += args[size].len;
+ size += 1;
+ }
+ return args;
+}
+
+/**
+ * Returns the Java types corresponding to the argument types of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java types corresponding to the argument types of the given
+ * method.
+ */
+public static Type[] getArgumentTypes(final Method method){
+ Class[] classes = method.getParameterTypes();
+ Type[] types = new Type[classes.length];
+ for(int i = classes.length - 1; i >= 0; --i)
+ {
+ types[i] = getType(classes[i]);
+ }
+ return types;
+}
+
+/**
+ * Returns the Java type corresponding to the return type of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java type corresponding to the return type of the given
+ * method descriptor.
+ */
+public static Type getReturnType(final String methodDescriptor){
+ char[] buf = methodDescriptor.toCharArray();
+ return getType(buf, methodDescriptor.indexOf(')') + 1);
+}
+
+/**
+ * Returns the Java type corresponding to the return type of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java type corresponding to the return type of the given
+ * method.
+ */
+public static Type getReturnType(final Method method){
+ return getType(method.getReturnType());
+}
+
+/**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param buf a buffer containing a type descriptor.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+private static Type getType(final char[] buf, final int off){
+ int len;
+ switch(buf[off])
+ {
+ case'V':
+ return VOID_TYPE;
+ case'Z':
+ return BOOLEAN_TYPE;
+ case'C':
+ return CHAR_TYPE;
+ case'B':
+ return BYTE_TYPE;
+ case'S':
+ return SHORT_TYPE;
+ case'I':
+ return INT_TYPE;
+ case'F':
+ return FLOAT_TYPE;
+ case'J':
+ return LONG_TYPE;
+ case'D':
+ return DOUBLE_TYPE;
+ case'[':
+ len = 1;
+ while(buf[off + len] == '[')
+ {
+ ++len;
+ }
+ if(buf[off + len] == 'L')
+ {
+ ++len;
+ while(buf[off + len] != ';')
+ {
+ ++len;
+ }
+ }
+ return new Type(ARRAY, buf, off, len + 1);
+ // case 'L':
+ default:
+ len = 1;
+ while(buf[off + len] != ';')
+ {
+ ++len;
+ }
+ return new Type(OBJECT, buf, off, len + 1);
+ }
+}
+
+// ------------------------------------------------------------------------
+// Accessors
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the sort of this Java type.
+ *
+ * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
+ * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
+ * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
+ * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or
+ * {@link #OBJECT OBJECT}.
+ */
+public int getSort(){
+ return sort;
+}
+
+/**
+ * Returns the number of dimensions of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return the number of dimensions of this array type.
+ */
+public int getDimensions(){
+ int i = 1;
+ while(buf[off + i] == '[')
+ {
+ ++i;
+ }
+ return i;
+}
+
+/**
+ * Returns the type of the elements of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return Returns the type of the elements of this array type.
+ */
+public Type getElementType(){
+ return getType(buf, off + getDimensions());
+}
+
+/**
+ * Returns the name of the class corresponding to this type.
+ *
+ * @return the fully qualified name of the class corresponding to this type.
+ */
+public String getClassName(){
+ switch(sort)
+ {
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuffer b = new StringBuffer(getElementType().getClassName());
+ for(int i = getDimensions(); i > 0; --i)
+ {
+ b.append("[]");
+ }
+ return b.toString();
+ // case OBJECT:
+ default:
+ return new String(buf, off + 1, len - 2).replace('/', '.');
+ }
+}
+
+/**
+ * Returns the internal name of the class corresponding to this object type.
+ * The internal name of a class is its fully qualified name, where '.' are
+ * replaced by '/'. This method should only be used for an object type.
+ *
+ * @return the internal name of the class corresponding to this object type.
+ */
+public String getInternalName(){
+ return new String(buf, off + 1, len - 2);
+}
+
+// ------------------------------------------------------------------------
+// Conversion to type descriptors
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the descriptor corresponding to this Java type.
+ *
+ * @return the descriptor corresponding to this Java type.
+ */
+public String getDescriptor(){
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf);
+ return buf.toString();
+}
+
+/**
+ * Returns the descriptor corresponding to the given argument and return
+ * types.
+ *
+ * @param returnType the return type of the method.
+ * @param argumentTypes the argument types of the method.
+ * @return the descriptor corresponding to the given argument and return
+ * types.
+ */
+public static String getMethodDescriptor(
+ final Type returnType,
+ final Type[] argumentTypes){
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for(int i = 0; i < argumentTypes.length; ++i)
+ {
+ argumentTypes[i].getDescriptor(buf);
+ }
+ buf.append(')');
+ returnType.getDescriptor(buf);
+ return buf.toString();
+}
+
+/**
+ * Appends the descriptor corresponding to this Java type to the given
+ * string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ */
+private void getDescriptor(final StringBuffer buf){
+ switch(sort)
+ {
+ case VOID:
+ buf.append('V');
+ return;
+ case BOOLEAN:
+ buf.append('Z');
+ return;
+ case CHAR:
+ buf.append('C');
+ return;
+ case BYTE:
+ buf.append('B');
+ return;
+ case SHORT:
+ buf.append('S');
+ return;
+ case INT:
+ buf.append('I');
+ return;
+ case FLOAT:
+ buf.append('F');
+ return;
+ case LONG:
+ buf.append('J');
+ return;
+ case DOUBLE:
+ buf.append('D');
+ return;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ buf.append(this.buf, off, len);
+ }
+}
+
+// ------------------------------------------------------------------------
+// Direct conversion from classes to type descriptors,
+// without intermediate Type objects
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the internal name of the given class. The internal name of a
+ * class is its fully qualified name, where '.' are replaced by '/'.
+ *
+ * @param c an object class.
+ * @return the internal name of the given class.
+ */
+public static String getInternalName(final Class c){
+ return c.getName().replace('.', '/');
+}
+
+/**
+ * Returns the descriptor corresponding to the given Java type.
+ *
+ * @param c an object class, a primitive class or an array class.
+ * @return the descriptor corresponding to the given class.
+ */
+public static String getDescriptor(final Class c){
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf, c);
+ return buf.toString();
+}
+
+/**
+ * Returns the descriptor corresponding to the given constructor.
+ *
+ * @param c a {@link Constructor Constructor} object.
+ * @return the descriptor of the given constructor.
+ */
+public static String getConstructorDescriptor(final Constructor c){
+ Class[] parameters = c.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for(int i = 0; i < parameters.length; ++i)
+ {
+ getDescriptor(buf, parameters[i]);
+ }
+ return buf.append(")V").toString();
+}
+
+/**
+ * Returns the descriptor corresponding to the given method.
+ *
+ * @param m a {@link Method Method} object.
+ * @return the descriptor of the given method.
+ */
+public static String getMethodDescriptor(final Method m){
+ Class[] parameters = m.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for(int i = 0; i < parameters.length; ++i)
+ {
+ getDescriptor(buf, parameters[i]);
+ }
+ buf.append(')');
+ getDescriptor(buf, m.getReturnType());
+ return buf.toString();
+}
+
+/**
+ * Appends the descriptor of the given class to the given string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ * @param c the class whose descriptor must be computed.
+ */
+private static void getDescriptor(final StringBuffer buf, final Class c){
+ Class d = c;
+ while(true)
+ {
+ if(d.isPrimitive())
+ {
+ char car;
+ if(d == Integer.TYPE)
+ {
+ car = 'I';
+ }
+ else if(d == Void.TYPE)
+ {
+ car = 'V';
+ }
+ else if(d == Boolean.TYPE)
+ {
+ car = 'Z';
+ }
+ else if(d == Byte.TYPE)
+ {
+ car = 'B';
+ }
+ else if(d == Character.TYPE)
+ {
+ car = 'C';
+ }
+ else if(d == Short.TYPE)
+ {
+ car = 'S';
+ }
+ else if(d == Double.TYPE)
+ {
+ car = 'D';
+ }
+ else if(d == Float.TYPE)
+ {
+ car = 'F';
+ }
+ else /* if (d == Long.TYPE) */
+ {
+ car = 'J';
+ }
+ buf.append(car);
+ return;
+ }
+ else if(d.isArray())
+ {
+ buf.append('[');
+ d = d.getComponentType();
+ }
+ else
+ {
+ buf.append('L');
+ String name = d.getName();
+ int len = name.length();
+ for(int i = 0; i < len; ++i)
+ {
+ char car = name.charAt(i);
+ buf.append(car == '.' ? '/' : car);
+ }
+ buf.append(';');
+ return;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+// Corresponding size and opcodes
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the size of values of this type.
+ *
+ * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
+ * <tt>double</tt>, and 1 otherwise.
+ */
+public int getSize(){
+ return sort == LONG || sort == DOUBLE ? 2 : 1;
+}
+
+/**
+ * Returns a JVM instruction opcode adapted to this Java type.
+ *
+ * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
+ * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
+ * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+ * @return an opcode that is similar to the given opcode, but adapted to
+ * this Java type. For example, if this type is <tt>float</tt> and
+ * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
+ */
+public int getOpcode(final int opcode){
+ if(opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE)
+ {
+ switch(sort)
+ {
+ case BOOLEAN:
+ case BYTE:
+ return opcode + 5;
+ case CHAR:
+ return opcode + 6;
+ case SHORT:
+ return opcode + 7;
+ case INT:
+ return opcode;
+ case FLOAT:
+ return opcode + 2;
+ case LONG:
+ return opcode + 1;
+ case DOUBLE:
+ return opcode + 3;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ return opcode + 4;
+ }
+ }
+ else
+ {
+ switch(sort)
+ {
+ case VOID:
+ return opcode + 5;
+ case BOOLEAN:
+ case CHAR:
+ case BYTE:
+ case SHORT:
+ case INT:
+ return opcode;
+ case FLOAT:
+ return opcode + 2;
+ case LONG:
+ return opcode + 1;
+ case DOUBLE:
+ return opcode + 3;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ return opcode + 4;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+// Equals, hashCode and toString
+// ------------------------------------------------------------------------
+
+/**
+ * Tests if the given object is equal to this type.
+ *
+ * @param o the object to be compared to this type.
+ * @return <tt>true</tt> if the given object is equal to this type.
+ */
+public boolean equals(final Object o){
+ if(this == o)
+ {
+ return true;
+ }
+ if(!(o instanceof Type))
+ {
+ return false;
+ }
+ Type t = (Type) o;
+ if(sort != t.sort)
+ {
+ return false;
+ }
+ if(sort == Type.OBJECT || sort == Type.ARRAY)
+ {
+ if(len != t.len)
+ {
+ return false;
+ }
+ for(int i = off, j = t.off, end = i + len; i < end; i++, j++)
+ {
+ if(buf[i] != t.buf[j])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ * Returns a hash code value for this type.
+ *
+ * @return a hash code value for this type.
+ */
+public int hashCode(){
+ int hc = 13 * sort;
+ if(sort == Type.OBJECT || sort == Type.ARRAY)
+ {
+ for(int i = off, end = i + len; i < end; i++)
+ {
+ hc = 17 * (hc + buf[i]);
+ }
+ }
+ return hc;
+}
+
+/**
+ * Returns a string representation of this type.
+ *
+ * @return the descriptor of this type.
+ */
+public String toString(){
+ return getDescriptor();
+}
+}
|
