|
Boost : |
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2008-03-02 14:39:22
Hello,
First of all, sorry for the long post.
I'm doing a Locally Unique Identifier generator library.
The DSL grammar is quite complex (see below), so the use of optional
parameters seams unavoidable. I have started to use the Boost.Parameter
Library as the Boost.Flyweight does.
For the recover node which can takes two optional parameters recovery_when
and recovery_how, this results in:
<code>
template <typename Arg1=parameter::void_, typename Arg2=parameter::void_>
struct recover : on_release_marker {
private:
typedef parameter::parameters<
parameter::optional<
parameter::deduced<recovery_when<> >,
is_recovery_when<boost::mpl::_>
>,
parameter::optional<
parameter::deduced<recovery_how<> >,
is_recovery_how<boost::mpl::_>
>
> signature;
typedef typename signature::bind<Arg1,Arg2>::type args;
public:
typedef typename parameter::binding<
args,recovery_when<>,dsl::immediate<>
>::type recovery_when;
typedef typename parameter::binding<
args,recovery_how<>,dsl::fifo<>
>::type recovery_how;
private:
typedef parameter::parameters<
parameter::optional<
parameter::deduced<
detail::unmatched_arg
>,
mpl::not_<
mpl::or_<
is_recovery_when<boost::mpl::_>,
is_recovery_how<boost::mpl::_>
>
>
>
> unmatched_signature;
typedef typename unmatched_signature::bind<
Arg1,Arg2
>::type unmatched_args;
typedef typename parameter::binding<
unmatched_args,detail::unmatched_arg,
detail::unmatched_arg
>::type unmatched_arg_detected;
/* You have passed a type in the specification of a recover type that
* could not be interpreted as a valid argument.
*/
BOOST_STATIC_ASSERT((
is_same<unmatched_arg_detected,detail::unmatched_arg>::value));
};
</code>
There is a lot of syntactic boilerplate in the recover class which will be
repeated for each one of the & nodes on the DSL grammar.
I have defined a expr class which hides all this repetitive stuff. The
recover
class can then be defined as:
<code>
template <typename Arg1=parameter::void_, typename Arg2=parameter::void_>
struct recover : on_release_marker,
boost::dsl::expr<recover<>, mpl::vector<
boost::dsl::optional<recovery_when<>, is_recovery_when<mpl::_>,
immediate<> >,
boost::dsl::optional<recovery_how<>, is_recovery_how<mpl::_>, fifo<> >
>, mpl::vector<Arg1, Arg2> >
{};
</code>
I would like to know if there is an interest in such a expression, and if it
is the case if this could be added to the parameters library.
As the issue here is to transform an DSL expression to another DSL I
was wondering if the Boost.Proto which is now been review could help
to do this kind of transformations.
The expr.hpp file is attached. The class in not yet able to manage with a
variable number of parameters (up to 3). I would like to know if there
is a way to avoid preprocessor programming.
I have faced some problems when trying to avoid preprocessor programming.
The first one was doing the mapping from a vector of args to the
parameter::parameters::bind.
<code>
template <typename Signature, typename Args>
struct args;
template <typename Signature, typename Arg0>
struct args<Signature, mpl::vector<Arg0> > {
typedef typename Signature::template bind<Arg0>::type type;
};
template <typename Signature, typename Arg0, typename Arg1>
struct args<Signature, mpl::vector<Arg0, Arg1> > {
typedef typename Signature::template bind<Arg0, Arg1>::type type;
};
</code>
I don't know if there is a better way to do that, any hint is welcome.
Any way I think that it will be easier to adapt the
parameter::parameters::bind template to take a mpl sequence.
See the definition of bind in boost/parameter/parameters.hpp
<code>
template <
BOOST_PP_ENUM_BINARY_PARAMS(
BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT
)
>
struct bind
{
typedef typename aux::make_arg_list<
typename BOOST_PARAMETER_build_arg_list(
BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A
)::type
, deduced_list
, aux::tag_template_keyword_arg
>::type result;
typedef typename mpl::first<result>::type type;
};
</code>
The second problem concern the mapping from a vector to a
unmatched_signature, which is reduced to transform a mpl::vector to a
mpl::or_
<code>
template <typename Param0,typename Param1>
struct unmatched_signature<mpl::vector<Param0, Param1> >{
typedef parameter::parameters<
parameter::optional<
parameter::deduced<
detail::unmatched_arg
>,
mpl::not_<
mpl::or_<
typename Param0::pred,
typename Param1::pred
>
>
>
> type;
};
</code>
Is there something in boost that can simplify this mapping?
Best Regards
_______________________________________________
Vicente Juan Botet Escriba
_______________________________________________
LUID DSL grammar
_______________
luidg(
numeric_type(uint_type) ?
& on_overflow(
throw_on_error
| errno_on_error
| ignore_error
| user_error(user_function)
) ?
& on_release(
discard
| recover(
recover_when?
& recover_how?
)
) ?
& scope(
mono_threaded
| multi_threaded(locking? )
| multi_process(locking? )
) ?
& persistecy(
process(
void_pointer_type?
& allocator_type?
)
| kernel(
void_pointer_type?
& allocator_type?
& segment_manager_type?
)
| filesystem(
void_pointer_type?
& allocator_type?
& segment_manager_type?
)
) ?
& optimization (
speed
| space
) ?
& coherency (
ensure(bitset | set | ...)?
| ignore
) ?
)
recover_when (
immediate
| freeze
| delay(time_traits)
)
recover_how (
fifo
| undefined
)
locking(
internally(locking_traits)
| externally(mutex_type)
)
locking_traits (
thread_locking_traits
| process_locking_traits
| thread_recursive_locking_traits
| process_recursive_locking_traits
| ...
)
time_traits (
posix_time_traits
| ...
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk