From: <cg...@us...> - 2008-01-01 01:43:49
|
Revision: 3925 http://jython.svn.sourceforge.net/jython/?rev=3925&view=rev Author: cgroves Date: 2007-12-31 17:43:48 -0800 (Mon, 31 Dec 2007) Log Message: ----------- Fields to the top per the new coding standards, and add a few convenience methods on Exposer to make method calling a little less verbose Modified Paths: -------------- trunk/jython/src/org/python/expose/ExposeAsSuperclass.java trunk/jython/src/org/python/expose/ExposedGet.java trunk/jython/src/org/python/expose/ExposedMethod.java trunk/jython/src/org/python/expose/ExposedNew.java trunk/jython/src/org/python/expose/ExposedType.java trunk/jython/src/org/python/expose/MethodType.java trunk/jython/src/org/python/expose/generate/DescriptorExposer.java trunk/jython/src/org/python/expose/generate/DescriptorVisitor.java trunk/jython/src/org/python/expose/generate/ExposeTask.java trunk/jython/src/org/python/expose/generate/ExposedFieldFinder.java trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java trunk/jython/src/org/python/expose/generate/ExposedTypeProcessor.java trunk/jython/src/org/python/expose/generate/ExposedTypeVisitor.java trunk/jython/src/org/python/expose/generate/Exposer.java trunk/jython/src/org/python/expose/generate/InvalidExposingException.java trunk/jython/src/org/python/expose/generate/MethodExposer.java trunk/jython/src/org/python/expose/generate/NewExposer.java trunk/jython/src/org/python/expose/generate/OverridableNewExposer.java trunk/jython/src/org/python/expose/generate/RestrictiveAnnotationVisitor.java trunk/jython/src/org/python/expose/generate/TypeExposer.java Modified: trunk/jython/src/org/python/expose/ExposeAsSuperclass.java =================================================================== --- trunk/jython/src/org/python/expose/ExposeAsSuperclass.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/ExposeAsSuperclass.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -1,7 +1,7 @@ package org.python.expose; /** - * Marker interface that indicates this class and all of its subclasses should - * be exposed to Python with the same Python type as its superclass. + * Marker interface that indicates this class and all of its subclasses should be exposed to Python + * with the same Python type as its superclass. */ public interface ExposeAsSuperclass {} Modified: trunk/jython/src/org/python/expose/ExposedGet.java =================================================================== --- trunk/jython/src/org/python/expose/ExposedGet.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/ExposedGet.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -6,7 +6,7 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD,ElementType.FIELD}) +@Target( {ElementType.METHOD, ElementType.FIELD}) public @interface ExposedGet { String name() default ""; Modified: trunk/jython/src/org/python/expose/ExposedMethod.java =================================================================== --- trunk/jython/src/org/python/expose/ExposedMethod.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/ExposedMethod.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -14,20 +14,17 @@ public @interface ExposedMethod { /** - * @return the names to expose this method as. Defaults to just actual name - * of the method. + * @return the names to expose this method as. Defaults to just actual name of the method. */ String[] names() default {}; /** - * @return default arguments. Starts at the number of arguments - - * defaults.length. + * @return default arguments. Starts at the number of arguments - defaults.length. */ String[] defaults() default {}; /** - * @return - how to expose this method. See {@link MethodType} for the - * options. + * @return - how to expose this method. See {@link MethodType} for the options. */ MethodType type() default MethodType.DEFAULT; } Modified: trunk/jython/src/org/python/expose/ExposedNew.java =================================================================== --- trunk/jython/src/org/python/expose/ExposedNew.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/ExposedNew.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -7,28 +7,25 @@ import org.python.core.PyInteger; - /** - * Can appear on two forms of methods to indicate a method should be part of the - * __new__ object creation. Can only appear once per exposed type. + * Can appear on two forms of methods to indicate a method should be part of the __new__ object + * creation. Can only appear once per exposed type. * * In the first form, the method must be static and take the arguments * <code>PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords</code>. - * In this case, the method has full responsibility for creating and initting - * the object and will be invoked for every subtype of this exposed type. - * Essentially its for object instantation that must be called for every - * instance of that object. See {@link PyInteger#int_new} for an example of this + * In this case, the method has full responsibility for creating and initting the object and will be + * invoked for every subtype of this exposed type. Essentially its for object instantation that must + * be called for every instance of that object. See {@link PyInteger#int_new} for an example of this * type of ExposedNew. * - * In the second form, the method must be an instance method that takes the - * standard Jython call arguments, - * <code>PyObject[] args, String[] keywords</code>. In this case, the basic - * new functionality is handled by PyOverridableNew and the method with - * ExposedNew is called as __init__ as part of that process. This allows - * subtypes to completely redefine new and create objects however they like. + * In the second form, the method must be an instance method that takes the standard Jython call + * arguments, <code>PyObject[] args, String[] keywords</code>. In this case, the basic new + * functionality is handled by PyOverridableNew and the method with ExposedNew is called as __init__ + * as part of that process. This allows subtypes to completely redefine new and create objects + * however they like. * - */ + */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExposedNew {} Modified: trunk/jython/src/org/python/expose/ExposedType.java =================================================================== --- trunk/jython/src/org/python/expose/ExposedType.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/ExposedType.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -10,23 +10,20 @@ import org.python.core.PyType; /** - * Indicates a given class should be made visible to Python code as a builtin - * type. + * Indicates a given class should be made visible to Python code as a builtin type. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ExposedType { /** - * @return the name to expose this item as. Defaults to the actual name of - * the class. + * @return the name to expose this item as. Defaults to the actual name of the class. */ String name() default ""; /** - * @return the base type of this type. Must be another class anotated with - * ExposedType. If unspecified, the base is set to object, or - * PyObject.class. + * @return the base type of this type. Must be another class anotated with ExposedType. If + * unspecified, the base is set to object, or PyObject.class. */ Class base() default Object.class; } Modified: trunk/jython/src/org/python/expose/MethodType.java =================================================================== --- trunk/jython/src/org/python/expose/MethodType.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/MethodType.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -2,9 +2,9 @@ public enum MethodType { /** Return this method's value unmolested. */ - DEFAULT, - /** If a method returns null, raise a NotImplemented.*/ - BINARY, - /** Only for __cmp__ methods. If it returns -2, raise a TypeError */ + DEFAULT, + /** If a method returns null, raise a NotImplemented. */ + BINARY, + /** Only for __cmp__ methods. If it returns -2, raise a TypeError */ CMP } Modified: trunk/jython/src/org/python/expose/generate/DescriptorExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/DescriptorExposer.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/DescriptorExposer.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -9,17 +9,38 @@ import org.python.expose.ExposedGet; /** - * Generates a class to expose a descriptor on Python type. One of - * addMethodGetter or addFieldGetter must be called, and possibly one of - * addMethodSetter and addFieldSetter if this is a settable descriptor. If this - * is a deletable descriptor, addMethodDeleter may be called. There is no + * Generates a class to expose a descriptor on Python type. One of addMethodGetter or addFieldGetter + * must be called, and possibly one of addMethodSetter and addFieldSetter if this is a settable + * descriptor. If this is a deletable descriptor, addMethodDeleter may be called. There is no * addFieldDeleter since there's no defined behavior to 'delete' a field. */ public class DescriptorExposer extends Exposer { + private Type onType, ofType; + + private String name; + + private String getterMethodName, getterFieldName, setterMethodName, setterFieldName, + deleterMethodName; + + private static final Set<Type> PRIMITIVES = Collections.unmodifiableSet(new HashSet<Type>() { + + { + add(Type.BOOLEAN_TYPE); + add(Type.BYTE_TYPE); + add(Type.CHAR_TYPE); + add(Type.DOUBLE_TYPE); + add(Type.FLOAT_TYPE); + add(Type.INT_TYPE); + add(Type.LONG_TYPE); + add(Type.SHORT_TYPE); + add(Type.VOID_TYPE); + } + }); + /** - * Creates an exposer that will work on type and have <code>descrName</code> - * as its name in the type's dict. + * Creates an exposer that will work on type and have <code>descrName</code> as its name in + * the type's dict. */ public DescriptorExposer(Type onType, String descrName) { super(PyDataDescr.class, onType.getClassName() + "$" + descrName + "_descriptor"); @@ -63,7 +84,7 @@ } if(ofType == null) { ofType = type; - } else if(!ofType.equals(type)) { + } else if(!ofType.equals(type)) { error("Types of the getter and setter must agree"); } } @@ -139,12 +160,8 @@ startMethod("invokeGet", OBJECT, PYOBJ); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, onType.getInternalName()); - mv.visitMethodInsn(INVOKEVIRTUAL, - onType.getInternalName(), - getterMethodName, - methodDesc(ofType)); - mv.visitInsn(ARETURN); - endMethod(); + call(onType, getterMethodName, ofType); + endMethod(ARETURN); } private void generateFieldGetter() { @@ -155,8 +172,7 @@ onType.getInternalName(), getterFieldName, ofType.getDescriptor()); - mv.visitInsn(ARETURN); - endMethod(); + endMethod(ARETURN); } private void generateMethodSetter() { @@ -165,12 +181,8 @@ mv.visitTypeInsn(CHECKCAST, onType.getInternalName()); mv.visitVarInsn(ALOAD, 2); mv.visitTypeInsn(CHECKCAST, ofType.getInternalName()); - mv.visitMethodInsn(INVOKEVIRTUAL, - onType.getInternalName(), - setterMethodName, - methodDesc(VOID, ofType)); - mv.visitInsn(RETURN); - endMethod(); + call(onType, setterMethodName, VOID, ofType); + endMethod(RETURN); } private void generateFieldSetter() { @@ -183,53 +195,25 @@ onType.getInternalName(), setterFieldName, ofType.getDescriptor()); - mv.visitInsn(RETURN); - endMethod(); + endMethod(RETURN); } private void generateMethodDeleter() { startMethod("invokeDelete", VOID, PYOBJ); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, onType.getInternalName()); - mv.visitMethodInsn(INVOKEVIRTUAL, - onType.getInternalName(), - deleterMethodName, - methodDesc(VOID)); - mv.visitInsn(RETURN); - endMethod(); + call(onType, deleterMethodName, VOID); + endMethod(RETURN); } private void generateDoesntImplement(String setOrDelete) { startMethod("implementsDescr" + setOrDelete, BOOLEAN); mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - endMethod(); + endMethod(IRETURN); } private void error(String reason) { throw new InvalidExposingException(reason + "[class=" + onType.getClassName() + ", name=" + name + "]"); } - - private Type onType, ofType; - - private String name; - - private String getterMethodName, getterFieldName, setterMethodName, setterFieldName, - deleterMethodName; - - private static final Set<Type> PRIMITIVES = Collections.unmodifiableSet(new HashSet<Type>() { - - { - add(Type.BOOLEAN_TYPE); - add(Type.BYTE_TYPE); - add(Type.CHAR_TYPE); - add(Type.DOUBLE_TYPE); - add(Type.FLOAT_TYPE); - add(Type.INT_TYPE); - add(Type.LONG_TYPE); - add(Type.SHORT_TYPE); - add(Type.VOID_TYPE); - } - }); } Modified: trunk/jython/src/org/python/expose/generate/DescriptorVisitor.java =================================================================== --- trunk/jython/src/org/python/expose/generate/DescriptorVisitor.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/DescriptorVisitor.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -2,6 +2,8 @@ abstract class DescriptorVisitor extends RestrictiveAnnotationVisitor { + private String val; + DescriptorVisitor(String defaultName) { val = defaultName; } @@ -21,6 +23,4 @@ } public abstract void handleResult(String name); - - private String val; } \ No newline at end of file Modified: trunk/jython/src/org/python/expose/generate/ExposeTask.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposeTask.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/ExposeTask.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -16,6 +16,12 @@ public class ExposeTask extends MatchingTask { + private Path src; + + private File destDir; + + private Set<File> toExpose = new HashSet<File>(); + /** * Set the source directories to find the class files to be exposed. */ @@ -35,8 +41,7 @@ } /** - * Set the destination directory into which the Java source files should be - * compiled. + * Set the destination directory into which the Java source files should be compiled. * * @param destDir * the destination director @@ -46,8 +51,7 @@ } /** - * Gets the destination directory into which the java source files should be - * compiled. + * Gets the destination directory into which the java source files should be compiled. * * @return the destination directory */ @@ -80,7 +84,7 @@ etp = new ExposedTypeProcessor(new FileInputStream(f)); } catch(IOException e) { throw new BuildException("Unable to read '" + f + "' to expose it", e); - } catch(InvalidExposingException iee){ + } catch(InvalidExposingException iee) { throw new BuildException(iee.getMessage()); } for(MethodExposer exposer : etp.getMethodExposers()) { @@ -134,8 +138,7 @@ } /** - * Check that all required attributes have been set and nothing silly has - * been entered. + * Check that all required attributes have been set and nothing silly has been entered. */ protected void checkParameters() throws BuildException { if(src == null || src.size() == 0) { @@ -146,10 +149,4 @@ + "or is not a directory", getLocation()); } } - - private Path src; - - private File destDir; - - private Set<File> toExpose = new HashSet<File>(); } Modified: trunk/jython/src/org/python/expose/generate/ExposedFieldFinder.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposedFieldFinder.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/ExposedFieldFinder.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -6,6 +6,10 @@ public abstract class ExposedFieldFinder implements FieldVisitor, PyTypes { + private String fieldName; + + private FieldVisitor delegate; + public ExposedFieldFinder(String name, FieldVisitor delegate) { fieldName = name; this.delegate = delegate; @@ -44,8 +48,4 @@ public void visitEnd() { delegate.visitEnd(); } - - private String fieldName; - - private FieldVisitor delegate; } Modified: trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/ExposedMethodFinder.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -11,13 +11,24 @@ import org.python.expose.MethodType; /** - * Visits a method passing all calls through to its delegate. If an ExposedNew - * or ExposedMethod annotation is visited, calls handleResult with the exposer - * constructed with that annotation. Only one of the handleResult methods will - * be called, if any. + * Visits a method passing all calls through to its delegate. If an ExposedNew or ExposedMethod + * annotation is visited, calls handleResult with the exposer constructed with that annotation. Only + * one of the handleResult methods will be called, if any. */ public abstract class ExposedMethodFinder extends MethodAdapter implements PyTypes, Opcodes { + private Exposer newExp; + + private ExposedMethodVisitor methVisitor; + + private Type onType; + + private String methodDesc, typeName, methodName; + + private String[] exceptions; + + private int access; + public ExposedMethodFinder(String typeName, Type onType, int access, @@ -59,11 +70,12 @@ newExp = new NewExposer(onType, access, methodName, methodDesc, exceptions); } else { newExp = new OverridableNewExposer(onType, - Type.getType("L" + onType.getInternalName() + "Derived;"), - access, - methodName, - methodDesc, - exceptions); + Type.getType("L" + onType.getInternalName() + + "Derived;"), + access, + methodName, + methodDesc, + exceptions); } } else if(desc.equals(EXPOSED_METHOD.getDescriptor())) { methVisitor = new ExposedMethodVisitor(); @@ -165,22 +177,10 @@ methVisitor.names, methVisitor.defaults, methVisitor.type)); - } + } if(newExp != null) { handleNewExposer(newExp); } super.visitEnd(); } - - private Exposer newExp; - - ExposedMethodVisitor methVisitor; - - private Type onType; - - private String methodDesc, typeName, methodName; - - private String[] exceptions; - - private int access; } Modified: trunk/jython/src/org/python/expose/generate/ExposedTypeProcessor.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposedTypeProcessor.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/ExposedTypeProcessor.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -21,18 +21,31 @@ import org.python.expose.ExposedType; /** - * Processes the bytecode of a Java class that has the {@link ExposedType} - * annotation on it and generates new bytecode for it containing the inner - * classes Jython needs to expose it as a type. + * Processes the bytecode of a Java class that has the {@link ExposedType} annotation on it and + * generates new bytecode for it containing the inner classes Jython needs to expose it as a type. */ public class ExposedTypeProcessor implements Opcodes, PyTypes { + private List<MethodExposer> methodExposers = new ArrayList<MethodExposer>(); + + private Map<String, DescriptorExposer> descExposers = new HashMap<String, DescriptorExposer>(); + + private Exposer newExposer; + + private TypeExposer typeExposer; + + private ClassWriter cw; + + private String typeName; + + private Type onType; + /** * @param in - * an InputStream to bytecode of an ExposedType * @throws InvalidExposingException - - * if the class doesn't have an annotation, or if one of the - * method annotations is malformed + * if the class doesn't have an annotation, or if one of the method annotations is + * malformed */ public ExposedTypeProcessor(InputStream in) throws IOException { ClassReader cr = new ClassReader(in); @@ -59,8 +72,7 @@ } /** - * @return The Exposer for __new__ for this type. Can be null if the type - * isn't instantiable. + * @return The Exposer for __new__ for this type. Can be null if the type isn't instantiable. */ public Exposer getNewExposer() { return newExposer; @@ -91,26 +103,15 @@ return descExposers.get(descName); } - private List<MethodExposer> methodExposers = new ArrayList<MethodExposer>(); - - private Map<String, DescriptorExposer> descExposers = new HashMap<String, DescriptorExposer>(); - - private Exposer newExposer; - - private TypeExposer typeExposer; - - private ClassWriter cw; - - private String typeName; - - private Type onType; - /** - * The actual visitor that runs over the bytecode and figures out what to - * expose. + * The actual visitor that runs over the bytecode and figures out what to expose. */ private final class TypeProcessor extends ClassAdapter { + private Type baseType = OBJECT; + + private boolean generatedStaticBlock; + private TypeProcessor(ClassVisitor cv) { super(cv); } @@ -144,8 +145,8 @@ } return super.visitAnnotation(desc, visible); } - - private void throwInvalid(String msg){ + + private void throwInvalid(String msg) { throw new InvalidExposingException(msg + "[class=" + onType.getClassName() + "]"); } @@ -251,7 +252,7 @@ @Override public void handleNewExposer(Exposer exposer) { - if(newExposer != null){ + if(newExposer != null) { throwInvalid("Only one @ExposedNew is allowed per class"); } newExposer = exposer; @@ -299,9 +300,5 @@ } }; } - - private Type baseType = OBJECT; - - private boolean generatedStaticBlock; } } Modified: trunk/jython/src/org/python/expose/generate/ExposedTypeVisitor.java =================================================================== --- trunk/jython/src/org/python/expose/generate/ExposedTypeVisitor.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/ExposedTypeVisitor.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -3,11 +3,16 @@ import org.objectweb.asm.Type; /** - * Visits an ExposedType annotation and passes the values it gathers to - * handleResult. + * Visits an ExposedType annotation and passes the values it gathers to handleResult. */ public abstract class ExposedTypeVisitor extends RestrictiveAnnotationVisitor { + private String typeName; + + private Type onType; + + private Type base = Type.getType(Object.class); + public ExposedTypeVisitor(Type onType) { this.onType = onType; } @@ -40,10 +45,4 @@ * the name the type should be exposed as from the annotation. */ public abstract void handleResult(String name); - - private String typeName; - - private Type onType; - - private Type base = Type.getType(Object.class); } Modified: trunk/jython/src/org/python/expose/generate/Exposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/Exposer.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/Exposer.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -8,12 +8,24 @@ import org.python.core.BytecodeLoader; /** - * Base class that handles the basics of generating a single class with asm. - * Subclass to supply the actual functionality of the generated class. + * Base class that handles the basics of generating a single class with asm. Subclass to supply the + * actual functionality of the generated class. * */ public abstract class Exposer implements Opcodes, PyTypes { + /** The current method under construction or null. */ + protected MethodVisitor mv; + + /** The current class under construction. */ + protected ClassVisitor cv; + + /** The super class of the type that will be generated. */ + private Type superType; + + /** The type that will be generated. */ + protected Type thisType; + /** * @param superClass - * the super class of the generated class @@ -26,8 +38,8 @@ } /** - * Implemented by subclasses to fill in the actual implementation of the - * class. cv is set to the ClassVisitor to be used when this is called. + * Implemented by subclasses to fill in the actual implementation of the class. cv is set to the + * ClassVisitor to be used when this is called. */ protected abstract void generate(); @@ -37,9 +49,6 @@ protected Class load(BytecodeLoader.Loader l) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); generate(cw); -// ClassVisitor cv = new CheckClassAdapter(cw); -// cv = new TraceClassVisitor(cv, new PrintWriter(System.out)); -// generate(cv); return l.loadClassFromBytes(getClassName(), cw.toByteArray()); } @@ -56,9 +65,9 @@ } /** - * Will call the methods on visitor to generate this class. Only one call to - * generate may be active at a time on a single instance of Exposer. The - * ClassVisitor is assumed to have been constructed with COMPUTE_FRAMES. + * Will call the methods on visitor to generate this class. Only one call to generate may be + * active at a time on a single instance of Exposer. The ClassVisitor is assumed to have been + * constructed with COMPUTE_FRAMES. */ public void generate(ClassVisitor visitor) { assert cv == null; @@ -79,13 +88,14 @@ protected void superConstructor(Type... args) { callConstructor(superType, args); } - + class Instantiator { + public Instantiator(Type... types) { this.types = types; } - /** + /** * Push args onto the stack corresponding to the types passed to the constructor. */ public void pushArgs() { @@ -102,18 +112,17 @@ private Type[] types; } - + /** Instantiates ofType using its no-arg constructor */ protected void instantiate(Type ofType) { instantiate(ofType, new Instantiator()); } - + /** - * Instantiates ofType with its constructor that takes the types returned by - * inst.getTypes(). inst should override pushArgs to put arguments of those - * types on the stack for the call. + * Instantiates ofType with its constructor that takes the types returned by inst.getTypes(). + * inst should override pushArgs to put arguments of those types on the stack for the call. */ - protected void instantiate(Type ofType, Instantiator inst){ + protected void instantiate(Type ofType, Instantiator inst) { mv.visitTypeInsn(NEW, ofType.getInternalName()); mv.visitInsn(DUP); inst.pushArgs(); @@ -128,14 +137,30 @@ methodDesc(VOID, args)); } + /** Calls the method on onType with the given return type and argument types. */ + protected void call(Type onType, String methodName, Type returnType, Type... args) { + mv.visitMethodInsn(INVOKEVIRTUAL, + onType.getInternalName(), + methodName, + methodDesc(returnType, args)); + } + + /** Calls the static method on onType with the given return type and argument types. */ + protected void callStatic(Type onType, String methodName, Type returnType, Type... args) { + mv.visitMethodInsn(INVOKESTATIC, + onType.getInternalName(), + methodName, + methodDesc(returnType, args)); + } + /** Produces a method descriptor with ret as its return type that takes args. */ protected String methodDesc(Type ret, Type... args) { return Type.getMethodDescriptor(ret, args); } /** - * Starts building a constructor in the class. Must be followed by a call to - * endConstructor before startConstructor or startMethod may be called. + * Starts building a constructor in the class. Must be followed by a call to endConstructor + * before startConstructor or startMethod may be called. */ protected void startConstructor(Type... args) { startMethod("<init>", VOID, args); @@ -143,14 +168,12 @@ /** Closes the constructor begun by startConstructor. */ protected void endConstructor() { - mv.visitInsn(RETURN); - endMethod(); + endMethod(RETURN); } /** - * Starts building a method in the class being generated. Must be followed - * by a call to endMethod before startMethod or startConstructor may be - * called. + * Starts building a method in the class being generated. Must be followed by a call to + * endMethod before startMethod or startConstructor may be called. */ protected void startMethod(String name, Type ret, Type... args) { assert mv == null; @@ -159,27 +182,21 @@ } /** Closes the method under construction. */ - protected void endMethod() { + protected void endMethod(int returnCode) { + mv.visitInsn(returnCode); mv.visitMaxs(0, 0); mv.visitEnd(); mv = null; } - /** Loads a field on the type under construction of ofType onto the stack */ + /** Loads a field on the instance under construction of ofType onto the stack */ protected void get(String fieldName, Type ofType) { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, getInternalName(), fieldName, ofType.getDescriptor()); } - /** The current method under construction or null. */ - protected MethodVisitor mv; - - /** The current class under construction. */ - protected ClassVisitor cv; - - /** The super class of the type that will be generated. */ - private Type superType; - - /** The type that will be generated. */ - protected Type thisType; + /** Gets a static field from onType of the given type. */ + protected void getStatic(Type onType, String fieldName, Type ofType) { + mv.visitFieldInsn(GETSTATIC, onType.getInternalName(), fieldName, ofType.getDescriptor()); + } } Modified: trunk/jython/src/org/python/expose/generate/InvalidExposingException.java =================================================================== --- trunk/jython/src/org/python/expose/generate/InvalidExposingException.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/InvalidExposingException.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -1,10 +1,9 @@ package org.python.expose.generate; /** - * Indicates that something is invalid in an exposed type be it a conflict of - * names, a missing annotation or some other such problem. The message on this - * exception should be sufficient for an end user to track down where the - * problem is occuring and fix it. + * Indicates that something is invalid in an exposed type be it a conflict of names, a missing + * annotation or some other such problem. The message on this exception should be sufficient for an + * end user to track down where the problem is occuring and fix it. */ public class InvalidExposingException extends RuntimeException { Modified: trunk/jython/src/org/python/expose/generate/MethodExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/MethodExposer.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/MethodExposer.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -8,11 +8,23 @@ import org.python.expose.MethodType; /** - * Generates a class to call a given method with the {@link ExposedMethod} - * annotation as a method on a builtin Python type. + * Generates a class to call a given method with the {@link ExposedMethod} annotation as a method on + * a builtin Python type. */ public class MethodExposer extends Exposer { + private String methodName; + + protected String[] asNames, defaults; + + private String prefix; + + private Type[] params; + + private Type onType, returnType; + + protected MethodType type; + public MethodExposer(Type onType, int access, String methodName, String desc, String prefix) { this(onType, access, @@ -23,7 +35,7 @@ new String[0], MethodType.DEFAULT); } - + public MethodExposer(Type onType, int access, String methodName, @@ -36,11 +48,11 @@ onType.getClassName() + "$" + methodName + "_exposer"); this.onType = onType; this.methodName = methodName; - if((access & ACC_STATIC) != 0){ + if((access & ACC_STATIC) != 0) { throwInvalid("@ExposedMethod can't be applied to static methods"); } this.params = Type.getArgumentTypes(desc); - if(isWide(params)){ + if(isWide(params)) { if(defaults.length > 0) { throwInvalid("Can't have defaults on a method that takes PyObject[], String[]"); } @@ -63,8 +75,7 @@ } /** - * @return the names this method will be exposed as. Must be at least length - * 1. + * @return the names this method will be exposed as. Must be at least length 1. */ public String[] getNames() { if(asNames.length == 0) { @@ -122,14 +133,14 @@ private void generateBind() { startMethod("bind", BUILTIN_FUNCTION, PYOBJ); - instantiate(thisType, new Instantiator(PYOBJ, BUILTIN_INFO){ + instantiate(thisType, new Instantiator(PYOBJ, BUILTIN_INFO) { + public void pushArgs() { mv.visitVarInsn(ALOAD, 1); get("info", BUILTIN_INFO); } }); - mv.visitInsn(ARETURN); - endMethod(); + endMethod(ARETURN); } private void generateWideCall() { @@ -138,78 +149,61 @@ mv.visitTypeInsn(CHECKCAST, onType.getInternalName()); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEVIRTUAL, - onType.getInternalName(), - methodName, - methodDesc(returnType, params)); + call(onType, methodName, returnType, params); generateCallReturn(); } private void generateCallReturn() { if(returnType.equals(VOID)) { - pushNone(); + getStatic(PY, "None", PYOBJ); } else if(returnType.equals(STRING)) { - mv.visitMethodInsn(INVOKESTATIC, PY.getInternalName(), "newString", methodDesc(PYSTR, - STRING)); + callStatic(PY, "newString", PYSTR, STRING); } else if(returnType.equals(BOOLEAN)) { - mv.visitMethodInsn(INVOKESTATIC, - PY.getInternalName(), - "newBoolean", - methodDesc(PYBOOLEAN, BOOLEAN)); + callStatic(PY, "newBoolean", PYBOOLEAN, BOOLEAN); } else if(returnType.equals(INT)) { - mv.visitMethodInsn(INVOKESTATIC, - PY.getInternalName(), - "newInteger", - methodDesc(PYINTEGER, INT)); + callStatic(PY, "newInteger", PYINTEGER, INT); } - mv.visitInsn(ARETURN); - endMethod(); + endMethod(ARETURN); } - + private boolean hasDefault(int argIndex) { return defaults.length - params.length + argIndex >= 0; } - + private String getDefault(int argIndex) { return defaults[defaults.length - params.length + argIndex]; } private void generateCall(int numDefaults) { - int usedLocals = 1;// We always have one used local for this + int usedLocals = 1;// We always have one used local for 'this' Type[] args = new Type[params.length - numDefaults]; for(int i = 0; i < args.length; i++) { args[i] = PYOBJ; } startMethod("__call__", PYOBJ, args); + // Push self on the stack so we can call it get("self", PYOBJ); mv.visitTypeInsn(CHECKCAST, onType.getInternalName()); + // Push the passed in args onto the stack, and convert them if necessary for(int i = 0; i < args.length; i++) { mv.visitVarInsn(ALOAD, usedLocals++); if(params[i].equals(INT)) { - mv.visitMethodInsn(INVOKEVIRTUAL, PYOBJ.getInternalName(), "asInt", "()I"); + call(PYOBJ, "asInt", INT); } else if(params[i].equals(STRING)) { if(hasDefault(i) && getDefault(i).equals("null")) { - mv.visitMethodInsn(INVOKEVIRTUAL, - PYOBJ.getInternalName(), - "asStringOrNull", - methodDesc(STRING)); + call(PYOBJ, "asStringOrNull", STRING); } else { - mv.visitMethodInsn(INVOKEVIRTUAL, - PYOBJ.getInternalName(), - "asString", - methodDesc(STRING)); + call(PYOBJ, "asString", STRING); } } else if(params[i].equals(BOOLEAN)) { - mv.visitMethodInsn(INVOKEVIRTUAL, - PYOBJ.getInternalName(), - "__nonzero__", - methodDesc(BOOLEAN)); + call(PYOBJ, "__nonzero__", BOOLEAN); } } + // Push the defaults onto the stack for(int i = args.length; i < params.length; i++) { String def = getDefault(i); if(def.equals("Py.None")) { - pushNone(); + getStatic(PY, "None", PYOBJ); } else if(def.equals("null")) { mv.visitInsn(ACONST_NULL); } else if(params[i].equals(INT)) { @@ -218,87 +212,55 @@ // If the default isn't a valid integer, a NumberFormatException // will be raised. mv.visitLdcInsn(new Integer(def)); - } else if(params[i].equals(BOOLEAN)){ + } else if(params[i].equals(BOOLEAN)) { mv.visitLdcInsn(Boolean.valueOf(def) ? 1 : 0); } } - mv.visitMethodInsn(INVOKEVIRTUAL, - onType.getInternalName(), - methodName, - methodDesc(returnType, params)); + // Actually call the exposed method + call(onType, methodName, returnType, params); if(type == MethodType.BINARY) { + // If this is a binary method, returning null means we should throw NotImplemented mv.visitInsn(DUP); Label regularReturn = new Label(); mv.visitJumpInsn(IFNONNULL, regularReturn); - mv.visitFieldInsn(GETSTATIC, - PY.getInternalName(), - "NotImplemented", - PYOBJ.getDescriptor()); + getStatic(PY, "NotImplemented", PYOBJ); mv.visitInsn(ARETURN); mv.visitLabel(regularReturn); } else if(type == MethodType.CMP) { + // If this is a cmp method, returning -2 means the passed in object was of the wrong + // type mv.visitInsn(DUP); mv.visitIntInsn(BIPUSH, -2); Label regularReturn = new Label(); mv.visitJumpInsn(IF_ICMPNE, regularReturn); - instantiate(STRING_BUILDER, new Instantiator(STRING){ - public void pushArgs(){ - mv.visitLdcInsn(prefix + ".__cmp__(x,y) requires y to be '" + prefix + "', not a '"); + // tediously build an error message based on the type name + instantiate(STRING_BUILDER, new Instantiator(STRING) { + + public void pushArgs() { + mv.visitLdcInsn(prefix + ".__cmp__(x,y) requires y to be '" + prefix + + "', not a '"); } }); mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, - PYOBJ.getInternalName(), - "getType", - methodDesc(PYTYPE)); - mv.visitMethodInsn(INVOKEVIRTUAL, - PYTYPE.getInternalName(), - "fastGetName", - methodDesc(STRING)); - mv.visitMethodInsn(INVOKEVIRTUAL, - STRING_BUILDER.getInternalName(), - "append", - methodDesc(STRING_BUILDER, STRING)); + call(PYOBJ, "getType", PYTYPE); + call(PYTYPE, "fastGetName", STRING); + call(STRING_BUILDER, "append", STRING_BUILDER, STRING); mv.visitLdcInsn("'"); - mv.visitMethodInsn(INVOKEVIRTUAL, - STRING_BUILDER.getInternalName(), - "append", - methodDesc(STRING_BUILDER, STRING)); - mv.visitMethodInsn(INVOKEVIRTUAL, - STRING_BUILDER.getInternalName(), - "toString", - methodDesc(STRING)); - mv.visitMethodInsn(INVOKESTATIC, - PY.getInternalName(), - "TypeError", - methodDesc(PYEXCEPTION, STRING)); + call(STRING_BUILDER, "append", STRING_BUILDER, STRING); + call(STRING_BUILDER, "toString", STRING); + // throw a type error with our excellent message since this was of the wrong type. + callStatic(PY, "TypeError", PYEXCEPTION, STRING); mv.visitInsn(ATHROW); mv.visitLabel(regularReturn); } generateCallReturn(); } - private void pushNone() { - mv.visitFieldInsn(GETSTATIC, PY.getInternalName(), "None", PYOBJ.getDescriptor()); - } - private static boolean isWide(String methDescriptor) { return isWide(Type.getArgumentTypes(methDescriptor)); } - + private static boolean isWide(Type[] args) { return args.length == 2 && args[0].equals(APYOBJ) && args[1].equals(ASTRING); } - - private String methodName; - - protected String[] asNames, defaults; - - private String prefix; - - private Type[] params; - - private Type onType, returnType; - - protected MethodType type; } Modified: trunk/jython/src/org/python/expose/generate/NewExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/NewExposer.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/NewExposer.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -10,6 +10,10 @@ public class NewExposer extends Exposer { + private Type onType; + + private String name; + public NewExposer(Type onType, int access, String methodName, String desc, String[] exceptions) { super(PyNewWrapper.class, onType.getClassName() + "$exposed___new__"); this.onType = onType; @@ -24,9 +28,10 @@ throwInvalid("@ExposedNew methods may not throw checked exceptions"); } } - - private void throwInvalid(String msg){ - throw new InvalidExposingException(msg + "[method=" + onType.getClassName() + "." + name +"]"); + + private void throwInvalid(String msg) { + throw new InvalidExposingException(msg + "[method=" + onType.getClassName() + "." + name + + "]"); } @Override @@ -50,8 +55,7 @@ mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKESTATIC, onType.getInternalName(), name, NEW_DESCRIPTOR); - mv.visitInsn(ARETURN); - endMethod(); + endMethod(ARETURN); } public static final String NEW_DESCRIPTOR = Type.getMethodDescriptor(PYOBJ, @@ -60,8 +64,4 @@ PYTYPE, APYOBJ, ASTRING}); - - private Type onType; - - private String name; } Modified: trunk/jython/src/org/python/expose/generate/OverridableNewExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/OverridableNewExposer.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/OverridableNewExposer.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -7,12 +7,16 @@ public class OverridableNewExposer extends Exposer { + private Type onType, subtype; + + private String name; + public OverridableNewExposer(Type onType, - Type subtype, - int access, - String methodName, - String descriptor, - String[] exceptions) { + Type subtype, + int access, + String methodName, + String descriptor, + String[] exceptions) { super(PyOverridableNew.class, onType.getClassName() + "$exposed___new__"); this.onType = onType; this.subtype = subtype; @@ -35,8 +39,9 @@ private void generateOfType() { startMethod("createOfType", PYOBJ, BOOLEAN, APYOBJ, ASTRING); - instantiate(onType, new Instantiator(PYTYPE){ - public void pushArgs(){ + instantiate(onType, new Instantiator(PYTYPE) { + + public void pushArgs() { get("for_type", PYTYPE); } }); @@ -47,28 +52,20 @@ mv.visitVarInsn(ALOAD, 4); mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 3); - mv.visitMethodInsn(INVOKEVIRTUAL, onType.getInternalName(), name, methodDesc(VOID, - APYOBJ, - ASTRING)); + call(onType, name, VOID, APYOBJ, ASTRING); mv.visitLabel(regularReturn); mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(ARETURN); - endMethod(); + endMethod(ARETURN); } - + private void generateOfSubtype() { startMethod("createOfSubtype", PYOBJ, PYTYPE); - instantiate(subtype, new Instantiator(PYTYPE){ - public void pushArgs(){ + instantiate(subtype, new Instantiator(PYTYPE) { + + public void pushArgs() { mv.visitVarInsn(ALOAD, 1); } }); - mv.visitInsn(ARETURN); - endMethod(); + endMethod(ARETURN); } - - private Type onType, subtype; - - private String name; - } Modified: trunk/jython/src/org/python/expose/generate/RestrictiveAnnotationVisitor.java =================================================================== --- trunk/jython/src/org/python/expose/generate/RestrictiveAnnotationVisitor.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/RestrictiveAnnotationVisitor.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -3,9 +3,8 @@ import org.objectweb.asm.AnnotationVisitor; /** - * An Annotation visitor that throws an IllegalArgumentException if it visits - * anything other than visitEnd. Should be subclasses by something interested in - * only certain events. + * An Annotation visitor that throws an IllegalArgumentException if it visits anything other than + * visitEnd. Should be subclasses by something interested in only certain events. */ public class RestrictiveAnnotationVisitor implements AnnotationVisitor { Modified: trunk/jython/src/org/python/expose/generate/TypeExposer.java =================================================================== --- trunk/jython/src/org/python/expose/generate/TypeExposer.java 2008-01-01 01:23:18 UTC (rev 3924) +++ trunk/jython/src/org/python/expose/generate/TypeExposer.java 2008-01-01 01:43:48 UTC (rev 3925) @@ -17,11 +17,25 @@ import org.python.expose.TypeBuilder; /** - * Generates a subclass of TypeBuilder to expose a class with the - * {@link ExposedType} annotation as a builtin Python type. + * Generates a subclass of TypeBuilder to expose a class with the {@link ExposedType} annotation as + * a builtin Python type. */ public class TypeExposer extends Exposer { + private Type baseType; + + private Type onType; + + private String name; + + private Collection<MethodExposer> methods; + + private Collection<DescriptorExposer> descriptors; + + private int numNames; + + private Exposer ne; + public TypeExposer(Type onType, Type baseType, String name, @@ -35,7 +49,7 @@ this.methods = methods; this.descriptors = descriptors; Set<String> names = new HashSet<String>(); - for(DescriptorExposer exposer: descriptors) { + for(DescriptorExposer exposer : descriptors) { if(!names.add(exposer.getName())) { throwDupe(exposer.getName()); } @@ -51,7 +65,7 @@ } this.ne = ne; } - + private void throwDupe(String exposedName) { throw new InvalidExposingException("Only one item may be exposed on a type with a given name[name=" + exposedName + ", class=" + onType.getClassName() + "]"); @@ -101,7 +115,8 @@ for(final String name : exposer.getNames()) { mv.visitVarInsn(ALOAD, 1); mv.visitLdcInsn(i++); - instantiate(exposer.getGeneratedType(), new Instantiator(STRING){ + instantiate(exposer.getGeneratedType(), new Instantiator(STRING) { + public void pushArgs() { mv.visitLdcInsn(name); } @@ -132,6 +147,18 @@ protected static class BaseTypeBuilder implements TypeBuilder { + private PyNewWrapper newWrapper; + + private PyBuiltinFunction[] funcs; + + private PyDataDescr[] descrs; + + private Class typeClass; + + private Class baseClass; + + private String name; + public BaseTypeBuilder(String name, Class typeClass, Class baseClass, @@ -173,31 +200,5 @@ public Class getBase() { return baseClass; } - - private PyNewWrapper newWrapper; - - private PyBuiltinFunction[] funcs; - - private PyDataDescr[] descrs; - - private Class typeClass; - - private Class baseClass; - - private String name; } - - private Type baseType; - - private Type onType; - - private String name; - - private Collection<MethodExposer> methods; - - private Collection<DescriptorExposer> descriptors; - - private int numNames; - - private Exposer ne; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |