Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/parameter/python.hpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 18.6 KB
Line 
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
Note: See TracBrowser for help on using the repository browser.