Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:31

0001 // Copyright Daniel Wallin 2006. Use, modification and distribution is
0002 // subject to the Boost Software License, Version 1.0. (See accompanying
0003 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0004 
0005 #ifndef BOOST_PARAMETER_PYTHON_060209_HPP
0006 # define BOOST_PARAMETER_PYTHON_060209_HPP
0007 
0008 # include <boost/mpl/vector.hpp>
0009 # include <boost/mpl/fold.hpp>
0010 # include <boost/mpl/prior.hpp>
0011 # include <boost/mpl/shift_right.hpp>
0012 # include <boost/mpl/shift_left.hpp>
0013 # include <boost/mpl/bitand.hpp>
0014 # include <boost/mpl/pair.hpp>
0015 # include <boost/mpl/size.hpp>
0016 # include <boost/mpl/push_back.hpp>
0017 # include <boost/mpl/or.hpp>
0018 # include <boost/mpl/count_if.hpp>
0019 # include <boost/mpl/transform.hpp>
0020 # include <boost/mpl/front.hpp>
0021 # include <boost/mpl/iterator_range.hpp>
0022 # include <boost/mpl/next.hpp>
0023 # include <boost/mpl/begin_end.hpp>
0024 # include <boost/mpl/not.hpp>
0025 # include <boost/mpl/empty.hpp>
0026 # include <boost/python/def.hpp>
0027 # include <boost/python/make_constructor.hpp>
0028 # include <boost/python/init.hpp>
0029 # include <boost/python/to_python_converter.hpp>
0030 # include <boost/parameter/aux_/maybe.hpp>
0031 # include <boost/parameter/aux_/python/invoker.hpp>
0032 
0033 namespace boost { namespace parameter { namespace python 
0034 {
0035   namespace python_ = boost::python;
0036 }}}
0037 
0038 namespace boost { namespace parameter { namespace python { namespace aux 
0039 {
0040 
0041   inline PyObject* unspecified_type()
0042   {
0043       static PyTypeObject unspecified = {
0044           PyVarObject_HEAD_INIT(NULL,0)
0045           "Boost.Parameter.Unspecified",    /* tp_name        */
0046           PyType_Type.tp_basicsize,         /* tp_basicsize   */
0047           0,                                /* tp_itemsize    */
0048           0,                                /* tp_dealloc     */
0049           0,                                /* tp_print       */
0050           0,                                /* tp_getattr     */
0051           0,                                /* tp_setattr     */
0052           0,                                /* tp_compare     */
0053           0,                                /* tp_repr        */
0054           0,                                /* tp_as_number   */
0055           0,                                /* tp_as_sequence */
0056           0,                                /* tp_as_mapping  */
0057           0,                                /* tp_hash        */
0058           0,                                /* tp_call        */
0059           0,                                /* tp_str         */
0060           0,                                /* tp_getattro    */
0061           0,                                /* tp_setattro    */
0062           0,                                /* tp_as_buffer   */
0063           Py_TPFLAGS_DEFAULT,               /* tp_flags       */
0064           0,                                /* tp_doc         */
0065       };
0066       
0067       if (Py_TYPE(&unspecified) == 0)
0068       {
0069           Py_TYPE(&unspecified) = &PyType_Type;
0070           PyType_Ready(&unspecified);
0071       }
0072       
0073       return (PyObject*)&unspecified;
0074   }
0075 
0076   struct empty_tag {};
0077 
0078   struct empty_tag_to_python
0079   {
0080       static PyObject* convert(empty_tag)
0081       {
0082           return python_::xincref(unspecified_type());
0083       }
0084   };
0085 
0086 }}}} // namespace boost::parameter::python::aux
0087 
0088 namespace boost { namespace python 
0089 {
0090 
0091   // Converts a Python value to a maybe<T>
0092   template <class T>
0093   struct arg_from_python<parameter::aux::maybe<T> >
0094     : arg_from_python<T>
0095   {
0096       arg_from_python(PyObject* p)
0097         : arg_from_python<T>(p)
0098         , empty(parameter::python::aux::unspecified_type() == p)
0099       {}
0100 
0101       bool convertible() const
0102       {
0103           return empty || arg_from_python<T>::convertible();
0104       }
0105 
0106       parameter::aux::maybe<T> operator()()
0107       {
0108           if (empty)
0109           {
0110               return parameter::aux::maybe<T>();
0111           }
0112           else
0113           {
0114               return parameter::aux::maybe<T>(
0115                   arg_from_python<T>::operator()()
0116               );
0117           }
0118       }
0119 
0120       bool empty;
0121   };
0122 
0123 }} // namespace boost::python
0124 
0125 namespace boost { namespace parameter { namespace python {
0126 
0127 namespace aux
0128 {
0129 
0130   template <class K>
0131   struct is_optional
0132     : mpl::not_<
0133           mpl::or_<typename K::required, typename K::optimized_default>
0134       >
0135   {};
0136 
0137   template <class K, class Required, class Optimized, class T>
0138   struct arg_spec
0139   {
0140       typedef K keyword;
0141       typedef Required required;
0142       typedef T type;
0143       typedef Optimized optimized_default;
0144   };
0145   
0146   template <class K, class T, class Optimized = mpl::false_>
0147   struct make_arg_spec_impl
0148   {
0149       typedef arg_spec<
0150           typename K::first, typename K::second, Optimized, T
0151       > type;
0152   };
0153 
0154   template <class K, class T>
0155   struct make_arg_spec_impl<K, T, typename K::third>
0156   {
0157       typedef arg_spec<
0158           typename K::first, typename K::second, typename K::third, T
0159       > type;
0160   };
0161 
0162   template <class K, class T>
0163   struct make_arg_spec
0164     : make_arg_spec_impl<K, T>
0165   {
0166   };
0167 
0168   template <class Spec, class State>
0169   struct combinations_op
0170   {
0171       typedef typename State::second bits;
0172       typedef typename State::first result0;
0173 
0174       typedef typename mpl::if_<
0175           mpl::or_<
0176               typename Spec::required
0177             , typename Spec::optimized_default
0178             , mpl::bitand_<bits, mpl::long_<1> >
0179           >
0180         , typename mpl::push_back<result0, Spec>::type
0181         , result0
0182       >::type result;
0183 
0184       typedef typename mpl::if_<
0185           mpl::or_<
0186               typename Spec::required
0187             , typename Spec::optimized_default
0188           >
0189         , bits
0190         , typename mpl::shift_right<bits, mpl::long_<1> >::type
0191       >::type next_bits;
0192 
0193       typedef mpl::pair<
0194           result
0195         , next_bits
0196       > type;
0197   };
0198 
0199   // Used as start value in the recursive arg() composition below.
0200   struct no_keywords
0201   {
0202       template <class T>
0203       T const& operator,(T const& x) const
0204       {
0205           return x;
0206       }
0207   };
0208 
0209   template <class Def, class F, class Iter, class End, class Keywords>
0210   void def_combination_aux0(
0211       Def def, F f, Iter, End, Keywords const& keywords, mpl::false_)
0212   {
0213       typedef typename mpl::deref<Iter>::type spec;
0214       typedef typename spec::keyword kw;
0215 
0216       def_combination_aux(
0217           def, f, typename mpl::next<Iter>::type(), End()
0218         , (
0219               keywords, boost::python::arg(kw::keyword_name())
0220           )
0221       );
0222   }
0223 
0224   template <class Def, class F, class Iter, class End, class Keywords>
0225   void def_combination_aux0(
0226       Def def, F f, Iter, End, Keywords const& keywords, mpl::true_)
0227   {
0228       typedef typename mpl::deref<Iter>::type spec;
0229       typedef typename spec::keyword kw;
0230 
0231       def_combination_aux(
0232           def, f, typename mpl::next<Iter>::type(), End()
0233         , (
0234               keywords, boost::python::arg(kw::keyword_name()) = empty_tag()
0235           )
0236       );
0237   }
0238 
0239   inline void initialize_converter()
0240   {
0241       static python_::to_python_converter<empty_tag, empty_tag_to_python> x;
0242   }
0243 
0244   template <class Def, class F, class Iter, class End, class Keywords>
0245   void def_combination_aux(
0246       Def def, F f, Iter, End, Keywords const& keywords)
0247   {
0248       typedef typename mpl::deref<Iter>::type spec;
0249 
0250       typedef typename mpl::and_<
0251           typename spec::optimized_default
0252         , mpl::not_<typename spec::required>
0253       >::type optimized_default;
0254       
0255       def_combination_aux0(
0256           def, f, Iter(), End(), keywords, optimized_default()
0257       );
0258   }
0259 
0260   template <class Def, class F, class End, class Keywords>
0261   void def_combination_aux(
0262       Def def, F f, End, End, Keywords const& keywords)
0263   {
0264       def(f, keywords);
0265   } 
0266 
0267   template <class Def, class F, class End>
0268   void def_combination_aux(
0269       Def def, F f, End, End, no_keywords const&)
0270   {
0271       def(f);
0272   }
0273 
0274   template <
0275       class Def, class Specs, class Bits, class Invoker
0276   >
0277   void def_combination(
0278       Def def, Specs*, Bits, Invoker*)
0279   {
0280       typedef typename mpl::fold<
0281           Specs
0282         , mpl::pair<mpl::vector0<>, Bits>
0283         , combinations_op<mpl::_2, mpl::_1>
0284       >::type combination0;
0285 
0286       typedef typename combination0::first combination;
0287 
0288       typedef typename mpl::apply_wrap1<
0289           Invoker, combination
0290       >::type invoker;
0291 
0292       def_combination_aux(
0293           def
0294         , &invoker::execute
0295         , typename mpl::begin<combination>::type()
0296         , typename mpl::end<combination>::type()
0297         , no_keywords()
0298       );
0299   }
0300 
0301   template <
0302       class Def, class Specs, class Bits, class End, class Invoker
0303   >
0304   void def_combinations(
0305       Def def, Specs*, Bits, End, Invoker*)
0306   {
0307       initialize_converter();
0308 
0309       def_combination(def, (Specs*)0, Bits(), (Invoker*)0);
0310 
0311       def_combinations(
0312           def
0313         , (Specs*)0
0314         , mpl::long_<Bits::value + 1>()
0315         , End()
0316         , (Invoker*)0
0317       );
0318   }
0319 
0320   template <
0321       class Def, class Specs, class End, class Invoker
0322   >
0323   void def_combinations(
0324       Def, Specs*, End, End, Invoker*)
0325   {}
0326 
0327   struct not_specified {};
0328 
0329   template <class CallPolicies>
0330   struct call_policies_as_options
0331   {
0332       call_policies_as_options(CallPolicies const& call_policies)
0333         : call_policies(call_policies)
0334       {}
0335 
0336       CallPolicies const& policies() const
0337       {
0338           return call_policies;
0339       }
0340 
0341       char const* doc() const
0342       {
0343           return 0;
0344       }
0345 
0346       CallPolicies call_policies;
0347   };
0348 
0349   template <class Class, class Options = not_specified>
0350   struct def_class
0351   {
0352       def_class(Class& cl, char const* name, Options options = Options())
0353         : cl(cl)
0354         , name(name)
0355         , options(options)
0356       {}
0357 
0358       template <class F>
0359       void def(F f, not_specified const*) const
0360       {
0361           cl.def(name, f);
0362       }
0363 
0364       template <class F>
0365       void def(F f, void const*) const
0366       {
0367           cl.def(name, f, options.doc(), options.policies());
0368       }
0369       
0370       template <class F>
0371       void operator()(F f) const
0372       {
0373           this->def(f, &options);
0374       }
0375 
0376       template <class F, class Keywords>
0377       void def(F f, Keywords const& keywords, not_specified const*) const
0378       {
0379           cl.def(name, f, keywords);
0380       }
0381 
0382       template <class F, class Keywords>
0383       void def(F f, Keywords const& keywords, void const*) const
0384       {
0385           cl.def(name, f, keywords, options.doc(), options.policies());
0386       }
0387 
0388       template <class F, class Keywords>
0389       void operator()(F f, Keywords const& keywords) const
0390       {
0391           this->def(f, keywords, &options);
0392       }
0393 
0394       Class& cl;
0395       char const* name;
0396       Options options;
0397   };
0398 
0399   template <class Class, class CallPolicies = boost::python::default_call_policies>
0400   struct def_init
0401   {
0402       def_init(Class& cl, CallPolicies call_policies = CallPolicies())
0403         : cl(cl)
0404         , call_policies(call_policies)
0405       {}
0406 
0407       template <class F>
0408       void operator()(F f) const
0409       {
0410           cl.def(
0411               "__init__"
0412             , boost::python::make_constructor(f, call_policies)
0413           );
0414       }
0415 
0416       template <class F, class Keywords>
0417       void operator()(F f, Keywords const& keywords) const
0418       {
0419           cl.def(
0420               "__init__"
0421             , boost::python::make_constructor(f, call_policies, keywords)
0422           );
0423       }
0424 
0425       Class& cl;
0426       CallPolicies call_policies;
0427   };
0428 
0429   struct def_function
0430   {
0431       def_function(char const* name)
0432         : name(name)
0433       {}
0434       
0435       template <class F>
0436       void operator()(F f) const
0437       {
0438           boost::python::def(name, f);
0439       }
0440 
0441       template <class F, class Keywords>
0442       void operator()(F f, Keywords const& keywords) const
0443       {
0444           boost::python::def(name, f, keywords);
0445       }
0446 
0447       char const* name;
0448   };
0449 
0450 } // namespace aux
0451 
0452 template <class M, class Signature>
0453 void def(char const* name, Signature)
0454 {
0455     typedef mpl::iterator_range<
0456         typename mpl::next<
0457             typename mpl::begin<Signature>::type
0458         >::type
0459       , typename mpl::end<Signature>::type
0460     > arg_types;
0461 
0462     typedef typename mpl::transform<
0463         typename M::keywords
0464       , arg_types
0465       , aux::make_arg_spec<mpl::_1, mpl::_2>
0466       , mpl::back_inserter<mpl::vector0<> >
0467     >::type arg_specs;
0468 
0469     typedef typename mpl::count_if<
0470         arg_specs
0471       , aux::is_optional<mpl::_1>
0472     >::type optional_arity;
0473     
0474     typedef typename mpl::front<Signature>::type result_type;
0475     typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0476 
0477     aux::def_combinations(
0478         aux::def_function(name)
0479       , (arg_specs*)0
0480       , mpl::long_<0>()
0481       , mpl::long_<upper::value>()
0482       , (aux::make_invoker<M, result_type>*)0
0483     );
0484 }
0485 
0486 template <class M, class Class, class Signature>
0487 void def(Class& cl, char const* name, Signature)
0488 {
0489     typedef mpl::iterator_range<
0490         typename mpl::next<
0491             typename mpl::begin<Signature>::type
0492         >::type
0493       , typename mpl::end<Signature>::type
0494     > arg_types;
0495 
0496     typedef typename mpl::transform<
0497         typename M::keywords
0498       , arg_types
0499       , aux::make_arg_spec<mpl::_1, mpl::_2>
0500       , mpl::back_inserter<mpl::vector0<> >
0501     >::type arg_specs;
0502 
0503     typedef typename mpl::count_if<
0504         arg_specs
0505       , aux::is_optional<mpl::_1>
0506     >::type optional_arity;
0507     
0508     typedef typename mpl::front<Signature>::type result_type;
0509     typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0510 
0511     aux::def_combinations(
0512         aux::def_class<Class>(cl, name)
0513       , (arg_specs*)0
0514       , mpl::long_<0>()
0515       , mpl::long_<upper::value>()
0516       , (aux::make_invoker<M, result_type>*)0
0517     );
0518 }
0519 
0520 namespace aux
0521 {
0522 
0523   template <class K>
0524   struct keyword
0525   {
0526       typedef K type;
0527   };
0528 
0529   template <class K>
0530   struct keyword<K*>
0531   {
0532       typedef K type;
0533   };
0534 
0535   template <class K>
0536   struct keyword<K**>
0537   {
0538       typedef K type;
0539   };
0540 
0541   template <class K>
0542   struct required
0543   {
0544       typedef mpl::true_ type;
0545   };
0546 
0547   template <class K>
0548   struct required<K*>
0549   {
0550       typedef mpl::false_ type;
0551   };
0552 
0553   template <class K>
0554   struct optimized
0555   {
0556       typedef mpl::true_ type;
0557   };
0558 
0559   template <class K>
0560   struct optimized<K**>
0561   {
0562       typedef mpl::false_ type;
0563   };
0564 
0565   template <class T>
0566   struct make_kw_spec;
0567 
0568   template <class K, class T>
0569   struct make_kw_spec<K(T)>
0570   {
0571       typedef arg_spec<
0572           typename keyword<K>::type
0573         , typename required<K>::type
0574         , typename optimized<K>::type
0575         , T
0576       > type;
0577   };
0578 
0579 } // namespace aux
0580 
0581 template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>
0582 struct init 
0583   : boost::python::def_visitor<init<ParameterSpecs, CallPolicies> >
0584 {
0585     init(CallPolicies call_policies = CallPolicies())
0586       : call_policies(call_policies)
0587     {}
0588 
0589     template <class CallPolicies1>
0590     init<ParameterSpecs, CallPolicies1> 
0591     operator[](CallPolicies1 const& call_policies) const
0592     {
0593         return init<ParameterSpecs, CallPolicies1>(call_policies);
0594     }
0595 
0596     template <class Class>
0597     void visit_aux(Class& cl, mpl::true_) const
0598     {
0599         cl.def(boost::python::init<>()[call_policies]);
0600     }
0601 
0602     template <class Class>
0603     void visit_aux(Class& cl, mpl::false_) const
0604     {
0605         typedef typename mpl::transform<
0606             ParameterSpecs
0607           , aux::make_kw_spec<mpl::_>
0608           , mpl::back_inserter<mpl::vector0<> >
0609         >::type arg_specs;
0610 
0611         typedef typename mpl::count_if<
0612             arg_specs
0613           , aux::is_optional<mpl::_>
0614         >::type optional_arity;
0615 
0616         typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0617 
0618         aux::def_combinations(
0619             aux::def_init<Class, CallPolicies>(cl, call_policies)
0620           , (arg_specs*)0
0621           , mpl::long_<0>()
0622           , mpl::long_<upper::value>()
0623           , (aux::make_init_invoker<typename Class::wrapped_type>*)0
0624         );
0625     }
0626 
0627     template <class Class>
0628     void visit(Class& cl) const
0629     {
0630         visit_aux(cl, mpl::empty<ParameterSpecs>());
0631     }
0632 
0633     CallPolicies call_policies;
0634 };
0635 
0636 template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>
0637 struct call 
0638   : boost::python::def_visitor<call<ParameterSpecs, CallPolicies> >
0639 {
0640     call(CallPolicies const& call_policies = CallPolicies())
0641       : call_policies(call_policies)
0642     {}
0643 
0644     template <class CallPolicies1>
0645     call<ParameterSpecs, CallPolicies1>
0646     operator[](CallPolicies1 const& call_policies) const
0647     {
0648         return call<ParameterSpecs, CallPolicies1>(call_policies);
0649     }
0650 
0651     template <class Class>
0652     void visit(Class& cl) const
0653     {
0654         typedef mpl::iterator_range<
0655             typename mpl::next<
0656                 typename mpl::begin<ParameterSpecs>::type
0657             >::type
0658           , typename mpl::end<ParameterSpecs>::type
0659         > arg_types;
0660 
0661         typedef typename mpl::front<ParameterSpecs>::type result_type;
0662 
0663         typedef typename mpl::transform<
0664             arg_types
0665           , aux::make_kw_spec<mpl::_>
0666           , mpl::back_inserter<mpl::vector0<> >
0667         >::type arg_specs;
0668 
0669         typedef typename mpl::count_if<
0670             arg_specs
0671           , aux::is_optional<mpl::_>
0672         >::type optional_arity;
0673 
0674         typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0675 
0676         typedef aux::call_policies_as_options<CallPolicies> options;
0677 
0678         aux::def_combinations(
0679             aux::def_class<Class, options>(cl, "__call__", options(call_policies))
0680           , (arg_specs*)0
0681           , mpl::long_<0>()
0682           , mpl::long_<upper::value>()
0683           , (aux::make_call_invoker<typename Class::wrapped_type, result_type>*)0
0684         );
0685     }
0686 
0687     CallPolicies call_policies;
0688 };
0689 
0690 template <class Fwd, class ParameterSpecs>
0691 struct function 
0692   : boost::python::def_visitor<function<Fwd, ParameterSpecs> >
0693 {
0694     template <class Class, class Options>
0695     void visit(Class& cl, char const* name, Options const& options) const
0696     {
0697         typedef mpl::iterator_range<
0698             typename mpl::next<
0699                 typename mpl::begin<ParameterSpecs>::type
0700             >::type
0701           , typename mpl::end<ParameterSpecs>::type
0702         > arg_types;
0703 
0704         typedef typename mpl::front<ParameterSpecs>::type result_type;
0705 
0706         typedef typename mpl::transform<
0707             arg_types
0708           , aux::make_kw_spec<mpl::_>
0709           , mpl::back_inserter<mpl::vector0<> >
0710         >::type arg_specs;
0711 
0712         typedef typename mpl::count_if<
0713             arg_specs
0714           , aux::is_optional<mpl::_>
0715         >::type optional_arity;
0716 
0717         typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
0718 
0719         aux::def_combinations(
0720             aux::def_class<Class, Options>(cl, name, options)
0721           , (arg_specs*)0
0722           , mpl::long_<0>()
0723           , mpl::long_<upper::value>()
0724           , (aux::make_member_invoker<
0725                 Fwd, result_type, typename Class::wrapped_type
0726             >*)0
0727         );
0728     }
0729 };
0730 
0731 }}} // namespace boost::parameter::python
0732 
0733 #endif // BOOST_PARAMETER_PYTHON_060209_HPP
0734