From 7b6caa0f6c7603aabb5e6ed657e24aaddbeafc78 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 23 Jul 2012 15:52:49 -0500 Subject: Rename samples subdirectories --- samples/Java/clojure-type.java | 872 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) create mode 100644 samples/Java/clojure-type.java (limited to 'samples/Java/clojure-type.java') 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 void type. See {@link #getSort getSort}. + */ +public final static int VOID = 0; + +/** + * The sort of the boolean type. See {@link #getSort getSort}. + */ +public final static int BOOLEAN = 1; + +/** + * The sort of the char type. See {@link #getSort getSort}. + */ +public final static int CHAR = 2; + +/** + * The sort of the byte type. See {@link #getSort getSort}. + */ +public final static int BYTE = 3; + +/** + * The sort of the short type. See {@link #getSort getSort}. + */ +public final static int SHORT = 4; + +/** + * The sort of the int type. See {@link #getSort getSort}. + */ +public final static int INT = 5; + +/** + * The sort of the float type. See {@link #getSort getSort}. + */ +public final static int FLOAT = 6; + +/** + * The sort of the long type. See {@link #getSort getSort}. + */ +public final static int LONG = 7; + +/** + * The sort of the double 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 void type. + */ +public final static Type VOID_TYPE = new Type(VOID); + +/** + * The boolean type. + */ +public final static Type BOOLEAN_TYPE = new Type(BOOLEAN); + +/** + * The char type. + */ +public final static Type CHAR_TYPE = new Type(CHAR); + +/** + * The byte type. + */ +public final static Type BYTE_TYPE = new Type(BYTE); + +/** + * The short type. + */ +public final static Type SHORT_TYPE = new Type(SHORT); + +/** + * The int type. + */ +public final static Type INT_TYPE = new Type(INT); + +/** + * The float type. + */ +public final static Type FLOAT_TYPE = new Type(FLOAT); + +/** + * The long type. + */ +public final static Type LONG_TYPE = new Type(LONG); + +/** + * The double 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 Type.getType("L"+name+";"). + * Note that opposed to {@link Type#getType(String)}, this method takes + * internal class names and not class descriptor. + * + * @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 long and + * double, 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 float and + * opcode 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 true 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(); +} +} -- cgit v1.2.3