the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 735 lines 19 kB view raw
1// Copyright Daniel Wallin 2006. Use, modification and distribution is 2// subject to the Boost Software License, Version 1.0. (See accompanying 3// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 4 5#ifndef BOOST_PARAMETER_PYTHON_060209_HPP 6# define BOOST_PARAMETER_PYTHON_060209_HPP 7 8# include <boost/mpl/vector.hpp> 9# include <boost/mpl/fold.hpp> 10# include <boost/mpl/prior.hpp> 11# include <boost/mpl/shift_right.hpp> 12# include <boost/mpl/shift_left.hpp> 13# include <boost/mpl/bitand.hpp> 14# include <boost/mpl/pair.hpp> 15# include <boost/mpl/size.hpp> 16# include <boost/mpl/push_back.hpp> 17# include <boost/mpl/or.hpp> 18# include <boost/mpl/count_if.hpp> 19# include <boost/mpl/transform.hpp> 20# include <boost/mpl/front.hpp> 21# include <boost/mpl/iterator_range.hpp> 22# include <boost/mpl/next.hpp> 23# include <boost/mpl/begin_end.hpp> 24# include <boost/mpl/not.hpp> 25# include <boost/mpl/empty.hpp> 26# include <boost/python/def.hpp> 27# include <boost/python/make_constructor.hpp> 28# include <boost/python/init.hpp> 29# include <boost/python/to_python_converter.hpp> 30# include <boost/parameter/aux_/maybe.hpp> 31# include <boost/parameter/aux_/python/invoker.hpp> 32 33namespace boost { namespace parameter { namespace python 34{ 35 namespace python_ = boost::python; 36}}} 37 38namespace boost { namespace parameter { namespace python { namespace aux 39{ 40 41 inline PyObject* unspecified_type() 42 { 43 static PyTypeObject unspecified = { 44 PyObject_HEAD_INIT(NULL) 45 0, /* ob_size */ 46 "Boost.Parameter.Unspecified", /* tp_name */ 47 PyType_Type.tp_basicsize, /* tp_basicsize */ 48 0, /* tp_itemsize */ 49 0, /* tp_dealloc */ 50 0, /* tp_print */ 51 0, /* tp_getattr */ 52 0, /* tp_setattr */ 53 0, /* tp_compare */ 54 0, /* tp_repr */ 55 0, /* tp_as_number */ 56 0, /* tp_as_sequence */ 57 0, /* tp_as_mapping */ 58 0, /* tp_hash */ 59 0, /* tp_call */ 60 0, /* tp_str */ 61 0, /* tp_getattro */ 62 0, /* tp_setattro */ 63 0, /* tp_as_buffer */ 64 Py_TPFLAGS_DEFAULT, /* tp_flags */ 65 0, /* tp_doc */ 66 }; 67 68 if (unspecified.ob_type == 0) 69 { 70 unspecified.ob_type = &PyType_Type; 71 PyType_Ready(&unspecified); 72 } 73 74 return (PyObject*)&unspecified; 75 } 76 77 struct empty_tag {}; 78 79 struct empty_tag_to_python 80 { 81 static PyObject* convert(empty_tag) 82 { 83 return python_::xincref(unspecified_type()); 84 } 85 }; 86 87}}}} // namespace boost::parameter::python::aux 88 89namespace boost { namespace python 90{ 91 92 // Converts a Python value to a maybe<T> 93 template <class T> 94 struct arg_from_python<parameter::aux::maybe<T> > 95 : arg_from_python<T> 96 { 97 arg_from_python(PyObject* p) 98 : arg_from_python<T>(p) 99 , empty(parameter::python::aux::unspecified_type() == p) 100 {} 101 102 bool convertible() const 103 { 104 return empty || arg_from_python<T>::convertible(); 105 } 106 107 parameter::aux::maybe<T> operator()() 108 { 109 if (empty) 110 { 111 return parameter::aux::maybe<T>(); 112 } 113 else 114 { 115 return parameter::aux::maybe<T>( 116 arg_from_python<T>::operator()() 117 ); 118 } 119 } 120 121 bool empty; 122 }; 123 124}} // namespace boost::python 125 126namespace boost { namespace parameter { namespace python { 127 128namespace aux 129{ 130 131 template <class K> 132 struct is_optional 133 : mpl::not_< 134 mpl::or_<typename K::required, typename K::optimized_default> 135 > 136 {}; 137 138 template <class K, class Required, class Optimized, class T> 139 struct arg_spec 140 { 141 typedef K keyword; 142 typedef Required required; 143 typedef T type; 144 typedef Optimized optimized_default; 145 }; 146 147 template <class K, class T, class Optimized = mpl::false_> 148 struct make_arg_spec_impl 149 { 150 typedef arg_spec< 151 typename K::first, typename K::second, Optimized, T 152 > type; 153 }; 154 155 template <class K, class T> 156 struct make_arg_spec_impl<K, T, typename K::third> 157 { 158 typedef arg_spec< 159 typename K::first, typename K::second, typename K::third, T 160 > type; 161 }; 162 163 template <class K, class T> 164 struct make_arg_spec 165 : make_arg_spec_impl<K, T> 166 { 167 }; 168 169 template <class Spec, class State> 170 struct combinations_op 171 { 172 typedef typename State::second bits; 173 typedef typename State::first result0; 174 175 typedef typename mpl::if_< 176 mpl::or_< 177 typename Spec::required 178 , typename Spec::optimized_default 179 , mpl::bitand_<bits, mpl::long_<1> > 180 > 181 , typename mpl::push_back<result0, Spec>::type 182 , result0 183 >::type result; 184 185 typedef typename mpl::if_< 186 mpl::or_< 187 typename Spec::required 188 , typename Spec::optimized_default 189 > 190 , bits 191 , typename mpl::shift_right<bits, mpl::long_<1> >::type 192 >::type next_bits; 193 194 typedef mpl::pair< 195 result 196 , next_bits 197 > type; 198 }; 199 200 // Used as start value in the recursive arg() composition below. 201 struct no_keywords 202 { 203 template <class T> 204 T const& operator,(T const& x) const 205 { 206 return x; 207 } 208 }; 209 210 template <class Def, class F, class Iter, class End, class Keywords> 211 void def_combination_aux0( 212 Def def, F f, Iter, End, Keywords const& keywords, mpl::false_) 213 { 214 typedef typename mpl::deref<Iter>::type spec; 215 typedef typename spec::keyword kw; 216 217 def_combination_aux( 218 def, f, typename mpl::next<Iter>::type(), End() 219 , ( 220 keywords, boost::python::arg(kw::keyword_name()) 221 ) 222 ); 223 } 224 225 template <class Def, class F, class Iter, class End, class Keywords> 226 void def_combination_aux0( 227 Def def, F f, Iter, End, Keywords const& keywords, mpl::true_) 228 { 229 typedef typename mpl::deref<Iter>::type spec; 230 typedef typename spec::keyword kw; 231 232 def_combination_aux( 233 def, f, typename mpl::next<Iter>::type(), End() 234 , ( 235 keywords, boost::python::arg(kw::keyword_name()) = empty_tag() 236 ) 237 ); 238 } 239 240 inline void initialize_converter() 241 { 242 static python_::to_python_converter<empty_tag, empty_tag_to_python> x; 243 } 244 245 template <class Def, class F, class Iter, class End, class Keywords> 246 void def_combination_aux( 247 Def def, F f, Iter, End, Keywords const& keywords) 248 { 249 typedef typename mpl::deref<Iter>::type spec; 250 251 typedef typename mpl::and_< 252 typename spec::optimized_default 253 , mpl::not_<typename spec::required> 254 >::type optimized_default; 255 256 def_combination_aux0( 257 def, f, Iter(), End(), keywords, optimized_default() 258 ); 259 } 260 261 template <class Def, class F, class End, class Keywords> 262 void def_combination_aux( 263 Def def, F f, End, End, Keywords const& keywords) 264 { 265 def(f, keywords); 266 } 267 268 template <class Def, class F, class End> 269 void def_combination_aux( 270 Def def, F f, End, End, no_keywords const&) 271 { 272 def(f); 273 } 274 275 template < 276 class Def, class Specs, class Bits, class Invoker 277 > 278 void def_combination( 279 Def def, Specs*, Bits, Invoker*) 280 { 281 typedef typename mpl::fold< 282 Specs 283 , mpl::pair<mpl::vector0<>, Bits> 284 , combinations_op<mpl::_2, mpl::_1> 285 >::type combination0; 286 287 typedef typename combination0::first combination; 288 289 typedef typename mpl::apply_wrap1< 290 Invoker, combination 291 >::type invoker; 292 293 def_combination_aux( 294 def 295 , &invoker::execute 296 , typename mpl::begin<combination>::type() 297 , typename mpl::end<combination>::type() 298 , no_keywords() 299 ); 300 } 301 302 template < 303 class Def, class Specs, class Bits, class End, class Invoker 304 > 305 void def_combinations( 306 Def def, Specs*, Bits, End, Invoker*) 307 { 308 initialize_converter(); 309 310 def_combination(def, (Specs*)0, Bits(), (Invoker*)0); 311 312 def_combinations( 313 def 314 , (Specs*)0 315 , mpl::long_<Bits::value + 1>() 316 , End() 317 , (Invoker*)0 318 ); 319 } 320 321 template < 322 class Def, class Specs, class End, class Invoker 323 > 324 void def_combinations( 325 Def, Specs*, End, End, Invoker*) 326 {} 327 328 struct not_specified {}; 329 330 template <class CallPolicies> 331 struct call_policies_as_options 332 { 333 call_policies_as_options(CallPolicies const& call_policies) 334 : call_policies(call_policies) 335 {} 336 337 CallPolicies const& policies() const 338 { 339 return call_policies; 340 } 341 342 char const* doc() const 343 { 344 return 0; 345 } 346 347 CallPolicies call_policies; 348 }; 349 350 template <class Class, class Options = not_specified> 351 struct def_class 352 { 353 def_class(Class& cl, char const* name, Options options = Options()) 354 : cl(cl) 355 , name(name) 356 , options(options) 357 {} 358 359 template <class F> 360 void def(F f, not_specified const*) const 361 { 362 cl.def(name, f); 363 } 364 365 template <class F> 366 void def(F f, void const*) const 367 { 368 cl.def(name, f, options.doc(), options.policies()); 369 } 370 371 template <class F> 372 void operator()(F f) const 373 { 374 this->def(f, &options); 375 } 376 377 template <class F, class Keywords> 378 void def(F f, Keywords const& keywords, not_specified const*) const 379 { 380 cl.def(name, f, keywords); 381 } 382 383 template <class F, class Keywords> 384 void def(F f, Keywords const& keywords, void const*) const 385 { 386 cl.def(name, f, keywords, options.doc(), options.policies()); 387 } 388 389 template <class F, class Keywords> 390 void operator()(F f, Keywords const& keywords) const 391 { 392 this->def(f, keywords, &options); 393 } 394 395 Class& cl; 396 char const* name; 397 Options options; 398 }; 399 400 template <class Class, class CallPolicies = boost::python::default_call_policies> 401 struct def_init 402 { 403 def_init(Class& cl, CallPolicies call_policies = CallPolicies()) 404 : cl(cl) 405 , call_policies(call_policies) 406 {} 407 408 template <class F> 409 void operator()(F f) const 410 { 411 cl.def( 412 "__init__" 413 , boost::python::make_constructor(f, call_policies) 414 ); 415 } 416 417 template <class F, class Keywords> 418 void operator()(F f, Keywords const& keywords) const 419 { 420 cl.def( 421 "__init__" 422 , boost::python::make_constructor(f, call_policies, keywords) 423 ); 424 } 425 426 Class& cl; 427 CallPolicies call_policies; 428 }; 429 430 struct def_function 431 { 432 def_function(char const* name) 433 : name(name) 434 {} 435 436 template <class F> 437 void operator()(F f) const 438 { 439 boost::python::def(name, f); 440 } 441 442 template <class F, class Keywords> 443 void operator()(F f, Keywords const& keywords) const 444 { 445 boost::python::def(name, f, keywords); 446 } 447 448 char const* name; 449 }; 450 451} // namespace aux 452 453template <class M, class Signature> 454void def(char const* name, Signature) 455{ 456 typedef mpl::iterator_range< 457 typename mpl::next< 458 typename mpl::begin<Signature>::type 459 >::type 460 , typename mpl::end<Signature>::type 461 > arg_types; 462 463 typedef typename mpl::transform< 464 typename M::keywords 465 , arg_types 466 , aux::make_arg_spec<mpl::_1, mpl::_2> 467 , mpl::back_inserter<mpl::vector0<> > 468 >::type arg_specs; 469 470 typedef typename mpl::count_if< 471 arg_specs 472 , aux::is_optional<mpl::_1> 473 >::type optional_arity; 474 475 typedef typename mpl::front<Signature>::type result_type; 476 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper; 477 478 aux::def_combinations( 479 aux::def_function(name) 480 , (arg_specs*)0 481 , mpl::long_<0>() 482 , mpl::long_<upper::value>() 483 , (aux::make_invoker<M, result_type>*)0 484 ); 485} 486 487template <class M, class Class, class Signature> 488void def(Class& cl, char const* name, Signature) 489{ 490 typedef mpl::iterator_range< 491 typename mpl::next< 492 typename mpl::begin<Signature>::type 493 >::type 494 , typename mpl::end<Signature>::type 495 > arg_types; 496 497 typedef typename mpl::transform< 498 typename M::keywords 499 , arg_types 500 , aux::make_arg_spec<mpl::_1, mpl::_2> 501 , mpl::back_inserter<mpl::vector0<> > 502 >::type arg_specs; 503 504 typedef typename mpl::count_if< 505 arg_specs 506 , aux::is_optional<mpl::_1> 507 >::type optional_arity; 508 509 typedef typename mpl::front<Signature>::type result_type; 510 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper; 511 512 aux::def_combinations( 513 aux::def_class<Class>(cl, name) 514 , (arg_specs*)0 515 , mpl::long_<0>() 516 , mpl::long_<upper::value>() 517 , (aux::make_invoker<M, result_type>*)0 518 ); 519} 520 521namespace aux 522{ 523 524 template <class K> 525 struct keyword 526 { 527 typedef K type; 528 }; 529 530 template <class K> 531 struct keyword<K*> 532 { 533 typedef K type; 534 }; 535 536 template <class K> 537 struct keyword<K**> 538 { 539 typedef K type; 540 }; 541 542 template <class K> 543 struct required 544 { 545 typedef mpl::true_ type; 546 }; 547 548 template <class K> 549 struct required<K*> 550 { 551 typedef mpl::false_ type; 552 }; 553 554 template <class K> 555 struct optimized 556 { 557 typedef mpl::true_ type; 558 }; 559 560 template <class K> 561 struct optimized<K**> 562 { 563 typedef mpl::false_ type; 564 }; 565 566 template <class T> 567 struct make_kw_spec; 568 569 template <class K, class T> 570 struct make_kw_spec<K(T)> 571 { 572 typedef arg_spec< 573 typename keyword<K>::type 574 , typename required<K>::type 575 , typename optimized<K>::type 576 , T 577 > type; 578 }; 579 580} // namespace aux 581 582template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies> 583struct init 584 : boost::python::def_visitor<init<ParameterSpecs, CallPolicies> > 585{ 586 init(CallPolicies call_policies = CallPolicies()) 587 : call_policies(call_policies) 588 {} 589 590 template <class CallPolicies1> 591 init<ParameterSpecs, CallPolicies1> 592 operator[](CallPolicies1 const& call_policies) const 593 { 594 return init<ParameterSpecs, CallPolicies1>(call_policies); 595 } 596 597 template <class Class> 598 void visit_aux(Class& cl, mpl::true_) const 599 { 600 cl.def(boost::python::init<>()[call_policies]); 601 } 602 603 template <class Class> 604 void visit_aux(Class& cl, mpl::false_) const 605 { 606 typedef typename mpl::transform< 607 ParameterSpecs 608 , aux::make_kw_spec<mpl::_> 609 , mpl::back_inserter<mpl::vector0<> > 610 >::type arg_specs; 611 612 typedef typename mpl::count_if< 613 arg_specs 614 , aux::is_optional<mpl::_> 615 >::type optional_arity; 616 617 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper; 618 619 aux::def_combinations( 620 aux::def_init<Class, CallPolicies>(cl, call_policies) 621 , (arg_specs*)0 622 , mpl::long_<0>() 623 , mpl::long_<upper::value>() 624 , (aux::make_init_invoker<typename Class::wrapped_type>*)0 625 ); 626 } 627 628 template <class Class> 629 void visit(Class& cl) const 630 { 631 visit_aux(cl, mpl::empty<ParameterSpecs>()); 632 } 633 634 CallPolicies call_policies; 635}; 636 637template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies> 638struct call 639 : boost::python::def_visitor<call<ParameterSpecs, CallPolicies> > 640{ 641 call(CallPolicies const& call_policies = CallPolicies()) 642 : call_policies(call_policies) 643 {} 644 645 template <class CallPolicies1> 646 call<ParameterSpecs, CallPolicies1> 647 operator[](CallPolicies1 const& call_policies) const 648 { 649 return call<ParameterSpecs, CallPolicies1>(call_policies); 650 } 651 652 template <class Class> 653 void visit(Class& cl) const 654 { 655 typedef mpl::iterator_range< 656 typename mpl::next< 657 typename mpl::begin<ParameterSpecs>::type 658 >::type 659 , typename mpl::end<ParameterSpecs>::type 660 > arg_types; 661 662 typedef typename mpl::front<ParameterSpecs>::type result_type; 663 664 typedef typename mpl::transform< 665 arg_types 666 , aux::make_kw_spec<mpl::_> 667 , mpl::back_inserter<mpl::vector0<> > 668 >::type arg_specs; 669 670 typedef typename mpl::count_if< 671 arg_specs 672 , aux::is_optional<mpl::_> 673 >::type optional_arity; 674 675 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper; 676 677 typedef aux::call_policies_as_options<CallPolicies> options; 678 679 aux::def_combinations( 680 aux::def_class<Class, options>(cl, "__call__", options(call_policies)) 681 , (arg_specs*)0 682 , mpl::long_<0>() 683 , mpl::long_<upper::value>() 684 , (aux::make_call_invoker<typename Class::wrapped_type, result_type>*)0 685 ); 686 } 687 688 CallPolicies call_policies; 689}; 690 691template <class Fwd, class ParameterSpecs> 692struct function 693 : boost::python::def_visitor<function<Fwd, ParameterSpecs> > 694{ 695 template <class Class, class Options> 696 void visit(Class& cl, char const* name, Options const& options) const 697 { 698 typedef mpl::iterator_range< 699 typename mpl::next< 700 typename mpl::begin<ParameterSpecs>::type 701 >::type 702 , typename mpl::end<ParameterSpecs>::type 703 > arg_types; 704 705 typedef typename mpl::front<ParameterSpecs>::type result_type; 706 707 typedef typename mpl::transform< 708 arg_types 709 , aux::make_kw_spec<mpl::_> 710 , mpl::back_inserter<mpl::vector0<> > 711 >::type arg_specs; 712 713 typedef typename mpl::count_if< 714 arg_specs 715 , aux::is_optional<mpl::_> 716 >::type optional_arity; 717 718 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper; 719 720 aux::def_combinations( 721 aux::def_class<Class, Options>(cl, name, options) 722 , (arg_specs*)0 723 , mpl::long_<0>() 724 , mpl::long_<upper::value>() 725 , (aux::make_member_invoker< 726 Fwd, result_type, typename Class::wrapped_type 727 >*)0 728 ); 729 } 730}; 731 732}}} // namespace boost::parameter::python 733 734#endif // BOOST_PARAMETER_PYTHON_060209_HPP 735