From: <cg...@us...> - 2007-10-08 06:01:13
|
Revision: 3581 http://jython.svn.sourceforge.net/jython/?rev=3581&view=rev Author: cgroves Date: 2007-10-07 23:01:12 -0700 (Sun, 07 Oct 2007) Log Message: ----------- Allow methods to be exposed as BINARY which handles returning Py.NotImplemented if they return null. It looks like the data for types vs methods will be different enough that sharing a single @Exposed between them won't hold up. I can't think of better names for separate annotations, so it stays for now. Modified Paths: -------------- branches/exposed_annotation/src/org/python/expose/Exposed.java branches/exposed_annotation/src/org/python/expose/Exposer.java branches/exposed_annotation/src/org/python/expose/MethodExposer.java branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java branches/exposed_annotation/tests/java/org/python/expose/SimpleExposed.java branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java Added Paths: ----------- branches/exposed_annotation/src/org/python/expose/MethodType.java Modified: branches/exposed_annotation/src/org/python/expose/Exposed.java =================================================================== --- branches/exposed_annotation/src/org/python/expose/Exposed.java 2007-10-08 03:21:45 UTC (rev 3580) +++ branches/exposed_annotation/src/org/python/expose/Exposed.java 2007-10-08 06:01:12 UTC (rev 3581) @@ -10,12 +10,16 @@ public @interface Exposed { /** - * @return the name to expose this item as. Defaults to the actual name of the item. + * @return the name to expose this item as. Defaults to the actual name of + * the item. */ String name() default ""; /** - * @return default arguments for a method. Starts at the number of arguments - defaults.length + * @return default arguments for a method. Starts at the number of arguments - + * defaults.length */ String[] defaults() default {}; + + MethodType type() default MethodType.NORMAL; } Modified: branches/exposed_annotation/src/org/python/expose/Exposer.java =================================================================== --- branches/exposed_annotation/src/org/python/expose/Exposer.java 2007-10-08 03:21:45 UTC (rev 3580) +++ branches/exposed_annotation/src/org/python/expose/Exposer.java 2007-10-08 06:01:12 UTC (rev 3581) @@ -1,11 +1,14 @@ package org.python.expose; +import java.io.PrintWriter; + import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.util.CheckClassAdapter; +import org.objectweb.asm.util.TraceClassVisitor; import org.python.core.BytecodeLoader; import org.python.core.Py; import org.python.core.PyBoolean; @@ -38,13 +41,17 @@ * class. cv is set to the ClassVisitor to be used when this is called. */ protected abstract void generate(); - + /** * Generates this Exposer and loads it into the given Loader. */ protected Class load(BytecodeLoader.Loader l) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - generate(new CheckClassAdapter(cw)); + ClassVisitor cv = new CheckClassAdapter(cw); + if(dump) { + cv = new TraceClassVisitor(cv, new PrintWriter(System.out)); + } + generate(cv); return l.loadClassFromBytes(getClassName(), cw.toByteArray()); } @@ -148,12 +155,14 @@ /** The type that will be generated. */ protected Type thisType; + private static final boolean dump = false; + public static final Type PYOBJ = Type.getType(PyObject.class); public static final Type PY = Type.getType(Py.class); - + public static final Type PYSTR = Type.getType(PyString.class); - + public static final Type PYBOOLEAN = Type.getType(PyBoolean.class); public static final Type BUILTIN_METHOD = Type.getType(PyBuiltinMethod.class); @@ -169,7 +178,7 @@ public static final Type STRING = Type.getType(String.class); public static final Type INT = Type.INT_TYPE; - + /** The primitive boolean type */ public static final Type BOOLEAN = Type.BOOLEAN_TYPE; Modified: branches/exposed_annotation/src/org/python/expose/MethodExposer.java =================================================================== --- branches/exposed_annotation/src/org/python/expose/MethodExposer.java 2007-10-08 03:21:45 UTC (rev 3580) +++ branches/exposed_annotation/src/org/python/expose/MethodExposer.java 2007-10-08 06:01:12 UTC (rev 3581) @@ -2,6 +2,7 @@ import java.lang.reflect.Method; +import org.objectweb.asm.Label; import org.objectweb.asm.Type; import org.python.core.PyBuiltinMethodNarrow; @@ -85,22 +86,33 @@ } private void generateCall() { + int usedLocals = 1;// We always have one used local for this Type[] args = new Type[method.getParameterTypes().length]; for(int i = 0; i < args.length; i++) { args[i] = PYOBJ; } startMethod("__call__", PYOBJ, args); Type methType = Type.getType(getMethodClass()); - mv.visitVarInsn(ALOAD, 0); get("self", PYOBJ); mv.visitTypeInsn(CHECKCAST, methType.getInternalName()); for(int i = 0; i < args.length; i++) { - mv.visitVarInsn(ALOAD, i + 1); + mv.visitVarInsn(ALOAD, usedLocals++); } mv.visitMethodInsn(INVOKEVIRTUAL, methType.getInternalName(), method.getName(), Type.getMethodDescriptor(method)); + if(exp.type() == MethodType.BINARY) { + mv.visitInsn(DUP); + Label regularReturn = new Label(); + mv.visitJumpInsn(IFNONNULL, regularReturn); + mv.visitFieldInsn(GETSTATIC, + PY.getInternalName(), + "NotImplemented", + PYOBJ.getDescriptor()); + mv.visitInsn(ARETURN); + mv.visitLabel(regularReturn); + } Class ret = method.getReturnType(); if(ret == Void.TYPE) { mv.visitFieldInsn(GETSTATIC, PY.getInternalName(), "None", PYOBJ.getDescriptor()); Added: branches/exposed_annotation/src/org/python/expose/MethodType.java =================================================================== --- branches/exposed_annotation/src/org/python/expose/MethodType.java (rev 0) +++ branches/exposed_annotation/src/org/python/expose/MethodType.java 2007-10-08 06:01:12 UTC (rev 3581) @@ -0,0 +1,5 @@ +package org.python.expose; + +public enum MethodType { + NORMAL, BINARY +} Modified: branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java =================================================================== --- branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java 2007-10-08 03:21:45 UTC (rev 3580) +++ branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java 2007-10-08 06:01:12 UTC (rev 3581) @@ -64,4 +64,12 @@ fail("Need to pass an argument to takesArgument"); } catch(Exception e) {} } + + public void testBinary() throws Exception { + MethodExposer me = new MethodExposer(SimpleExposed.class.getMethod("__add__", + PyObject.class)); + PyBuiltinFunction bound = createBound(me); + assertEquals(Py.NotImplemented, bound.__call__(Py.None)); + assertEquals(Py.One, bound.__call__(Py.False)); + } } Modified: branches/exposed_annotation/tests/java/org/python/expose/SimpleExposed.java =================================================================== --- branches/exposed_annotation/tests/java/org/python/expose/SimpleExposed.java 2007-10-08 03:21:45 UTC (rev 3580) +++ branches/exposed_annotation/tests/java/org/python/expose/SimpleExposed.java 2007-10-08 06:01:12 UTC (rev 3581) @@ -33,5 +33,13 @@ assert arg == Py.None; } + @Exposed(type=MethodType.BINARY) + public PyObject __add__(PyObject arg) { + if(arg == Py.False) { + return Py.One; + } + return null; + } + public static final String TO_STRING_RETURN = "A simple test class"; } \ No newline at end of file Modified: branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java =================================================================== --- branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java 2007-10-08 03:21:45 UTC (rev 3580) +++ branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java 2007-10-08 06:01:12 UTC (rev 3581) @@ -21,7 +21,7 @@ public void testFindMethods() { TypeExposer ecp = new TypeExposer(SimpleExposed.class); List<Method> methods = ecp.findMethods(); - assertEquals(5, methods.size()); + assertEquals(6, methods.size()); } public void testGetName() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |