Changeset 101
- Timestamp:
- 02/21/07 17:01:34 (1 year ago)
- Files:
-
- trunk/infrastructure/pyd/class_wrap.d (modified) (16 diffs)
- trunk/infrastructure/pyd/ctor_wrap.d (modified) (1 diff)
- trunk/infrastructure/pyd/make_wrapper.d (modified) (3 diffs)
- trunk/infrastructure/pyd/struct_wrap.d (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/infrastructure/pyd/class_wrap.d
r100 r101 285 285 static const uint min_args = MIN_ARGS; 286 286 287 static void call(T ) () {287 static void call(T, shim) () { 288 288 pragma(msg, "class.def: " ~ name); 289 289 static PyMethodDef empty = { null, null, 0, null }; … … 305 305 " }\n"; 306 306 } 307 template shim_call(char[] varname, uint i) {308 const char[] shim_call = "Def!("~varname~"."~_realname~", p"~ToString!(i)~".realname, p"~ToString!(i)~".funcname, p"~ToString!(i)~".func_t, p"~ToString!(i)~".min_args)";309 }310 307 } 311 308 … … 319 316 static const char[] funcname = name; 320 317 static const uint min_args = MIN_ARGS; 321 static void call(T ) () {318 static void call(T, shim) () { 322 319 pragma(msg, "class.static_def: " ~ name); 323 320 static PyMethodDef empty = { null, null, 0, null }; … … 333 330 const char[] shim = ""; 334 331 } 335 template shim_call(char[] varname, uint i) {336 const char[] shim_call = "DoNothing";337 }338 332 } 339 333 … … 355 349 static const char[] funcname = name; 356 350 static const bool readonly = RO; 357 static void call(T ) () {351 static void call(T, shim) () { 358 352 pragma(msg, "class.prop: " ~ name); 359 353 static PyGetSetDef empty = { null, null, null, null, null }; … … 391 385 shim_setter!(i); 392 386 } 393 template shim_call(char[] varname, uint i) {394 const char[] shim_call = "Property!("~varname~"."~_realname~", p"~ToString!(i)~".realname, p"~ToString!(i)~".funcname, p"~ToString!(i)~".readonly)";395 }396 387 } 397 388 … … 410 401 struct Init(C ...) { 411 402 alias C ctors; 412 static void call(T ) () {403 static void call(T, shim) () { 413 404 wrapped_class_type!(T).tp_init = 414 &wrapped_ctors!( T, C).init_func;405 &wrapped_ctors!(shim, C).init_func; 415 406 } 416 407 template shim_impl(uint i, uint c=0) { … … 421 412 " }\n" ~ shim_impl!(i, c+1); 422 413 } else { 423 const char[] shim_impl = ""; 414 const char[] shim_impl = 415 " static if (is(typeof(new T))) {\n" 416 " this() { super(); }\n" 417 " }\n"; 424 418 } 425 419 } … … 430 424 shim_impl!(i); 431 425 } 432 template shim_call(char[] varname, uint i) {433 const char[] shim_call = "Init!(p"~ToString!(i)~".ctors)";434 }435 426 } 436 427 … … 444 435 */ 445 436 struct Iter(iter_t) { 446 static void call(T) () { 437 alias iter_t iterator_t; 438 static void call(T, shim) () { 447 439 PydStackContext_Ready(); 448 440 // This strange bit of hackery is needed since we operate on pointer- … … 462 454 */ 463 455 struct AltIter(alias fn, char[] name = symbolnameof!(fn), iter_t = funcDelegInfoT!(typeof(&fn)).Meta.ArgType!(0)) { 464 static void call(T ) () {456 static void call(T, shim) () { 465 457 static PyMethodDef empty = { null, null, 0, null }; 466 458 alias wrapped_method_list!(T) list; … … 479 471 } /*Pyd_with_StackThreads*/ 480 472 481 private482 template comma(uint i, uint length) {483 static if (i < length-1) {484 const char[] comma = ",";485 } else {486 const char[] comma = "";487 }488 }489 490 private491 template recursive_call(char[] name, int i, Params...) {492 static if (i < Params.length) {493 const char[] recursive_call = Params[i].shim_call!(name, i) ~ comma!(i, Params.length) ~ recursive_call!(name, i+1, Params);494 } else {495 const char[] recursive_call = "";496 }497 }498 499 private500 template aliases(uint i, Params...) {501 static if (i < Params.length) {502 const char[] aliases = "alias Params["~ToString!(i)~"] p"~ToString!(i)~";\n" ~ aliases!(i+1, Params);503 } else {504 const char[] aliases = "";505 }506 }507 508 473 void wrap_class(T, Params...) (char[] docstring="", char[] modulename="") { 509 wrap_class!(void, T, symbolnameof!(T), Params)(docstring, modulename); 510 } 511 void wrap_class(T, char[] name, Params...) (char[] docstring="", char[] modulename="") { 512 wrap_class!(void, T, name, Params)(docstring, modulename); 513 } 514 515 void wrap_class(wrapping, _T, char[] name, Params...) (char[] docstring="", char[] modulename="") { 474 wrap_class!(T, symbolnameof!(T), Params)(docstring, modulename); 475 } 476 void wrap_class(_T, char[] name, Params...) (char[] docstring="", char[] modulename="") { 516 477 //alias CLS.wrapped_type T; 517 478 //const char[] name = CLS._name; 518 479 static if (is(_T == class)) { 519 480 pragma(msg, "wrap_class: " ~ name); 481 alias make_wrapper!(_T, Params).wrapper shim_class; 520 482 alias _T T; 521 483 } else { 522 484 pragma(msg, "wrap_struct: " ~ name); 485 alias void shim_class; 523 486 alias _T* T; 524 487 } … … 528 491 //Params params; 529 492 foreach (param; Params) { 530 param.call!(T )();493 param.call!(T, shim_class)(); 531 494 } 532 495 … … 548 511 // Inheritance // 549 512 ///////////////// 550 static if (is(wrapping == void)) { 551 // Inherit directly-wrapped classes from their wrapped superclass. 552 static if (is(T B == super)) { 553 foreach (C; B) { 554 static if (is(C == class) && !is(C == Object)) { 555 if (is_wrapped!(C)) { 556 type.tp_base = &wrapped_class_type!(C); 557 } 558 } 559 } 560 } 561 } else { 562 // Inherit shims from their grandparent's shim. 563 static if (is(wrapping B == super)) { 564 foreach (C; B) { 565 static if (is(C == class) && !is(C == Object)) { 566 type.tp_base = shim_class!(C); 513 // Inherit classes from their wrapped superclass. 514 static if (is(T B == super)) { 515 foreach (C; B) { 516 static if (is(C == class) && !is(C == Object)) { 517 if (is_wrapped!(C)) { 518 type.tp_base = &wrapped_class_type!(C); 567 519 } 568 520 } … … 608 560 // Constructor wrapping // 609 561 ////////////////////////// 610 static if (is(wrapping == void) && is(T == class)) { 611 // Non-shim classes cannot be instantiated from Python. 612 type.tp_init = null; 613 } else { 614 // If a ctor wasn't supplied, try the default. 615 // If the default ctor isn't available, and no ctors were supplied, 616 // then this class cannot be instantiated from Python. 617 // (Structs always use the default ctor.) 618 static if (is(typeof(new T))) { 619 if (type.tp_init is null) { 620 static if (is(T == class)) { 621 type.tp_init = &wrapped_init!(T).init; 622 } else { 623 type.tp_init = &wrapped_struct_init!(T).init; 624 } 562 // If a ctor wasn't supplied, try the default. 563 // If the default ctor isn't available, and no ctors were supplied, 564 // then this class cannot be instantiated from Python. 565 // (Structs always use the default ctor.) 566 static if (is(typeof(new T))) { 567 if (type.tp_init is null) { 568 static if (is(T == class)) { 569 type.tp_init = &wrapped_init!(shim_class).init; 570 } else { 571 type.tp_init = &wrapped_struct_init!(T).init; 625 572 } 626 573 } … … 634 581 } 635 582 Py_INCREF(cast(PyObject*)&type); 636 // Only directly expose a class to Python if it is a shim. 637 static if (!is(wrapping == void) || is(T U : U*) && is(U == struct)) { 638 PyModule_AddObject(Pyd_Module_p(modulename), name.ptr, cast(PyObject*)&type); 639 } 583 PyModule_AddObject(Pyd_Module_p(modulename), (name~\0).ptr, cast(PyObject*)&type); 640 584 641 585 is_wrapped!(T) = true; 642 586 static if (is(T == class)) { 587 is_wrapped!(shim_class) = true; 643 588 wrapped_classes[T.classinfo] = &type; 644 // If this is a class passed in by the user, create and wrap the shim. 645 // (By recursively calling this function.) 646 static if (is(wrapping == void)) { 647 alias make_wrapper!(T, Params).wrapper wrapper_class; 648 // Construct the recursive call. Since /this/ call to wrap_class 649 // was passed aliases to the members of the /base/ class, we need 650 // to pass the recursive call aliases to the members of the /shim/. 651 // The recursive_call template goes through each member of Params 652 // and constructs this. 653 654 // This is a workaround for some tuple shortcomings... 655 const char[] a = aliases!(0, Params); 656 pragma(msg, a); 657 mixin(a); 658 659 const char[] call = "wrap_class!(T, wrapper_class, name, "~recursive_call!("wrapper_class", 0, Params)~")();"; 660 pragma(msg, call); 661 mixin(call); 662 shim_class!(T) = &wrapped_class_type!(wrapper_class); 663 } 589 wrapped_classes[shim_class.classinfo] = &type; 664 590 } 665 591 } trunk/infrastructure/pyd/ctor_wrap.d
r100 r101 65 65 } 66 66 67 // This template accepts a Tuple of (either) function pointer types or other 68 // Tuples, which each describe a ctor of T, and uses them to wrap a Python 69 // tp_init function. 67 // This template accepts a tuple of function pointer types, which each describe 68 // a ctor of T, and uses them to wrap a Python tp_init function. 70 69 template wrapped_ctors(T, C ...) { 71 70 alias wrapped_class_object!(T) wrap_object; trunk/infrastructure/pyd/make_wrapper.d
r100 r101 34 34 ; 35 35 36 template T(A ...) { 37 alias A T; 38 } 39 template opFuncs() { 40 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; 41 } 42 43 template funcTypes() { 44 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; 45 } 46 template pyOpFuncs() { 47 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; 48 } 49 50 template opFunc(uint i) { 51 const char[] opFunc = opFuncs!()[i]; 52 } 53 54 template funcType(uint i) { 55 const char[] funcType = funcTypes!()[i]; 56 } 57 58 template pyOpFunc(uint i) { 59 const char[] pyOpFunc = pyOpFuncs!()[i]; 60 } 61 62 template op_shim(uint i) { 63 static if (funcType!(i) == "UNI" || funcType!(i) == "BIN" || funcType!(i) == "CMP" || funcType!("CALL")) { 64 const char[] op_shim = 65 " ReturnType!(T."~opFunc!(i)~") "~opFunc!(i)~"(ParameterTypeTuple!(T."~opFunc!(i)~") t) {\n" 66 " return __pyd_get_overload!(\""~opFunc!(i)~"\", typeof(&T."~opFunc!(i)~")).func(\""~pyOpFunc!(i)~"\", t);\n" 67 " }\n"; 68 } else static if (funcType!(i) == "APPLY") { 69 const char[] op_shim = 70 " int opApply(ParameterTypeTuple!(T.opApply)[0] dg) {\n" 71 " return __pyd_apply_wrapper(dg);\n" 72 " }\n"; 73 } else static assert(false, "Unsupported operator overload " ~ opFunc!(i)); 74 } 75 76 template op_shims(uint i, T) { 77 static if (i < opFuncs!().length) { 78 static if (is(typeof(mixin("&T."~opFunc!(i)))) && opFunc!(i) != "UNSUPPORTED") { 79 const char[] op_shims = op_shim!(i) ~ op_shims!(i+1, T); 80 } else { 81 const char[] op_shims = op_shims(i+1, T); 82 } 83 } else { 84 const char[] op_shims = ""; 85 } 86 } 87 36 88 template OverloadShim() { 89 // If this is actually an instance of a Python subclass, return the 90 // PyObject associated with the object. Otherwise, return null. 91 PyObject* __pyd_get_pyobj() { 92 PyObject** _pyobj = cast(void*)this in wrapped_gc_objects; 93 PyTypeObject** _pytype = this.classinfo in wrapped_classes; 94 if (_pyobj is null || _pytype is null || (*_pyobj).ob_type != *_pytype) { 95 return *_pyobj; 96 } else { 97 return null; 98 } 99 } 37 100 template __pyd_get_overload(char[] realname, fn_t) { 38 101 ReturnType!(fn_t) func(T ...) (char[] name, T t) { 39 PyObject** _pyobj = cast(void*)this in wrapped_gc_objects; 40 PyTypeObject** _pytype = this.classinfo in wrapped_classes; 41 if (_pyobj is null || _pytype is null || (*_pyobj).ob_type != *_pytype) { 102 PyObject* _pyobj = this.__pyd_get_pyobj(); 103 if (_pyobj !is null) { 42 104 // If this object's type is not the wrapped class's type (that is, 43 105 // if this object is actually a Python subclass of the wrapped 44 106 // class), then call the Python object. 45 PyObject* method = PyObject_GetAttrString( *_pyobj, (name ~ \0).ptr);107 PyObject* method = PyObject_GetAttrString(_pyobj, (name ~ \0).ptr); 46 108 if (method is null) handle_exception(); 47 109 auto pydg = PydCallable_AsDelegate!(fn_to_dg!(fn_t))(method); … … 51 113 mixin("return super."~realname~"(t);"); 52 114 } 115 } 116 } 117 int __pyd_apply_wrapper(dg_t) (dg_t dg) { 118 alias ParameterTypeTuple!(dg_t)[0] arg_t; 119 const uint args = ParameterTypeTuple!(dg_t).length; 120 PyObject* _pyobj = this.__pyd_get_pyobj(); 121 if (_pyobj !is null) { 122 PyObject* iter = PyObject_GetIter(_pyobj); 123 if (iter is null) handle_exception(); 124 PyObject* item; 125 int result = 0; 126 127 item = PyIter_Next(iter); 128 while (item) { 129 static if (args == 1 && is(arg_t == PyObject*)) { 130 result = dg(item); 131 } else { 132 if (PyTuple_Check(item)) { 133 result = applyPyTupleToDelegate(dg, item); 134 } else { 135 static if (args == 1) { 136 arg_t t = d_type!(typeof(arg_t))(item); 137 result = dg(t); 138 } else { 139 throw new Exception("Tried to override opApply with wrong number of args..."); 140 } 141 } 142 } 143 Py_DECREF(item); 144 if (result) break; 145 item = PyIter_Next(iter); 146 } 147 Py_DECREF(iter); 148 handle_exception(); 149 return result; 150 } else { 151 return super.opApply(dg); 53 152 } 54 153 } … … 68 167 " mixin OverloadShim;\n"~ 69 168 class_decls!(0, Params)~"\n"~ 169 // op_shims!(0, T)~ 70 170 "}\n"; 71 171 pragma(msg, cls); trunk/infrastructure/pyd/struct_wrap.d
r100 r101 64 64 65 65 struct Member(char[] realname, char[] name=realname) { 66 static void call(T ) () {66 static void call(T, dummy) () { 67 67 pragma(msg, "struct.member: " ~ name); 68 68 static PyGetSetDef empty = {null, null, null, null, null};
