Changeset 40

Show
Ignore:
Timestamp:
10/24/06 01:24:13 (6 years ago)
Author:
KirkMcDonald
Message:

Meta-programming library replaced; large re-write. StackThreads? updated to 0.3.2. Iteration updates.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dcompiler.py

    r37 r40  
    3232    'dpyobject.d', 
    3333    'exception.d', 
    34     'ftype.d', 
     34#    'ftype.d', 
    3535    'func_wrap.d', 
    3636    'iteration.d', 
     
    3838    'op_wrap.d', 
    3939    'pyd.d', 
    40     'tuples.d', 
     40#    'tuples.d', 
    4141] 
    4242 
     
    4545    'stackcontext.d', 
    4646    'stackthread.d', 
     47    'tls.d', 
     48] 
     49 
     50_metaFiles = [ 
     51    'Apply.d', 
     52    'Bind.d', 
     53    'Default.d', 
     54    'Demangle.d', 
     55    'FuncMeta.d', 
     56    'Instantiate.d', 
     57    'Nameof.d', 
     58    'Tuple.d', 
     59    'Use.d', 
     60    'Util.d', 
     61    'VarArg.d', 
    4762] 
    4863 
     
    162177            if not os.path.isfile(filePath): 
    163178                raise DistutilsPlatformError("Required StackThreads source" 
    164                     "file '%s' is missing." % filePath 
     179                    " file '%s' is missing." % filePath 
     180                ) 
     181            sources.append(filePath) 
     182        # And meta 
     183        for file in _metaFiles: 
     184            filePath = os.path.join(_infraDir, 'meta', file) 
     185            if not os.path.isfile(filePath): 
     186                raise DistutilsPlatformError("Required meta source file" 
     187                    " '%s' is missing." % filePath 
    165188                ) 
    166189            sources.append(filePath) 
     
    380403        self._debugOpt = '-debug=%s' 
    381404        # _defaultOptimizeOpts 
    382         self._defaultOptimizeOpts = ['-debug', '-unittest'
     405        self._defaultOptimizeOpts = ['-debug'
    383406        # _debugOptimizeOpts 
    384         self._debugOptimizeOpts = self._defaultOptimizeOpts + ['-g'] 
     407        self._debugOptimizeOpts = self._defaultOptimizeOpts + ['-unittest', '-g'] 
    385408        # _releaseOptimizeOpts 
    386409        self._releaseOptimizeOpts = ['-version=Optimized', '-release', '-O', '-inline'] 
  • trunk/examples/testdll/testdll.d

    r38 r40  
    66import std.stdio; 
    77 
     8import meta.Tuple; 
     9import meta.Apply; 
     10 
    811void apply_test(int i, char[] s) { 
    912    writefln("%s %s", i, s); 
     
    1114 
    1215void foo() { 
    13     alias tuple!(int, char[]) Tuple; 
    14 //    alias dg_from_tuple!(void, Tuple) dg; 
    15     Tuple t; 
    16 //    Tuple.TypeNo!(0) i = 20; 
    17 //    typeof(Tuple.arg1) j = 30; 
    18     t.arg1 = 20; 
    19     t.arg2 = "Monkey"; 
    20 //    t.arg3 = 5.8; 
    21     apply_tuple_to_fn(t, &apply_test); 
    22      
    23 //    writefln(typeid(ArgType!(dg, 1))); 
    24 //    writefln(typeid(TypeNo!(Tuple, 0))); 
    25 //    writefln(typeid(Tuple.A1)); 
    26 //    writefln(typeid(dg)); 
    27 //    writefln(i, " ", j); 
     16    alias Tuple!(int, char[]) T; 
     17    T t; 
     18    t.val!(0) = 20; 
     19    t.val!(1) = "Monkey"; 
     20    apply(&apply_test, t); 
    2821} 
    2922 
     
    4740    int m_i; 
    4841    this() { } 
    49     this(int i) { m_i = i; } 
    50     this(int i, int j) { m_i = i + j; } 
     42    this(int i) { 
     43        m_i = i; 
     44    } 
     45    this(int i, int j) { 
     46        m_i = i + j; 
     47    } 
    5148    void foo() { 
    5249        writefln("Foo.foo(): i = %s", m_i); 
     
    109106extern (C) 
    110107export void inittestdll() { 
    111     def!(foo, "foo"); 
     108    def!(foo/*, "foo"*/); 
    112109    // Python does not support function overloading. This allows us to wrap 
    113110    // an overloading function under a different name. Note that if the 
     
    132129    wrapped_class!(Foo, "Foo") f; 
    133130    // Constructor wrapping 
    134     f.init!(tuple!(int), tuple!(int, int)); 
     131    f.init!(void function(int), void function(int, int)); 
    135132    // Member function wrapping 
    136133    f.def!(Foo.foo, "foo"); 
  • trunk/html_doc/basics.html

    r39 r40  
    2828<p>Pyd requires Python 2.4 or newer and the latest version of DMD.</p> 
    2929 
    30 <p>At the moment, Pyd is only supported on Windows using the <a href="http://digitalmars.com/d/index.html">DMD</a> compiler. GDC support has been written, but Pyd cannot yet be compiled with GDC. Once GDC support is available, Pyd should work on Linux. Support for Derek Parnell's Build is also planned.</p> 
     30<p>At the moment, Pyd is only supported on Windows using the <a href="http://digitalmars.com/d/index.html">DMD</a> compiler. GDC support has been written, but Pyd cannot yet be compiled with GDC (due to <a href="http://d.puremagic.com/issues/show_bug.cgi?id=311">this bug</a>). Once GDC support is available, Pyd should work on Linux. Support for Derek Parnell's Build is also planned.</p> 
    3131 
    3232<p>Because Pyd is still in development, it is only available via Subversion. The repository is located <a href="http://svn.dsource.org/projects/pyd/trunk">here</a>.</p> 
  • trunk/infrastructure/pyd/class_wrap.d

    r37 r40  
    2222module pyd.class_wrap; 
    2323 
    24 private import python; 
    25  
    26 private import pyd.ctor_wrap; 
    27 private import pyd.def; 
    28 private import pyd.exception; 
    29 private import pyd.ftype; 
    30 private import pyd.func_wrap; 
    31 private import pyd.iteration; 
    32 private import pyd.make_object; 
    33 private import pyd.op_wrap; 
    34 private import pyd.tuples; 
    35  
    36 private import std.string; 
     24private { 
     25    import python; 
     26 
     27    import pyd.ctor_wrap; 
     28    import pyd.def; 
     29    import pyd.exception; 
     30    import pyd.func_wrap; 
     31    import pyd.iteration; 
     32    import pyd.make_object; 
     33    import pyd.op_wrap; 
     34 
     35    import meta.Default; 
     36    import meta.FuncMeta; 
     37    import meta.Tuple; 
     38 
     39    import std.string; 
     40
    3741 
    3842bool[TypeInfo] wrapped_classes; 
     
    168172    // This may be either the getter or the setter 
    169173    alias typeof(&p) p_t; 
     174    alias funcDelegInfoT!(p_t) Info; 
    170175    // This means it's the getter 
    171     static if (NumberOfArgs!(p_t) == 0) { 
     176    static if (Info.numArgs == 0) { 
    172177        alias p_t getter_type; 
    173178        // The setter may return void, or it may return the newly set attribute. 
    174         alias typeof(p(ReturnType!(p_t).init)) function(ReturnType!(p_t)) setter_type; 
     179        alias typeof(p(RetType!(p_t).init)) function(RetType!(p_t)) setter_type; 
    175180    // This means it's the setter 
    176181    } else { 
    177182        alias p_t setter_type; 
    178         alias ArgType!(p_t, 1) function() getter_type; 
     183        alias Info.Meta.ArgType!(0) function() getter_type; 
    179184    } 
    180185} 
     
    258263         *        if more than one function has the same name as this one. 
    259264         */ 
    260         template def(alias fn, char[] name, fn_t=typeof(&fn), uint MIN_ARGS = MIN_ARGS!(fn)) { 
     265        template def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn), uint MIN_ARGS = minArgs!(fn, fn_t)) { 
    261266            pragma(msg, "class.def: " ~ name); 
    262267            static void def() { 
     
    315320         * the same number of arguments. 
    316321         */ 
    317         template init(C1=Void, C2=Void, C3=Void, C4=Void, C5=Void, C6=Void, C7=Void, C8=Void, C9=Void, C10=Void) { 
    318             static void init() { 
    319                 wrapped_class_type!(T).tp_init = 
    320                     &wrapped_ctors!(T, tuple!(C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)).init_func; 
    321             } 
     322        static void init(C1=int, C2=int, C3=int, C4=int, C5=int, C6=int, C7=int, C8=int, C9=int, C10=int) () { 
     323            wrapped_class_type!(T).tp_init = 
     324                &wrapped_ctors!(T, Tuple!(C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)).init_func; 
     325        } 
     326 
     327        /** 
     328         * Allows selection of alternate opApply overloads. iter_t should be 
     329         * the type of the delegate in the opApply function that the user wants 
     330         * to be the default. 
     331         */ 
     332        static void iter(iter_t) () { 
     333            DPySC_Ready(); 
     334            wrapped_class_type!(T).tp_iter = &wrapped_iter!(T, T.opApply, int function(iter_t)).iter; 
     335        } 
     336 
     337        /** 
     338         * Exposes alternate iteration methods, originally intended for use with 
     339         * D's delegate-as-iterator features, as methods returning a Python 
     340         * iterator. 
     341         */ 
     342        static void alt_iter(alias fn, char[] name = symbolnameof!(fn), iter_t = funcDelegInfoT!(typeof(&fn)).Meta.ArgType!(0)) () { 
     343            static PyMethodDef empty = { null, null, 0, null }; 
     344            alias wrapped_method_list!(T) list; 
     345            list[length-1].ml_name = name ~ \0; 
     346            list[length-1].ml_meth = cast(PyCFunction)&wrapped_iter!(T, fn, int function(iter_t)).iter; 
     347            list[length-1].ml_flags = METH_VARARGS; 
     348            list[length-1].ml_doc = ""; 
     349            list ~= empty; 
     350            // It's possible that appending the empty item invalidated the 
     351            // pointer in the type struct, so we renew it here. 
     352            wrapped_class_type!(T).tp_methods = list; 
    322353        } 
    323354    } 
     
    350381 
    351382    static if (is(typeof(&T.opApply))) { 
    352         DPySC_Ready(); 
    353         type.tp_iter = &wrapped_iter!(T).iter; 
     383        if (type.tp_iter is null) { 
     384            DPySC_Ready(); 
     385            type.tp_iter = &wrapped_iter!(T, T.opApply).iter; 
     386        } 
    354387    } 
    355388     
  • trunk/infrastructure/pyd/ctor_wrap.d

    r37 r40  
    2727private import pyd.func_wrap; 
    2828private import pyd.make_object; 
    29 private import pyd.tuples; 
    3029 
    31 template outer(T) { 
     30private import meta.Tuple; 
     31private import meta.Bind; 
     32private import meta.Instantiate; 
     33 
     34template ctor_redirect(T) { 
    3235    T call_ctor()() { 
    3336        return new T(); 
     
    7578} 
    7679 
    77 // This template accepts a list of "ctor" templates and uses them to wrap a Python tp_init function. 
    78 template wrapped_ctors(T, Tuple) { 
     80// This template accepts a Tuple of (either) function pointer types or other 
     81// Tuples, which each describe a ctor of T, and  uses them to wrap a Python 
     82// tp_init function. 
     83template wrapped_ctors(T, Tu) { 
    7984    alias wrapped_class_object!(T) wrap_object; 
    80     const uint ARGS = Tuple.length; 
     85 
     86    // The user can provide ctor footprints as either function pointer types 
     87    // or as tuples. This converts either to a tuple. 
     88    template ctorAsTuple(T) { 
     89        static if (isTuple!(T)) 
     90            alias T ctorAsTuple; 
     91        else static if (is(typeof(*T) == function)) 
     92            alias getFuncTuple!(T) ctorAsTuple; 
     93    } 
     94 
     95    // This loops through the passed Tuple type and extracts the actual ctor 
     96    // types. 
     97    template loop(uint current, NewTu = EmptyTuple) { 
     98        static if (current == Tu.length || is(typeof(Tu.mix.val!(current))==int)) { 
     99            alias NewTu type; 
     100        } else { 
     101            alias loop!(current+1, NewTu.mix.appendT!(ctorAsTuple!(typeof(Tu.mix.val!(current))))).type type; 
     102        } 
     103    } 
     104    alias loop!(0).type Ctors; 
     105 
     106    // Checks each element of the Ctors tuple against the number of arguments 
     107    // passed in from Python. Then, it calls the ctor with the passed-in 
     108    // arguments. 
     109    int findAndCallCtor(uint current) (PyObject* self, PyObject* args, int argCount) { 
     110        static if (current == Ctors.length) { 
     111            // No match, handle error 
     112            PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments."); 
     113            return -1; 
     114        } else { 
     115            alias typeof(Ctors.mix.val!(current)) Ctor; 
     116            if (Ctor.length == argCount) { 
     117                alias instantiateTemplate!(ctor_redirect!(T).call_ctor, Ctor) fn; 
     118                WrapPyObject_SetObj(self, py_call(&fn, args)); 
     119                return 0; 
     120            } else { 
     121                return findAndCallCtor!(current+1)(self, args, argCount); 
     122            } 
     123        } 
     124    } 
     125 
    81126    extern(C) 
    82127    int init_func(PyObject* self, PyObject* args, PyObject* kwds) { 
     
    91136                } 
    92137            } 
    93             // We only match the first supplied ctor with the proper number of 
    94             // arguments. (Eventually, we'll do some more sophisticated matching, 
    95             // but this will do for now.) 
    96             static if (ARGS >= 1) { 
    97                 if (len == TypeNo!(Tuple, 0).length) { 
    98                     // This works thusly: 
    99                     // 1) outer!(T).call_ctor is a series of template functions 
    100                     //    that call a constructor with its passed arguments, and 
    101                     //    return the new object. 
    102                     // 2) instant_from_tuple is a template that instantiates a 
    103                     //    template with the types in the passed tuple type. By 
    104                     //    combining call_ctor with the selected tuple representing 
    105                     //    the best match of constructor, we can get something like 
    106                     //    a pointer to a constructor function. 
    107                     // 3) This function pointer is sent off to py_call, which calls 
    108                     //    it with the PyTuple that args points to. 
    109                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 0) ) fn1; 
    110                     WrapPyObject_SetObj(self, py_call( &fn1, args )); 
    111                     return 0; 
    112                 } 
    113             } 
    114             static if (ARGS >= 2) { 
    115                 if (len == TypeNo!(Tuple, 1).length) { 
    116                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 1) ) fn2; 
    117                     WrapPyObject_SetObj(self, py_call( &fn2, args )); 
    118                     return 0; 
    119                 } 
    120             } 
    121             static if (ARGS >= 3) { 
    122                 if (len == TypeNo!(Tuple, 2).length) { 
    123                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 2) ) fn3; 
    124                     WrapPyObject_SetObj(self, py_call( &fn3, args )); 
    125                     return 0; 
    126                 } 
    127             } 
    128             static if (ARGS >= 4) { 
    129                 if (len == TypeNo!(Tuple, 3).length) { 
    130                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 3) ) fn4; 
    131                     WrapPyObject_SetObj(self, py_call( &fn4, args )); 
    132                     return 0; 
    133                 } 
    134             } 
    135             static if (ARGS >= 5) { 
    136                 if (len == TypeNo!(Tuple, 4).length) { 
    137                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 4) ) fn5; 
    138                     WrapPyObject_SetObj(self, py_call( &fn5, args )); 
    139                     return 0; 
    140                 } 
    141             } 
    142             static if (ARGS >= 6) { 
    143                 if (len == TypeNo!(Tuple, 5).length) { 
    144                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 5) ) fn6; 
    145                     WrapPyObject_SetObj(self, py_call( &fn6, args )); 
    146                     return 0; 
    147                 } 
    148             } 
    149             static if (ARGS >= 7) { 
    150                 if (len == TypeNo!(Tuple, 6).length) { 
    151                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 6) ) fn7; 
    152                     WrapPyObject_SetObj(self, py_call( &fn7, args )); 
    153                     return 0; 
    154                 } 
    155             } 
    156             static if (ARGS >= 8) { 
    157                 if (len == TypeNo!(Tuple, 7).length) { 
    158                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 7) ) fn8; 
    159                     WrapPyObject_SetObj(self, py_call( &fn8, args )); 
    160                     return 0; 
    161                 } 
    162             } 
    163             static if (ARGS >= 9) { 
    164                 if (len == TypeNo!(Tuple, 8).length) { 
    165                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 8) ) fn9; 
    166                     WrapPyObject_SetObj(self, py_call( &fn9, args )); 
    167                     return 0; 
    168                 } 
    169             } 
    170             static if (ARGS >= 10) { 
    171                 if (len == TypeNo!(Tuple, 9).length) { 
    172                     alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 9) ) fn10; 
    173                     WrapPyObject_SetObj(self, py_call( &fn10, args )); 
    174                     return 0; 
    175                 } 
    176             } else { 
    177                 PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments."); 
    178                 return -1; 
    179             } 
     138            return findAndCallCtor!(0) (self, args, len); 
    180139        }); 
    181140    } 
  • trunk/infrastructure/pyd/def.d

    r28 r40  
    2727private import pyd.dg_convert; 
    2828private import pyd.exception; 
    29 private import pyd.ftype; 
    3029private import pyd.func_wrap; 
    3130private import pyd.make_object; 
     31 
     32private import meta.Default; 
     33private import meta.Nameof; 
    3234 
    3335private import std.string; 
     
    7779 *It's greater than 10!) 
    7880 */ 
    79 template def(alias fn, char[] name, fn_t=typeof(&fn), uint MIN_ARGS = MIN_ARGS!(fn)) { 
     81template def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn), uint MIN_ARGS = minArgs!(fn, fn_t)) { 
    8082    pragma(msg, "def: " ~ name); 
    8183    void def() { 
  • trunk/infrastructure/pyd/dg_convert.d

    r25 r40  
    2828module pyd.dg_convert; 
    2929 
    30 private import pyd.ftype
     30private import meta.FuncMeta
    3131 
    3232template fn_to_dgT(Fn) { 
    33     const uint ARGS = NumberOfArgs!(Fn); 
    34     alias ReturnType!(Fn) RetType; 
     33    alias funcDelegInfoT!(Fn) Info; 
     34    const uint ARGS = Info.numArgs; 
     35    alias RetType!(Fn) Ret; 
     36 
     37    template A(uint i) { 
     38        alias Info.Meta.ArgType!(i) A; 
     39    } 
    3540 
    3641    static if (ARGS == 0) { 
    37         alias RetType delegate() type; 
     42        alias Ret delegate() type; 
    3843    } else static if (ARGS == 1) { 
    39         alias RetType delegate(ArgType!(Fn, 1)) type; 
     44        alias Ret delegate(A!(0)) type; 
    4045    } else static if (ARGS == 2) { 
    41         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2)) type; 
     46        alias Ret delegate(A!(0), A!(1)) type; 
    4247    } else static if (ARGS == 3) { 
    43         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3)) type; 
     48        alias Ret delegate(A!(0), A!(1), A!(2)) type; 
    4449    } else static if (ARGS == 4) { 
    45         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3), ArgType!(Fn, 4)) type; 
     50        alias Ret delegate(A!(0), A!(1), A!(2), A!(3)) type; 
    4651    } else static if (ARGS == 5) { 
    47         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3), ArgType!(Fn, 4), ArgType!(Fn, 5)) type; 
     52        alias Ret delegate(A!(0), A!(1), A!(2), A!(3), A!(4)) type; 
    4853    } else static if (ARGS == 6) { 
    49         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3), ArgType!(Fn, 4), ArgType!(Fn, 5), ArgType!(Fn, 6)) type; 
     54        alias Ret delegate(A!(0), A!(1), A!(2), A!(3), A!(4), A!(5)) type; 
    5055    } else static if (ARGS == 7) { 
    51         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3), ArgType!(Fn, 4), ArgType!(Fn, 5), ArgType!(Fn, 6), ArgType!(Fn, 7)) type; 
     56        alias Ret delegate(A!(0), A!(1), A!(2), A!(3), A!(4), A!(5), A!(6)) type; 
    5257    } else static if (ARGS == 8) { 
    53         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3), ArgType!(Fn, 4), ArgType!(Fn, 5), ArgType!(Fn, 6), ArgType!(Fn, 7), ArgType!(Fn, 8)) type; 
     58        alias Ret delegate(A!(0), A!(1), A!(2), A!(3), A!(4), A!(5), A!(6), A!(7)) type; 
    5459    } else static if (ARGS == 9) { 
    55         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3), ArgType!(Fn, 4), ArgType!(Fn, 5), ArgType!(Fn, 6), ArgType!(Fn, 7), ArgType!(Fn, 8), ArgType!(Fn, 9)) type; 
     60        alias Ret delegate(A!(0), A!(1), A!(2), A!(3), A!(4), A!(5), A!(6), A!(7), A!(8)) type; 
    5661    } else static if (ARGS == 10) { 
    57         alias RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2), ArgType!(Fn, 3), ArgType!(Fn, 4), ArgType!(Fn, 5), ArgType!(Fn, 6), ArgType!(Fn, 7), ArgType!(Fn, 8), ArgType!(Fn, 9), ArgType!(Fn, 10)) type; 
     62        alias Ret delegate(A!(0), A!(1), A!(2), A!(3), A!(4), A!(5), A!(6), A!(7), A!(8), A!(9)) type; 
    5863    } 
    5964} 
     
    8994    return u.real_dg; 
    9095} 
     96 
  • trunk/infrastructure/pyd/func_wrap.d

    r37 r40  
    2222module pyd.func_wrap; 
    2323 
    24 private import python; 
    25  
    26 private import pyd.class_wrap; 
    27 private import pyd.dg_convert; 
    28 private import pyd.exception; 
    29 private import pyd.ftype; 
    30 private import pyd.make_object; 
    31 private import pyd.tuples; 
    32  
    33 private import std.string; 
     24private { 
     25    import python; 
     26 
     27    import pyd.class_wrap; 
     28    import pyd.dg_convert; 
     29    import pyd.exception; 
     30    import pyd.make_object; 
     31 
     32    import meta.Tuple; 
     33    import meta.Bind; 
     34    import meta.FuncMeta; 
     35    import meta.Apply; 
     36    import meta.Default; 
     37    import meta.Nameof; 
     38 
     39    import std.string; 
     40
    3441 
    3542// Builds a Python callable object from a delegate or function pointer. 
    36 template DPyFunc_FromDG(T, uint MIN_ARGS=NumberOfArgs!(T)) { 
     43template DPyFunc_FromDG(T) { 
    3744    PyObject* DPyFunc_FromDG(T dg) { 
    3845        alias wrapped_class_type!(T) type; 
     
    5461} 
    5562 
     63// Populates the tuple t with converted arguments from the PyTuple args 
     64private void loop(T, uint i = 0) (T* t, PyObject* args) { 
     65    static if (i < T.length) { 
     66        t.val!(i) = d_type!(typeof(t.val!(i)))(PyTuple_GetItem(args, i)); 
     67        loop!(T, i+1)(t, args); 
     68    } 
     69} 
     70 
     71private void setWrongArgsError(int gotArgs, uint minArgs, uint maxArgs) { 
     72    char[] str = "Wrong number of arguments. Got " ~ 
     73        toString(gotArgs) ~ 
     74        ", expected "; 
     75    if (minArgs == maxArgs) str ~= toString(minArgs) ~ "."; 
     76    else str ~= "between " ~ toString(minArgs) ~ " and " ~ toString(maxArgs) ~ "."; 
     77    PyErr_SetString(PyExc_TypeError, str ~ \0); 
     78} 
     79 
    5680// Calls the passed function with the passed Python tuple. 
    57 ReturnType!(fn_t) py_call(fn_t, PY)(fn_t fn, PY* args) { 
    58     const uint MAX_ARGS = NumberOfArgs!(fn_t); 
    59     alias ReturnType!(fn_t) RetType; 
     81RetType!(fn_t) py_call(fn_t, PY)(fn_t fn, PY* args) { 
     82    alias funcDelegInfoT!(fn_t) Meta; 
     83    const uint MAX_ARGS = Meta.numArgs; 
     84    alias RetType!(fn_t) RT; 
    6085 
    6186    int ARGS = 0; 
     
    6388    if (args !is null) { 
    6489        ARGS = PyObject_Length(args); 
    65         assert(ARGS == MAX_ARGS, "Function called with wrong number of arguments"); 
     90        //assert(ARGS == MAX_ARGS, "Function called with wrong number of arguments"); 
    6691    } 
    6792 
    6893    // Sanity check! 
    6994    if (ARGS != MAX_ARGS) { 
    70         PyErr_SetString(PyExc_TypeError, 
    71             "Wrong number of arguments. Got " ~ 
    72             toString(ARGS) ~ 
    73             ", expected " ~ 
    74             toString(MAX_ARGS) ~ 
    75             " args."); 
     95        setWrongArgsError(ARGS, MAX_ARGS, MAX_ARGS); 
    7696        handle_exception(); 
    7797    } 
    7898 
    79     // I've refactored this to use a tuple rather than the old cascade of 
    80     // variable function calls. There are now 10 calls to d_type where there 
    81     // once were 110. 
    82     alias tuple_from_fn!(fn_t) t_t; // tuple type 
    83     t_t t; 
    84  
    85     static if (MAX_ARGS >= 1) 
    86         t.set!(0)(d_type!(t_t.TypeNo!(0))(PyTuple_GetItem(args, 0))); 
    87     static if (MAX_ARGS >= 2) 
    88         t.set!(1)(d_type!(t_t.TypeNo!(1))(PyTuple_GetItem(args, 1))); 
    89     static if (MAX_ARGS >= 3) 
    90         t.set!(2)(d_type!(t_t.TypeNo!(2))(PyTuple_GetItem(args, 2))); 
    91     static if (MAX_ARGS >= 4) 
    92         t.set!(3)(d_type!(t_t.TypeNo!(3))(PyTuple_GetItem(args, 3))); 
    93     static if (MAX_ARGS >= 5) 
    94         t.set!(4)(d_type!(t_t.TypeNo!(4))(PyTuple_GetItem(args, 4))); 
    95     static if (MAX_ARGS >= 6) 
    96         t.set!(5)(d_type!(t_t.TypeNo!(5))(PyTuple_GetItem(args, 5))); 
    97     static if (MAX_ARGS >= 7) 
    98         t.set!(6)(d_type!(t_t.TypeNo!(6))(PyTuple_GetItem(args, 6))); 
    99     static if (MAX_ARGS >= 8) 
    100         t.set!(7)(d_type!(t_t.TypeNo!(7))(PyTuple_GetItem(args, 7))); 
    101     static if (MAX_ARGS >= 9) 
    102         t.set!(8)(d_type!(t_t.TypeNo!(8))(PyTuple_GetItem(args, 8))); 
    103     static if (MAX_ARGS >= 10) 
    104         t.set!(9)(d_type!(t_t.TypeNo!(9))(PyTuple_GetItem(args, 9))); 
    105  
    106     static if (is(RetType : void)) { 
    107         apply_tuple_to_fn(t, fn); 
     99    alias getFuncTuple!(fn_t) T; // tuple type 
     100    T t; 
     101 
     102    loop!(T)(&t, args); 
     103 
     104    static if (is(RT : void)) { 
     105        apply(fn, t); 
    108106        return; 
    109107    } else { 
    110         return apply_tuple_to_fn(t, fn); 
     108        return apply(fn, t); 
    111109    } 
    112110} 
    113111 
    114112template wrapped_func_call(fn_t) { 
    115     const uint MAX_ARGS = NumberOfArgs!(fn_t); 
    116     alias ReturnType!(fn_t) RetType; 
     113    alias funcDelegInfoT!(fn_t) Meta; 
     114    const uint MAX_ARGS = Meta.numArgs; 
     115    alias RetType!(fn_t) RT; 
    117116    // The entry for the tp_call slot of the DPyFunc types. 
    118117    // (Or: What gets called when you pass a delegate or function pointer to 
     
    129128 
    130129        return exception_catcher({ 
    131             static if (is(RetType == void)) { 
     130            static if (is(RT == void)) { 
    132131                py_call(fn, args); 
    133132                Py_INCREF(Py_None); 
     
    143142// with a PyCFunction. 
    144143template func_wrap(alias real_fn, uint MIN_ARGS, C=void, fn_t=typeof(&real_fn)) { 
    145     const uint MAX_ARGS = NumberOfArgs!(fn_t); 
    146     alias ReturnType!(fn_t) RetType; 
     144    alias funcDelegInfoT!(fn_t) Meta; 
     145    const uint MAX_ARGS = Meta.numArgs; 
     146    alias RetType!(fn_t) RT; 
    147147 
    148148    // Wraps py_call to return a PyObject* 
    149149    PyObject* py_py_call(fn_t, PY)(fn_t fn, PY* args) { 
    150         static if (is(ReturnType!(fn_t) == void)) { 
     150        static if (is(RetType!(fn_t) == void)) { 
    151151            py_call(fn, args); 
    152152            Py_INCREF(Py_None); 
     
    157157    } 
    158158 
     159    // Loops through the tuple of function pointers until the number of 
     160    // elements in the PyTuple equals the number of arguments accepted by the 
     161    // function pointer. Then, it applies the PyTuple to the function pointer. 
     162    PyObject* loop(T, uint i = 0) (T* t, PyObject* args, int argCount) { 
     163        static if (i == T.length) { 
     164            // This is tripped if the number of args in the passed PyTuple is 
     165            // not matched to a function pointer in the defaultsTuple. 
     166            setWrongArgsError(argCount, MIN_ARGS, MAX_ARGS); 
     167            return null; 
     168        } else { 
     169            alias funcDelegInfoT!(typeof(t.val!(i))) current; 
     170            if (current.numArgs == argCount) { 
     171                return py_py_call(t.val!(i), args); 
     172            } 
     173            return loop!(T, i+1) (t, args, argCount); 
     174        } 
     175    } 
     176 
    159177    // Calls py_py_call with the proper function contained in a tuple 
    160178    // returned from tuples.func_range. 
    161179    PyObject* tuple_py_call(Tu, PY)(Tu t, PY* args) { 
    162         int ARGS = 0; 
     180        int argCount = 0; 
    163181        if (args !is null) 
    164             ARGS = PyObject_Length(args); 
     182            argCount = PyObject_Length(args); 
     183         
    165184        static if (MIN_ARGS == 0) { 
    166             if (ARGS == 0) 
    167                 return py_py_call(&partial!(real_fn, 0), args); 
    168         } static if (!is(TypeNo!(Tu, 0) == Void)) { 
    169             if (ARGS == 1) 
    170                 return py_py_call(t.get!(0), args); 
    171         } static if (!is(TypeNo!(Tu, 1) == Void)) { 
    172             if (ARGS == 2) 
    173                 return py_py_call(t.get!(1), args); 
    174         } static if (!is(TypeNo!(Tu, 2) == Void)) { 
    175             if (ARGS == 3) 
    176                 return py_py_call(t.get!(2), args); 
    177         } static if (!is(TypeNo!(Tu, 3) == Void)) { 
    178             if (ARGS == 4) 
    179                 return py_py_call(t.get!(3), args); 
    180         } static if (!is(TypeNo!(Tu, 4) == Void)) { 
    181             if (ARGS == 5) 
    182                 return py_py_call(t.get!(4), args); 
    183         } static if (!is(TypeNo!(Tu, 5) == Void)) { 
    184             if (ARGS == 6) 
    185                 return py_py_call(t.get!(5), args); 
    186         } static if (!is(TypeNo!(Tu, 6) == Void)) { 
    187             if (ARGS == 7) 
    188                 return py_py_call(t.get!(6), args); 
    189         } static if (!is(TypeNo!(Tu, 7) == Void)) { 
    190             if (ARGS == 8) 
    191                 return py_py_call(t.get!(7), args); 
    192         } static if (!is(TypeNo!(Tu, 8) == Void)) { 
    193             if (ARGS == 9) 
    194                 return py_py_call(t.get!(8), args); 
    195         } static if (!is(TypeNo!(Tu, 9) == Void)) { 
    196             if (ARGS == 10) 
    197                 return py_py_call(t.get!(9), args); 
    198         } 
    199         PyErr_SetString(PyExc_RuntimeError, "Something happened..."); 
    200         return null; 
     185            if (argCount == 0) 
     186                return py_py_call(&firstArgs!(real_fn, 0, fn_t), args); 
     187        } 
     188        return loop!(Tu)(&t, args, argCount); 
    201189    } 
    202190 
     
    207195        return exception_catcher(delegate PyObject*() { 
    208196            // If C is specified, then this is a method call. We need to pull out 
    209             // the object in self and turn the member function pointer in real_fn 
     197            // the object in self and turn the member function alias real_fn 
    210198            // into a delegate. This conversion is done with a dirty hack; see 
    211199            // dg_convert.d. 
     
    219207                C instance = (cast(wrapped_class_object!(C)*)self).d_obj; 
    220208                fn_to_dg!(fn_t) fn = dg_wrapper!(C, fn_t)(instance, &real_fn); 
    221                 static if (is(ReturnType!(typeof(fn)) == void)) { 
     209                static if (is(RetType!(typeof(fn)) == void)) { 
    222210                    py_call(fn, args); 
    223211                    Py_INCREF(Py_None); 
     
    228216            // If C is not specified, then this is just a normal function call. 
    229217            } else { 
    230                 return tuple_py_call(func_range!(real_fn, MIN_ARGS)(), args); 
     218                return tuple_py_call(defaultsTuple!(real_fn, MIN_ARGS, fn_t)(), args); 
    231219            } 
    232220        }); 
     
    252240 
    253241Dg DPyCallable_AsDelegate(Dg) (PyObject* c) { 
    254     auto f = new DPyWrappedFunc(c); 
    255  
    256     const uint ARGS = NumberOfArgs!(Dg); 
    257     alias ReturnType!(Dg) Tr; 
    258     static if (ARGS == 0) 
    259         return &f.fn!(Tr); 
    260     else static if (ARGS == 1) 
    261         return &f.fn!(Tr, ArgType!(Dg, 1)); 
    262     else static if (ARGS == 2) 
    263         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2)); 
    264     else static if (ARGS == 3) 
    265         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3)); 
    266     else static if (ARGS == 4) 
    267         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4)); 
    268     else static if (ARGS == 5) 
    269         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5)); 
    270     else static if (ARGS == 6) 
    271         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6)); 
    272     else static if (ARGS == 7) 
    273         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7)); 
    274     else static if (ARGS == 8) 
    275         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7), ArgType!(Dg, 8)); 
    276     else static if (ARGS == 9) 
    277         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7), ArgType!(Dg, 8), ArgType!(Dg, 9)); 
    278     else static if (ARGS == 10) 
    279         return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7), ArgType!(Dg, 8), ArgType!(Dg, 9), ArgType!(Dg, 10)); 
    280     else static assert(false, "Unsupported number of args in delegate type."); 
    281 
    282  
    283 class Dummy { } 
     242    return _pycallable_asdgT!(Dg).func(c); 
     243
     244 
     245private template _pycallable_asdgT(Dg) { 
     246    alias funcDelegInfoT!(Dg) Info; 
     247    const uint ARGS = Info.numArgs; 
     248    alias RetType!(Dg) Tr; 
     249 
     250    template A(uint i) { 
     251        alias Info.Meta.ArgType!(i-1) A; 
     252    } 
     253 
     254    Dg func(PyObject* c) { 
     255        auto f = new DPyWrappedFunc(c); 
     256 
     257        static if (ARGS == 0) 
     258            return &f.fn!(Tr); 
     259        else static if (ARGS == 1) 
     260            return &f.fn!(Tr, A!(1)); 
     261        else static if (ARGS == 2) 
     262            return &f.fn!(Tr, A!(1), A!(2)); 
     263        else static if (ARGS == 3) 
     264            return &f.fn!(Tr, A!(1), A!(2), A!(3)); 
     265        else static if (ARGS == 4) 
     266            return &f.fn!(Tr, A!(1), A!(2), A!(3), A!(4)); 
     267        else static if (ARGS == 5) 
     268            return &f.fn!(Tr, A!(1), A!(2), A!(3), A!(4), A!(5)); 
     269        else static if (ARGS == 6) 
     270            return &f.fn!(Tr, A!(1), A!(2), A!(3), A!(4), A!(5), A!(6)); 
     271        else static if (ARGS == 7) 
     272            return &f.fn!(Tr, A!(1), A!(2), A!(3), A!(4), A!(5), A!(6), A!(7)); 
     273        else static if (ARGS == 8) 
     274            return &f.fn!(Tr, A!(1), A!(2), A!(3), A!(4), A!(5), A!(6), A!(7), A!(8)); 
     275        else static if (ARGS == 9) 
     276            return &f.fn!(Tr, A!(1), A!(2), A!(3), A!(4), A!(5), A!(6), A!(7), A!(8), A!(9)); 
     277        else static if (ARGS == 10) 
     278            return &f.fn!(Tr, A!(1), A!(2), A!(3), A!(4), A!(5), A!(6), A!(7), A!(8), A!(9), A!(10)); 
     279        else static assert(false, "Unsupported number of args in delegate type."); 
     280    } 
     281
    284282 
    285283private 
     
    297295     
    298296    Tr fn(Tr)() { 
    299         return boilerplate!(Tr)(call()); 
     297        return boilerplate!(Tr)(call(makeTuple())); 
    300298    } 
    301299     
    302300    Tr fn(Tr, T1)(T1 t1) { 
    303         return boilerplate!(Tr)(call(t1)); 
     301        return boilerplate!(Tr)(call(makeTuple(t1))); 
    304302    } 
    305303 
    306304    Tr fn(Tr, T1, T2)(T1 t1, T2 t2) { 
    307         return boilerplate!(Tr)(call(t1, t2)); 
     305        return boilerplate!(Tr)(call(makeTuple(t1, t2))); 
    308306    } 
    309307 
    310308    Tr fn(Tr, T1, T2, T3)(T1 t1, T2 t2, T3 t3) { 
    311         return boilerplate!(Tr)(call(t1, t2, t3)); 
     309        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3))); 
    312310    } 
    313311 
    314312    Tr fn(Tr, T1, T2, T3, T4)(T1 t1, T2 t2, T3 t3, T4 t4) { 
    315         return boilerplate!(Tr)(call(t1, t2, t3, t4)); 
     313        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3, t4))); 
    316314    } 
    317315 
    318316    Tr fn(Tr, T1, T2, T3, T4, T5)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { 
    319         return boilerplate!(Tr)(call(t1, t2, t3, t4, t5)); 
     317        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3, t4, t5))); 
    320318    } 
    321319 
    322320    Tr fn(Tr, T1, T2, T3, T4, T5, T6)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { 
    323         return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6)); 
     321        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3, t4, t5, t6))); 
    324322    } 
    325323 
    326324    Tr fn(Tr, T1, T2, T3, T4, T5, T6, T7)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { 
    327         return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7)); 
     325        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3, t4, t5, t6, t7))); 
    328326    } 
    329327 
    330328    Tr fn(Tr, T1, T2, T3, T4, T5, T6, T7, T8)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { 
    331         return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7, t8)); 
     329        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3, t4, t5, t6, t7, t8))); 
    332330    } 
    333331 
    334332    Tr fn(Tr, T1, T2, T3, T4, T5, T6, T7, T8, T9)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) { 
    335         return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 
     333        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3, t4, t5, t6, t7, t8, t9))); 
    336334    } 
    337335 
    338336    Tr fn(Tr, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) { 
    339         return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 
    340     } 
    341      
    342     template call(T1=Dummy, T2=Dummy, T3=Dummy, T4=Dummy, T5=Dummy, T6=Dummy, T7=Dummy, T8=Dummy, T9=Dummy, T10=Dummy) { 
    343         PyObject* call (T1 t1=null, T2 t2=null, T3 t3=null, T4 t4=null, T5 t5=null, T6 t6=null, T7 t7=null, T8 t8=null, T9 t9=null, T10 t10=null) { 
    344             static if (!is(T10 == Dummy)) 
    345                 const uint ARGS = 10; 
    346             else static if (!is(T9 == Dummy)) 
    347                 const uint ARGS = 9; 
    348             else static if (!is(T8 == Dummy)) 
    349                 const uint ARGS = 8; 
    350             else static if (!is(T7 == Dummy)) 
    351                 const uint ARGS = 7; 
    352             else static if (!is(T6 == Dummy)) 
    353                 const uint ARGS = 6; 
    354             else static if (!is(T5 == Dummy)) 
    355                 const uint ARGS = 5; 
    356             else static if (!is(T4 == Dummy)) 
    357                 const uint ARGS = 4; 
    358             else static if (!is(T3 == Dummy)) 
    359                 const uint ARGS = 3; 
    360             else static if (!is(T2 == Dummy)) 
    361                 const uint ARGS = 2; 
    362             else static if (!is(T1 == Dummy)) 
    363                 const uint ARGS = 1; 
    364             else 
    365                 const uint ARGS = 0; 
    366             PyObject* t = PyTuple_New(ARGS); 
    367             if (t is null) return null; 
    368             scope(exit) Py_DECREF(t); 
    369             static if (!is(T10 == Dummy)) 
    370                 PyTuple_SetItem(t, 9, _py(t10)); 
    371             static if (!is(T9 == Dummy)) 
    372                 PyTuple_SetItem(t, 8, _py(t9)); 
    373             static if (!is(T8 == Dummy)) 
    374                 PyTuple_SetItem(t, 7, _py(t8)); 
    375             static if (!is(T7 == Dummy)) 
    376                 PyTuple_SetItem(t, 6, _py(t7)); 
    377             static if (!is(T6 == Dummy)) 
    378                 PyTuple_SetItem(t, 5, _py(t6)); 
    379             static if (!is(T5 == Dummy)) 
    380                 PyTuple_SetItem(t, 4, _py(t5)); 
    381             static if (!is(T4 == Dummy)) 
    382                 PyTuple_SetItem(t, 3, _py(t4)); 
    383             static if (!is(T3 == Dummy)) 
    384                 PyTuple_SetItem(t, 2, _py(t3)); 
    385             static if (!is(T2 == Dummy)) 
    386                 PyTuple_SetItem(t, 1, _py(t2)); 
    387             static if (!is(T1 == Dummy)) 
    388                 PyTuple_SetItem(t, 0, _py(t1)); 
    389             return PyObject_CallObject(callable, t); 
    390         } 
    391     } 
    392 
     337        return boilerplate!(Tr)(call(makeTuple(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))); 
     338    } 
     339 
     340    void loop(T, uint current)(T* dt, PyObject* pyt) { 
     341        static if (current < T.length) { 
     342            PyTuple_SetItem(pyt, current, _py(dt.val!(current))); 
     343            loop!(T, current+1)(dt, pyt); 
     344        } 
     345    } 
     346 
     347    PyObject* call(T) (T dt) { 
     348        const uint ARGS = T.length; 
     349 
     350        PyObject* pyt = PyTuple_New(ARGS); 
     351        if (pyt is null) return null; 
     352        scope(exit) Py_DECREF(pyt); 
     353 
     354        loop!(T, 0)(&dt, pyt); 
     355        return PyObject_CallObject(callable, pyt); 
     356    } 
     357
  • trunk/infrastructure/pyd/generators/min_args.py

    r26 r40  
    33sys.stdout = open('min_args.txt', 'w') 
    44 
    5 arg_template = """ArgType!(fn_t, %s).init""" 
     5arg_template = """I!(%s)()""" 
    66 
    77template = """\ 
    8     else static if (is(typeof(fn(%s)))) 
    9         const uint MIN_ARGS = %s;""" 
     8\telse static if (is(typeof(fn(%s)))) 
     9\t\tconst uint minArgs = %s;""" 
    1010 
    11 for i in range(1, 11): 
     11for i in range(21): 
    1212    args = [] 
    1313    for j in range(i): 
    14         args.append(arg_template % (j+1,)) 
     14        args.append(arg_template % (j,)) 
    1515    print template % (", ".join(args), i) 
     16 
     17sys.stdout = old_stdout 
     18 
  • trunk/infrastructure/pyd/generators/min_args.txt

    r26 r40  
    1     else static if (is(typeof(fn(ArgType!(fn_t, 1).init)))) 
    2         const uint MIN_ARGS = 1; 
    3     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init)))) 
    4         const uint MIN_ARGS = 2; 
    5     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init)))) 
    6         const uint MIN_ARGS = 3; 
    7     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init)))) 
    8         const uint MIN_ARGS = 4; 
    9     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init)))) 
    10         const uint MIN_ARGS = 5; 
    11     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init)))) 
    12         const uint MIN_ARGS = 6; 
    13     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init)))) 
    14         const uint MIN_ARGS = 7; 
    15     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init, ArgType!(fn_t, 8).init)))) 
    16         const uint MIN_ARGS = 8; 
    17     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init, ArgType!(fn_t, 8).init, ArgType!(fn_t, 9).init)))) 
    18         const uint MIN_ARGS = 9; 
    19     else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init, ArgType!(fn_t, 8).init, ArgType!(fn_t, 9).init, ArgType!(fn_t, 10).init)))) 
    20         const uint MIN_ARGS = 10; 
     1    else static if (is(typeof(fn()))) 
     2        const uint minArgs = 0; 
     3    else static if (is(typeof(fn(I!(0)())))) 
     4        const uint minArgs = 1; 
     5    else static if (is(typeof(fn(I!(0)(), I!(1)())))) 
     6        const uint minArgs = 2; 
     7    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)())))) 
     8        const uint minArgs = 3; 
     9    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)())))) 
     10        const uint minArgs = 4; 
     11    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)())))) 
     12        const uint minArgs = 5; 
     13    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)())))) 
     14        const uint minArgs = 6; 
     15    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)())))) 
     16        const uint minArgs = 7; 
     17    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)())))) 
     18        const uint minArgs = 8; 
     19    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)())))) 
     20        const uint minArgs = 9; 
     21    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)())))) 
     22        const uint minArgs = 10; 
     23    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)())))) 
     24        const uint minArgs = 11; 
     25    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)())))) 
     26        const uint minArgs = 12; 
     27    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)())))) 
     28        const uint minArgs = 13; 
     29    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)(), I!(13)())))) 
     30        const uint minArgs = 14; 
     31    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)(), I!(13)(), I!(14)())))) 
     32        const uint minArgs = 15; 
     33    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)(), I!(13)(), I!(14)(), I!(15)())))) 
     34        const uint minArgs = 16; 
     35    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)(), I!(13)(), I!(14)(), I!(15)(), I!(16)())))) 
     36        const uint minArgs = 17; 
     37    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)(), I!(13)(), I!(14)(), I!(15)(), I!(16)(), I!(17)())))) 
     38        const uint minArgs = 18; 
     39    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)(), I!(13)(), I!(14)(), I!(15)(), I!(16)(), I!(17)(), I!(18)())))) 
     40        const uint minArgs = 19; 
     41    else static if (is(typeof(fn(I!(0)(), I!(1)(), I!(2)(), I!(3)(), I!(4)(), I!(5)(), I!(6)(), I!(7)(), I!(8)(), I!(9)(), I!(10)(), I!(11)(), I!(12)(), I!(13)(), I!(14)(), I!(15)(), I!(16)(), I!(17)(), I!(18)(), I!(19)())))) 
     42        const uint minArgs = 20; 
  • trunk/infrastructure/pyd/iteration.d

    r39 r40  
    2929private import python; 
    3030private import pyd.class_wrap; 
     31private import pyd.dg_convert; 
    3132private import pyd.exception; 
    32 private import pyd.ftype; 
     33//private import pyd.ftype; 
    3334private import pyd.make_object; 
     35 
     36private import meta.FuncMeta; 
     37 
    3438private import st.stackcontext; 
    3539 
     
    6064 
    6165// Creates an iterator object from an object. 
    62 PyObject* DPySC_FromWrapped(T) (T obj) { 
     66PyObject* DPySC_FromWrapped(T, alias Iter = T.opApply, iter_t = typeof(&Iter)) (T obj) { 
    6367    // Get the number of args the opApply's delegate argument takes 
    64     const uint ARGS = NumberOfArgsInout!(ArgType!(typeof(&T.opApply), 1)); 
     68    alias funcDelegInfoT!(iter_t) IInfo; 
     69    alias funcDelegInoutInfoT!(IInfo.Meta.ArgType!(0)) Info; 
     70    const uint ARGS = Info.numArgs; 
    6571    auto sc = new StackContext(delegate void() { 
    66         T t = obj; 
     72        T o = obj; 
     73        fn_to_dg!(iter_t) t = dg_wrapper!(T, iter_t)(o, &Iter); 
    6774        // So we can get the variable in the enclosing function's stack frame 
    6875        StackContext.yield(); 
     
    135142} 
    136143 
    137 template wrapped_iter(T) { 
     144template wrapped_iter(T, alias Iter, iter_t = typeof(&Iter)) { 
    138145    alias wrapped_class_object!(T) wrap_object; 
    139146 
     
    144151            wrap_object* self = cast(wrap_object*)_self; 
    145152 
    146             return DPySC_FromWrapped(self.d_obj); 
     153            return DPySC_FromWrapped!(T, Iter, iter_t)(self.d_obj); 
    147154        }); 
    148155    } 
  • trunk/infrastructure/st/stackcontext.d

    r37 r40  
    1919 * implementations. 
    2020 * 
    21  * Version: 0.10 
    22  * Date: June 30, 2006 
     21 * Version: 0.12 
     22 * Date: October 17, 2006 
    2323 * Authors: Mikola Lysenko, mclysenk@mtu.edu 
    2424 * License: Use/copy/modify freely, just give credit. 
     
    3131 *  since overflows are now trapped. 
    3232 * 
    33  *  Implementation is not thread safe. 
    34  * 
    3533 *  DMD has a bug on linux with multiple delegates in a 
    3634 *  scope.  Be aware that the linux version may have 
     
    4846 *  removeRange I have set it as optional. 
    4947 * 
     48 *  GDC version does not support assembler optimizations, since 
     49 *  it uses a different calling convention.  
     50 * 
    5051 * History: 
     52 *  v0.12 - Workaround for DMD bug. 
     53 * 
     54 *  v0.11 - Implementation is now thread safe. 
     55 * 
    5156 *  v0.10 - Added the LEAK_FIX flag to work around the 
    5257 *          slowness of std.gc.removeRange 
     
    8186    std.stdio, 
    8287    std.string, 
    83     std.gc; 
     88    std.gc, 
     89    st.tls; 
     90 
     91//Handle versions 
     92version(D_InlineAsm_X86) 
     93
     94    version(DigitalMars) 
     95    { 
     96        version(Win32) version = SC_WIN_ASM; 
     97        version(linux) version = SC_LIN_ASM; 
     98    } 
     99     
     100    //GDC uses a different calling conventions, need to reverse engineer them later 
     101
     102 
    84103 
    85104/// The default size of a StackContext's stack 
     
    136155    } 
    137156} 
     157 
     158 
    138159 
    139160 
     
    255276 *  
    256277 ******************************************************/ 
    257 public class StackContext 
     278public final class StackContext 
    258279{ 
    259280    /** 
     
    335356    { 
    336357        assert(state != CONTEXT_STATE.RUNNING); 
    337         assert(current_context !is this); 
     358        assert(current_context.val !is this); 
    338359    } 
    339360    body 
     
    357378     *  bubbled up through this method. 
    358379     */ 
    359     public void run() 
     380    public final void run() 
    360381    { 
    361382        debug (StackContext) writefln("Running %s", this.toString); 
    362383         
    363384        //We must be ready to run 
    364         if(state != CONTEXT_STATE.READY) 
    365         { 
    366             throw new ContextException(this,  
    367                 "Context is not in a runnable state"); 
    368         } 
     385        assert(state == CONTEXT_STATE.READY,  
     386            "Context is not in a runnable state"); 
    369387         
    370388        //Save the old context 
    371         StackContext tmp = current_context
     389        StackContext tmp = current_context.val
    372390         
    373391        version(LEAK_FIX) 
     
    379397         
    380398        //Set new context 
    381         current_context = this; 
     399        current_context.val = this; 
    382400        ctx.switchIn(); 
    383         current_context = tmp; 
     401        current_context.val = tmp; 
    384402         
    385403        assert(state != CONTEXT_STATE.RUNNING); 
     
    428446     *  running context. 
    429447     */ 
    430     public static void yield() 
    431     { 
    432         if(current_context is null) 
    433         { 
    434             throw new ContextException( 
    435                 null, 
    436                 "Tried to yield without any running contexts."); 
    437         } 
    438          
    439         debug (StackContext) writefln("Yielding %s", current_context.toString); 
    440          
    441         assert(current_context.running); 
     448    public final static void yield() 
     449    { 
     450        StackContext cur_ctx = current_context.val; 
     451         
     452        //Make sure we are actually running 
     453        assert(cur_ctx !is null, 
     454            "Tried to yield without any running contexts."); 
     455         
     456        debug (StackContext) writefln("Yielding %s", cur_ctx.toString); 
     457         
     458        assert(cur_ctx.running); 
    442459         
    443460        //Leave the current context 
    444         current_context.state = CONTEXT_STATE.READY; 
    445         StackContext tmp = current_context
     461        cur_ctx.state = CONTEXT_STATE.READY; 
     462        StackContext tmp = cur_ctx
    446463         
    447464        version(LEAK_FIX) 
    448465        { 
    449466            //Save the GC range 
    450             current_context.gc_start = cast(void*)&tmp; 
     467            cur_ctx.gc_start = cast(void*)&tmp; 
    451468            debug (LogGC) writefln("Adding range: %8x-%8x", 
    452                 current_context.gc_start, current_context.ctx.stack_top); 
    453             addRange(current_context.gc_start, current_context.ctx.stack_top); 
     469                cur_ctx.gc_start, cur_ctx.ctx.stack_top); 
     470            addRange(cur_ctx.gc_start, cur_ctx.ctx.stack_top); 
    454471        } 
    455472         
    456473        //Swap 
    457         current_context.ctx.switchOut(); 
     474        cur_ctx.ctx.switchOut(); 
    458475         
    459476        version(LEAK_FIX) 
    460477        { 
     478            StackContext t_ctx = current_context.val; 
     479             
    461480            //Remove the GC range 
    462481            debug (LogGC) writefln("Removing range: %8x", 
    463                 current_context.gc_start); 
    464             assert(current_context.gc_start !is null); 
    465             removeRange(current_context.gc_start); 
    466             current_context.gc_start = null; 
     482                t_ctx.gc_start); 
     483            assert(t_ctx.gc_start !is null); 
     484            removeRange(t_ctx.gc_start); 
     485            t_ctx.gc_start = null; 
    467486        } 
    468487         
    469488        //Return 
    470         current_context = tmp; 
    471         current_context.state = CONTEXT_STATE.RUNNING; 
    472          
    473         debug (StackContext) writefln("Resuming context: %s", current_context.toString); 
     489        current_context.val = tmp; 
     490        tmp.state = CONTEXT_STATE.RUNNING; 
     491         
     492        debug (StackContext) writefln("Resuming context: %s", tmp.toString); 
    474493    } 
    475494     
     
    484503     *  t = The exception object we will propagate. 
    485504     */ 
    486     public static void throwYield(Object t) 
    487     { 
    488         last_exception = t; 
     505    public final static void throwYield(Object t) 
     506    { 
     507        current_context.val.last_exception = t; 
    489508        yield(); 
    490509    } 
     
    496515     *  A ContextException if the context is running. 
    497516     */ 
    498     public void restart() 
     517    public final void restart() 
    499518    { 
    500519        debug (StackContext) writefln("Restarting %s", this.toString); 
    501520         
    502         if(state == CONTEXT_STATE.RUNNING) 
    503         { 
    504             throw new ContextException(this,  
    505                 "Cannot reset this context while it is running!"); 
    506         } 
     521        assert(state != CONTEXT_STATE.RUNNING, 
     522            "Cannot restart a context while it is running"); 
    507523         
    508524        //Reset the context 
     525        restartStack(); 
     526    } 
     527     
     528    /** 
     529     * Recycles the context by restarting it with a new delegate. This 
     530     * can save resources by allowing a program to reuse previously 
     531     * allocated contexts. 
     532     * 
     533     * Params: 
     534     *  dg = The delegate which we will be running. 
     535     */ 
     536    public final void recycle(void delegate() dg) 
     537    { 
     538        debug (StackContext) writefln("Recycling %s", this.toString); 
     539         
     540        assert(state != CONTEXT_STATE.RUNNING, 
     541            "Cannot recycle a context while it is running"); 
     542         
     543        //Set the delegate and restart 
     544        proc = dg; 
    509545        restartStack(); 
    510546    } 
     
    519555     *  A ContextException if the context is not READY. 
    520556     */ 
    521     public void kill() 
    522     { 
    523         if(state == CONTEXT_STATE.RUNNING) 
    524         { 
    525             throw new ContextException(this, "Cannot kill a context if it is not ready"); 
    526         } 
    527         else if(state == CONTEXT_STATE.DEAD) 
    528         { 
    529             return; 
    530         } 
     557    public final void kill() 
     558    { 
     559        assert(state != CONTEXT_STATE.RUNNING, 
     560            "Cannot kill a context while it is running."); 
     561         
    531562         
    532563        version(LEAK_FIX) 
    533564        { 
     565            if(state == CONTEXT_STATE.DEAD) 
     566            { 
     567                return; 
     568            } 
     569             
    534570            //Clear the GC ranges if necessary 
    535571            if(gc_start !is null) 
     
    550586     * Returns: A string describing the context. 
    551587     */ 
    552     public char[] toString() 
     588    public final char[] toString() 
    553589    { 
    554590        static char[][] state_names =  
     
    622658    public static StackContext getRunning() 
    623659    { 
    624         return current_context
     660        return current_context.val
    625661    } 
    626662     
     
    633669                //Make sure context is running 
    634670                //assert(ctx.old_stack_pointer !is null); 
    635                 assert(current_context !is null); 
     671                assert(current_context.val !is null); 
    636672             
    637673            case CONTEXT_STATE.READY: 
     
    655691        } 
    656692    } 
    657      
    658      
     693         
    659694    version(LEAK_FIX) 
    660695    { 
     
    669704    private CONTEXT_STATE state; 
    670705     
    671 //FIXME: All static objects should be in thread local  
    672 //storage.  Not sure how to do this effectively yet. 
    673  
    674 /*BEGIN TLS {*/ 
    675      
    676706    // The last exception generated 
    677707    private static Object last_exception = null; 
    678  
     708     
     709/*BEGIN TLS {*/ 
     710         
    679711    // The currently running stack context 
    680     private static StackContext current_context = null; 
    681  
     712    private static ThreadLocal!(StackContext) current_context = null; 
     713     
    682714/*} END TLS*/ 
    683715     
     
    767799    in 
    768800    { 
    769         assert(current_context !is null); 
     801        assert(current_context.val !is null); 
    770802        version(LEAK_FIX) 
    771             assert(current_context.gc_start is null); 
     803            assert(current_context.val.gc_start is null); 
    772804    } 
    773805    body 
    774806    { 
     807        StackContext cur_ctx = current_context.val; 
     808         
    775809        try 
    776810        { 
    777811            //Set state to running, enter the context 
    778             current_context.state = CONTEXT_STATE.RUNNING; 
    779             debug (StackContext) writefln("Starting %s", current_context.toString); 
    780             current_context.proc(); 
    781             debug (StackContext) writefln("Finished %s", current_context.toString); 
     812            cur_ctx.state = CONTEXT_STATE.RUNNING; 
     813            debug (StackContext) writefln("Starting %s", cur_ctx.toString); 
     814            cur_ctx.proc(); 
     815            debug (StackContext) writefln("Finished %s", cur_ctx.toString); 
    782816        } 
    783817        catch(Object o) 
    784818        { 
    785819            //Save exceptions so we can throw them later 
    786             debug (StackContext) writefln("Got an exception: %s, in %s", o.toString, current_context.toString); 
    787             last_exception = o; 
     820            debug (StackContext) writefln("Got an exception: %s, in %s", o.toString, cur_ctx.toString); 
     821            cur_ctx.last_exception = o; 
    788822        } 
    789823        finally 
     
    791825            //Leave the object.  Don't need to worry about 
    792826            //GC, since it should already be released. 
    793             current_context.state = CONTEXT_STATE.DEAD; 
    794             debug (StackContext) writefln("Leaving %s", current_context.toString); 
    795             current_context.ctx.switchOut(); 
     827            cur_ctx.state = CONTEXT_STATE.DEAD; 
     828            debug (StackContext) writefln("Leaving %s", cur_ctx.toString); 
     829            cur_ctx.ctx.switchOut(); 
    796830        } 
    797831         
     
    807841        version(Win32) 
    808842        { 
    809             if(current_context is null) 
     843            StackContext cur = current_context.val; 
     844             
     845            if(cur is null) 
    810846                return os_query_stackBottom(); 
    811847             
    812             return current_context.ctx.stack_top; 
     848            return cur.ctx.stack_top; 
    813849        } 
    814850        else 
     
    819855    } 
    820856} 
     857 
     858static this() 
     859{ 
     860    StackContext.current_context = new ThreadLocal!(StackContext); 
     861 
     862    version(SC_WIN_ASM) 
     863    { 
     864        //Get the system's page size 
     865        SYSTEM_INFO sys_info; 
     866        GetSystemInfo(&sys_info); 
     867        page_size = sys_info.dwPageSize; 
     868    } 
     869} 
     870 
    821871 
    822872/******************************************************** 
     
    828878 ********************************************************/ 
    829879 
    830 private version (Win32
     880private version (SC_WIN_ASM
    831881{ 
    832882 
     
    904954size_t page_size; 
    905955 
    906 static this() 
    907 { 
    908     //Get the system's page size 
    909     SYSTEM_INFO sys_info; 
    910     GetSystemInfo(&sys_info); 
    911     page_size = sys_info.dwPageSize; 
    912 } 
    913956 
    914957private struct SysContext 
     
    10351078    void killStack() 
    10361079    { 
     1080        //Work around for bug in DMD 0.170 
     1081        if(stack_bottom is null) 
     1082        { 
     1083            debug(StackContext) 
     1084                writefln("WARNING!!!! Accidentally deleted a context twice"); 
     1085            return; 
     1086        } 
     1087         
    10371088        debug (LogStack) 
    10381089        { 
     
    11411192} 
    11421193} 
    1143 else private version(linux
     1194else private version(SC_LIN_ASM
    11441195{ 
    11451196 
     
    12251276        //Initialize stack pointer 
    12261277        stack_pointer = stack_top; 
    1227  
    1228          //Initialize stack state 
    1229         void push(uint val) 
    1230         { 
    1231             stack_pointer -= 4; 
    1232             *cast(uint*)stack_pointer = val; 
    1233         } 
    1234          
    1235         push(cast(uint)&StackContext.startContext); //Start point 
    1236         push(0);        //EBP 
    1237         push(0);        //EBX 
    1238         push(0);        //ESI 
    1239         push(0);        //EDI 
     1278         
     1279        //Initialize stack state 
     1280        *cast(uint*)(stack_pointer-4) = cast(uint)&StackContext.startContext; 
     1281        stack_pointer -= 20; 
    12401282    } 
    12411283     
     
    12451287    void killStack() 
    12461288    { 
     1289        //Make sure the GC didn't accidentally double collect us... 
     1290        if(stack_bottom is null) 
     1291        { 
     1292            debug(StackContext) writefln("WARNING!!! Accidentally killed stack twice"); 
     1293            return; 
     1294        } 
     1295         
    12471296        //Deallocate the stack 
    12481297        if(munmap(stack_bottom, (stack_top - stack_bottom))) 
     
    13431392else 
    13441393{ 
    1345     //Unsupported system 
    1346     static assert(false, "Stack Context: System Unsupported"); 
     1394    static assert(false, "System currently unsupported"); 
    13471395} 
    13481396 
     
    13931441    assert(s1 == 0); 
    13941442    assert(a.getState == CONTEXT_STATE.DEAD); 
    1395     assert(b.getState == CONTEXT_STATE.READY); 
    1396      
    1397     try 
    1398     { 
    1399         a.run(); 
    1400         assert(false); 
    1401     } 
    1402     catch(ContextException ce) 
    1403     { 
    1404         debug writefln("Generated exception correctly"); 
    1405     } 
    1406      
     1443    assert(b.getState == CONTEXT_STATE.READY);     
    14071444     
    14081445    assert(b.getState == CONTEXT_STATE.READY); 
     
    16811718    } 
    16821719     
     1720    writefln("blah2"); 
     1721     
    16831722    assert(a); 
    16841723    assert(b); 
     
    19001939    delete a; 
    19011940     
    1902     StackContext b; 
    1903      
    1904     b = new StackContext( 
    1905     delegate void() 
    1906     { 
    1907         b.restart(); 
    1908         assert(false); 
    1909     }); 
    1910      
    1911     try 
    1912     { 
    1913         b.run(); 
    1914         assert(false); 
    1915     } 
    1916     catch(ContextException e) 
    1917     { 
    1918         e.print; 
    1919     } 
    1920      
    1921     try 
    1922     { 
    1923         StackContext.yield(); 
    1924         assert(false); 
    1925     } 
    1926     catch(ContextException e) 
    1927     { 
    1928         e.print; 
    1929     } 
    19301941     
    19311942    writefln("Standard exceptions passed"); 
     
    22152226} 
    22162227 
     2228unittest 
     2229{ 
     2230    writefln("Testing thread safety"); 
     2231     
     2232    int x = 0, y = 0; 
     2233     
     2234    StackContext sc0 = new StackContext( 
     2235    { 
     2236        while(true) 
     2237        { 
     2238            x++; 
     2239            StackContext.yield; 
     2240        } 
     2241    }); 
     2242     
     2243    StackContext sc1 = new StackContext( 
     2244    { 
     2245        while(true) 
     2246        { 
     2247            y++; 
     2248            StackContext.yield; 
     2249        } 
     2250    }); 
     2251     
     2252    Thread t0 = new Thread( 
     2253    { 
     2254        for(int i=0; i<10000; i++) 
     2255            sc0.run(); 
     2256         
     2257        return 0; 
     2258    }); 
     2259     
     2260    Thread t1 = new Thread( 
     2261    { 
     2262        for(int i=0; i<10000; i++) 
     2263            sc1.run(); 
     2264         
     2265        return 0; 
     2266    }); 
     2267     
     2268    assert(sc0); 
     2269    assert(sc1); 
     2270    assert(t0); 
     2271    assert(t1); 
     2272     
     2273    t0.start; 
     2274    t1.start; 
     2275    t0.wait; 
     2276    t1.wait; 
     2277     
     2278    assert(x == 10000); 
     2279    assert(y == 10000); 
     2280     
     2281    writefln("Thread safety passed!"); 
     2282} 
     2283 
  • trunk/infrastructure/st/stackthread.d

    r37 r40  
    2121 * 
    2222 * Bugs: 
    23  *  None known yet. 
     23 *  Not thread safe.  May be changed in future versions, 
     24 *  however this will require a radical refactoring. 
    2425 * 
    2526 * History: 
  • trunk/readme.txt

    r24 r40  
    1212 
    1313Celerid is primarily written by David Rushby, and Pyd is primarily written by 
    14 Kirk McDonald. 
     14Kirk McDonald. Pyd uses a number of additional libraries; see credits.txt for 
     15details. These libraries are contained in the "infrastructure" directory. 
    1516 
    1617INSTALLATION