// Copyright Daniel Wallin 2006. Use, modification and distribution is // subject to the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PARAMETER_PYTHON_060209_HPP # define BOOST_PARAMETER_PYTHON_060209_HPP # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include namespace boost { namespace parameter { namespace python { namespace python_ = boost::python; }}} namespace boost { namespace parameter { namespace python { namespace aux { inline PyObject* unspecified_type() { static PyTypeObject unspecified = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "Boost.Parameter.Unspecified", /* tp_name */ PyType_Type.tp_basicsize, /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ }; if (unspecified.ob_type == 0) { unspecified.ob_type = &PyType_Type; PyType_Ready(&unspecified); } return (PyObject*)&unspecified; } struct empty_tag {}; struct empty_tag_to_python { static PyObject* convert(empty_tag) { return python_::xincref(unspecified_type()); } }; }}}} // namespace boost::parameter::python::aux namespace boost { namespace python { // Converts a Python value to a maybe template struct arg_from_python > : arg_from_python { arg_from_python(PyObject* p) : arg_from_python(p) , empty(parameter::python::aux::unspecified_type() == p) {} bool convertible() const { return empty || arg_from_python::convertible(); } parameter::aux::maybe operator()() { if (empty) { return parameter::aux::maybe(); } else { return parameter::aux::maybe( arg_from_python::operator()() ); } } bool empty; }; }} // namespace boost::python namespace boost { namespace parameter { namespace python { namespace aux { template struct is_optional : mpl::not_< mpl::or_ > {}; template struct arg_spec { typedef K keyword; typedef Required required; typedef T type; typedef Optimized optimized_default; }; template struct make_arg_spec_impl { typedef arg_spec< typename K::first, typename K::second, Optimized, T > type; }; template struct make_arg_spec_impl { typedef arg_spec< typename K::first, typename K::second, typename K::third, T > type; }; template struct make_arg_spec : make_arg_spec_impl { }; template struct combinations_op { typedef typename State::second bits; typedef typename State::first result0; typedef typename mpl::if_< mpl::or_< typename Spec::required , typename Spec::optimized_default , mpl::bitand_ > > , typename mpl::push_back::type , result0 >::type result; typedef typename mpl::if_< mpl::or_< typename Spec::required , typename Spec::optimized_default > , bits , typename mpl::shift_right >::type >::type next_bits; typedef mpl::pair< result , next_bits > type; }; // Used as start value in the recursive arg() composition below. struct no_keywords { template T const& operator,(T const& x) const { return x; } }; template void def_combination_aux0( Def def, F f, Iter, End, Keywords const& keywords, mpl::false_) { typedef typename mpl::deref::type spec; typedef typename spec::keyword kw; def_combination_aux( def, f, typename mpl::next::type(), End() , ( keywords, boost::python::arg(kw::keyword_name()) ) ); } template void def_combination_aux0( Def def, F f, Iter, End, Keywords const& keywords, mpl::true_) { typedef typename mpl::deref::type spec; typedef typename spec::keyword kw; def_combination_aux( def, f, typename mpl::next::type(), End() , ( keywords, boost::python::arg(kw::keyword_name()) = empty_tag() ) ); } inline void initialize_converter() { static python_::to_python_converter x; } template void def_combination_aux( Def def, F f, Iter, End, Keywords const& keywords) { typedef typename mpl::deref::type spec; typedef typename mpl::and_< typename spec::optimized_default , mpl::not_ >::type optimized_default; def_combination_aux0( def, f, Iter(), End(), keywords, optimized_default() ); } template void def_combination_aux( Def def, F f, End, End, Keywords const& keywords) { def(f, keywords); } template void def_combination_aux( Def def, F f, End, End, no_keywords const&) { def(f); } template < class Def, class Specs, class Bits, class Invoker > void def_combination( Def def, Specs*, Bits, Invoker*) { typedef typename mpl::fold< Specs , mpl::pair, Bits> , combinations_op >::type combination0; typedef typename combination0::first combination; typedef typename mpl::apply_wrap1< Invoker, combination >::type invoker; def_combination_aux( def , &invoker::execute , typename mpl::begin::type() , typename mpl::end::type() , no_keywords() ); } template < class Def, class Specs, class Bits, class End, class Invoker > void def_combinations( Def def, Specs*, Bits, End, Invoker*) { initialize_converter(); def_combination(def, (Specs*)0, Bits(), (Invoker*)0); def_combinations( def , (Specs*)0 , mpl::long_() , End() , (Invoker*)0 ); } template < class Def, class Specs, class End, class Invoker > void def_combinations( Def, Specs*, End, End, Invoker*) {} struct not_specified {}; template struct call_policies_as_options { call_policies_as_options(CallPolicies const& call_policies) : call_policies(call_policies) {} CallPolicies const& policies() const { return call_policies; } char const* doc() const { return 0; } CallPolicies call_policies; }; template struct def_class { def_class(Class& cl, char const* name, Options options = Options()) : cl(cl) , name(name) , options(options) {} template void def(F f, not_specified const*) const { cl.def(name, f); } template void def(F f, void const*) const { cl.def(name, f, options.doc(), options.policies()); } template void operator()(F f) const { this->def(f, &options); } template void def(F f, Keywords const& keywords, not_specified const*) const { cl.def(name, f, keywords); } template void def(F f, Keywords const& keywords, void const*) const { cl.def(name, f, keywords, options.doc(), options.policies()); } template void operator()(F f, Keywords const& keywords) const { this->def(f, keywords, &options); } Class& cl; char const* name; Options options; }; template struct def_init { def_init(Class& cl, CallPolicies call_policies = CallPolicies()) : cl(cl) , call_policies(call_policies) {} template void operator()(F f) const { cl.def( "__init__" , boost::python::make_constructor(f, call_policies) ); } template void operator()(F f, Keywords const& keywords) const { cl.def( "__init__" , boost::python::make_constructor(f, call_policies, keywords) ); } Class& cl; CallPolicies call_policies; }; struct def_function { def_function(char const* name) : name(name) {} template void operator()(F f) const { boost::python::def(name, f); } template void operator()(F f, Keywords const& keywords) const { boost::python::def(name, f, keywords); } char const* name; }; } // namespace aux template void def(char const* name, Signature) { typedef mpl::iterator_range< typename mpl::next< typename mpl::begin::type >::type , typename mpl::end::type > arg_types; typedef typename mpl::transform< typename M::keywords , arg_types , aux::make_arg_spec , mpl::back_inserter > >::type arg_specs; typedef typename mpl::count_if< arg_specs , aux::is_optional >::type optional_arity; typedef typename mpl::front::type result_type; typedef typename mpl::shift_left, optional_arity>::type upper; aux::def_combinations( aux::def_function(name) , (arg_specs*)0 , mpl::long_<0>() , mpl::long_() , (aux::make_invoker*)0 ); } template void def(Class& cl, char const* name, Signature) { typedef mpl::iterator_range< typename mpl::next< typename mpl::begin::type >::type , typename mpl::end::type > arg_types; typedef typename mpl::transform< typename M::keywords , arg_types , aux::make_arg_spec , mpl::back_inserter > >::type arg_specs; typedef typename mpl::count_if< arg_specs , aux::is_optional >::type optional_arity; typedef typename mpl::front::type result_type; typedef typename mpl::shift_left, optional_arity>::type upper; aux::def_combinations( aux::def_class(cl, name) , (arg_specs*)0 , mpl::long_<0>() , mpl::long_() , (aux::make_invoker*)0 ); } namespace aux { template struct keyword { typedef K type; }; template struct keyword { typedef K type; }; template struct keyword { typedef K type; }; template struct required { typedef mpl::true_ type; }; template struct required { typedef mpl::false_ type; }; template struct optimized { typedef mpl::true_ type; }; template struct optimized { typedef mpl::false_ type; }; template struct make_kw_spec; template struct make_kw_spec { typedef arg_spec< typename keyword::type , typename required::type , typename optimized::type , T > type; }; } // namespace aux template struct init : boost::python::def_visitor > { init(CallPolicies call_policies = CallPolicies()) : call_policies(call_policies) {} template init operator[](CallPolicies1 const& call_policies) const { return init(call_policies); } template void visit_aux(Class& cl, mpl::true_) const { cl.def(boost::python::init<>()[call_policies]); } template void visit_aux(Class& cl, mpl::false_) const { typedef typename mpl::transform< ParameterSpecs , aux::make_kw_spec , mpl::back_inserter > >::type arg_specs; typedef typename mpl::count_if< arg_specs , aux::is_optional >::type optional_arity; typedef typename mpl::shift_left, optional_arity>::type upper; aux::def_combinations( aux::def_init(cl, call_policies) , (arg_specs*)0 , mpl::long_<0>() , mpl::long_() , (aux::make_init_invoker*)0 ); } template void visit(Class& cl) const { visit_aux(cl, mpl::empty()); } CallPolicies call_policies; }; template struct call : boost::python::def_visitor > { call(CallPolicies const& call_policies = CallPolicies()) : call_policies(call_policies) {} template call operator[](CallPolicies1 const& call_policies) const { return call(call_policies); } template void visit(Class& cl) const { typedef mpl::iterator_range< typename mpl::next< typename mpl::begin::type >::type , typename mpl::end::type > arg_types; typedef typename mpl::front::type result_type; typedef typename mpl::transform< arg_types , aux::make_kw_spec , mpl::back_inserter > >::type arg_specs; typedef typename mpl::count_if< arg_specs , aux::is_optional >::type optional_arity; typedef typename mpl::shift_left, optional_arity>::type upper; typedef aux::call_policies_as_options options; aux::def_combinations( aux::def_class(cl, "__call__", options(call_policies)) , (arg_specs*)0 , mpl::long_<0>() , mpl::long_() , (aux::make_call_invoker*)0 ); } CallPolicies call_policies; }; template struct function : boost::python::def_visitor > { template void visit(Class& cl, char const* name, Options const& options) const { typedef mpl::iterator_range< typename mpl::next< typename mpl::begin::type >::type , typename mpl::end::type > arg_types; typedef typename mpl::front::type result_type; typedef typename mpl::transform< arg_types , aux::make_kw_spec , mpl::back_inserter > >::type arg_specs; typedef typename mpl::count_if< arg_specs , aux::is_optional >::type optional_arity; typedef typename mpl::shift_left, optional_arity>::type upper; aux::def_combinations( aux::def_class(cl, name, options) , (arg_specs*)0 , mpl::long_<0>() , mpl::long_() , (aux::make_member_invoker< Fwd, result_type, typename Class::wrapped_type >*)0 ); } }; }}} // namespace boost::parameter::python #endif // BOOST_PARAMETER_PYTHON_060209_HPP