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