Commits

ariovistus committed 296ef00

enable wrapped D objects to be made iterable by their ranges in python.

remove mention of opApply from examples.
readme.panache++

  • Participants
  • Parent commits d259b82

Comments (0)

Files changed (6)

File examples/testdll/setup.py

     name=projName,
     version='0.1',
     ext_modules=[
-        Extension(projName, [projName + '.d'], build_deimos=True)
+        Extension(projName, [projName + '.d'], 
+            d_lump=True, 
+            build_deimos=True)
     ],
   )

File examples/testdll/test.py

 print "Testing operator overloading"
 print a+a
 
-print "Testing opApply wrapping:"
-try:
-    for i in a:
-        print i
-except TypeError, e:
-    print "opApply not supported on this platform"
+print "Testing range iteration wrapping:"
+for i in a:
+    print i
 
 print
 

File examples/testdll/testdll.d

         return new Foo(m_i + f.m_i); 
     }
 
-    int opApply(int delegate(ref int, ref int) dg) {
-        int result = 0;
-        int j;
-        for (int i=0; i<10; ++i) {
-            j = i+1;
-            result = dg(i, j);
-            if (result) break;
+    struct Range {
+        int i = 0;
+
+        @property bool empty() {
+            return i >= 10;
         }
-        return result;
+        @property int front() {
+            return i+1;
+        }
+        void popFront() {
+            i++;
+        }
+    }
+
+    Range opSlice() {
+        return Range();
     }
     @property int i() { return m_i; }
     @property void i(int j) { m_i = j; }
     int[] m_a;
     this() { }
     this(int[] i ...) { m_a = i; }
-    int opApply(int delegate(ref int) dg) {
-        int result = 0;
-        for (int i=0; i<m_a.length; ++i) {
-            result = dg(m_a[i]);
-            if (result) break;
-        }
-        return result;
-    }
 }
 
 struct S {
         Init!(int, int),
         Property!(Foo.i, Docstring!"A sample property of Foo."),
         OpBinary!("+"),
+        Def!(Foo.opSlice, PyName!"__iter__", Foo.Range function()),
         Def!(Foo.foo, Docstring!"A sample method of Foo."),
         Def!(Foo.a),
         Def!(Foo.b),

File infrastructure/pyd/class_wrap.d

     enum bool needs_shim = false;
     static void call(T)() {
         alias wrapped_class_type!T type;
-        static if(Iters.length == 1 && Nexts.length == 1) {
+        import std.range;
+        static if(Iters.length == 1 && (Nexts.length == 1 || isInputRange!(ReturnType!(Iters[0].func)))) {
             version(Python_3_0_Or_Later) {
             }else{
                 type.tp_flags |= Py_TPFLAGS_HAVE_ITER;
             }
             type.tp_iter = &opiter_wrap!(T, Iters[0].func).func;
-            type.tp_iternext = &opiter_wrap!(T, Nexts[0].func).func;
+            static if(Nexts.length == 1)
+                type.tp_iternext = &opiter_wrap!(T, Nexts[0].func).func;
         }
     }
 }

File infrastructure/pyd/make_wrapper.d

 import pyd.func_wrap;
 import std.traits;
 
-template T(A ...) {
-    alias A T;
-}
-template opFuncs() {
-    alias T!("opNeg", "opPos", "opCom", "opAdd", "opSub", "opMul", "opDiv", "opMod", "opAnd", "opOr", "opXor", "opShl", "opShr", "opCat", "opAddAssign", "opSubAssign", "opMulAssign", "opDivAssign", "opModAssign", "opAndAssign", "opOrAssign", "opXorAssign", "opShlAssign", "opShrAssign", "opCatAssign", "opIn_r", "opCmp", "opCall", "opApply", "opIndex", "opIndexAssign", "opSlice", "opSliceAssign", "length") opFuncs;
-}
-
-template funcTypes() {
-    alias T!("UNI", "UNI", "UNI", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "BIN", "UNSUPPORTED", "CMP", "CALL", "APPLY", "INDEX", "INDEXASS", "SLICE", "SLICEASS", "LEN") funcTypes;
-}
-template pyOpFuncs() {
-    alias T!("__neg__", "__pos__", "__invert__", "__add__", "__sub__", "__mul__", "__div__", "__mod__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__add__", "__iadd__", "__isub__", "__imul__", "__idiv__", "__imod__", "__iand__", "__ior__", "__ixor__", "__ilshift__", "__irshift__", "__iadd__", "UNSUPPORTED", "__cmp__", "__call__", "__iter__", "__getitem__", "__setitem__", "UNSUPPORTED", "UNSUPPORTED", "__len__") pyOpFuncs;
-}
-
-template opFunc(uint i) {
-    enum string opFunc = opFuncs!()[i];
-}
-
-template funcType(uint i) {
-    enum string funcType = funcTypes!()[i];
-}
-
-template pyOpFunc(uint i) {
-    enum string pyOpFunc = pyOpFuncs!()[i];
-}
-
-template op_shim(uint i) {
-    static if (funcType!(i) == "UNI" || funcType!(i) == "BIN" || funcType!(i) == "CMP" || funcType!("CALL")) {
-        enum string op_shim =
-            "    ReturnType!(T."~opFunc!(i)~") "~opFunc!(i)~"(ParameterTypeTuple!(T."~opFunc!(i)~") t) {\n"
-            "        return __pyd_get_overload!(\""~opFunc!(i)~"\", typeof(&T."~opFunc!(i)~")).func(\""~pyOpFunc!(i)~"\", t);\n"
-            "    }\n";
-    } else static if (funcType!(i) == "APPLY") {
-        enum string op_shim =
-            "    int opApply(ParameterTypeTuple!(T.opApply)[0] dg) {\n"
-            "        return __pyd_apply_wrapper(dg);\n"
-            "    }\n";
-    } else static assert(false, "Unsupported operator overload " ~ opFunc!(i));
-}
-
-template op_shims(uint i, T) {
-    static if (i < opFuncs!().length) {
-        static if (is(typeof(mixin("&T."~opFunc!(i)))) && opFunc!(i) != "UNSUPPORTED") {
-            enum string op_shims = op_shim!(i) ~ op_shims!(i+1, T);
-        } else {
-            enum string op_shims = op_shims(i+1, T);
-        }
-    } else {
-        enum string op_shims = "";
-    }
-}
-
 template OverloadShim() {
     // If this is actually an instance of a Python subclass, return the
     // PyObject associated with the object. Otherwise, return null.
     "class wrapper : T {\n"~
     "    mixin OverloadShim;\n"~
     pyd.make_wrapper.class_decls!(0, T, Params)~"\n"~
-//    op_shims!(0, T)~
     "}\n";
     pragma(msg, cls);
     mixin(cls);
 Welcome to Pyd!
 
-Pyd is currently under development, and is in the middle of API 
+Pyd is currently under development, and is still subject to API 
 changes (https://bitbucket.org/ariovistus/pyd/wiki/Changes)
 
+Current status: https://bitbucket.org/ariovistus/pyd/wiki/Status
+
 This package is composed of two separate parts:
 
   * CeleriD - An extension to Python's Distutils that is aware of D.
   * Pyd - A library for D that wraps the Python API.
 
-CeleriD was originally written by David Rushby, and Pyd is written by Kirk
+CeleriD was originally written by David Rushby, and Pyd was written by Kirk
 McDonald. Pyd uses a number of additional libraries; see credits.txt for
 details. These libraries are contained in the "infrastructure" directory.
 
 INSTALLATION
 
-In the easiest case, you just need to say:
+Normally it is as simple as
 
     python setup.py install
 
-while in the root directory of the project. This will place CeleriD in Python's
+from the root directory of the project. This will place CeleriD in Python's
 site-packages directory, and Pyd lives inside of CeleriD.
 
-The easiest time will be had if both D and Python are on the system's PATH.
+For the smoothest of sailing, ensure both D and Python are on the system's PATH.
 This is not required, however:
 
   * On Windows, only the DMD compiler is supported. If it is not found on the
     PATH, CeleriD will check the DMD_BIN environment variable.
-  * On Linux, currently the LDC compiler is supported. If it is not found on the
-    PATH, CeleriD will check the LDC_BIN environment variable.
+  * On Linux, currently the DMD compiler is supported. If it is not found on the
+    PATH, CeleriD will check the DMD_BIN environment variable.
 
 Examples of using Pyd may be found in the "examples" directory. For full
 documentation, check the wiki: