|
Proto : |
Subject: Re: [proto] Thoughts on traversing proto expressions and reusing grammar
From: joel falcou (joel.falcou_at_[hidden])
Date: 2010-10-20 15:24:49
I took the liberty to peruse this design to redesign nt2 computation
evaluation.
As nt2 provides a lot of functions on its various DSL terminal, we're
seeking
some solution that scale - as havign 200+ case<Tag> specialization is a
bit unpractical.
Soooo, despite ppl telling me dispacthing on tag cause loss of hairs and
other
bad stuff, I came to the conclusion that I could use both part :
- dispatch on tag for most things
- dispatch on rules for local, AST based optimisation (turnign a*b+c
into madd, or similar stuff)
Using thomas code and my own functor class , i designed a new
computation transform but it fails
to dispatch. Before goign further, recall that nt2::functors::functor ae
generalized polymorphic function
object follwoing the result_of protocol. For a given tag, functor<Tag>
perform the proper operation
on its arguments by forwarding the call to a call<Tag,Category> class,
Category being something
discriminating the various type i want to differentiate.
So here's the transform (reuing algorithm etc from previosu post)
template<class Rule, class Actions, class Dispatch = Rule>
struct bind
: boost::proto::when< Rule
, typename Actions::template action<Dispatch>
>
{};
template<class Actions>
struct compiler : boost::proto::switch_<Actions> {};
//////////////////////////////////////////////////////////////////////////////
// computation action
//////////////////////////////////////////////////////////////////////////////
template<class Locality>
struct compute
{
template<class Tag>
struct case_
: bind< boost::proto::_
, compute
, boost::proto::tag_of<boost::proto::_>()
>
{};
//////////////////////////////////////////////////////////////////////////////
// Primary case captures any tag into appropriate functor and call it
// recursively using unpack
//////////////////////////////////////////////////////////////////////////////
template<class Case,class Dummy=void>
struct action
: boost::proto::
unpack< boost::proto::
call<functors::functor<Case,Locality>(compiler<compute>)>
>
{};
};
//////////////////////////////////////////////////////////////////////////////
// Captures terminal and forward their value, state and data to the functor
//////////////////////////////////////////////////////////////////////////////
template<class Locality> template<class Dummy>
struct compute<Locality>::action<functors::terminal_,Dummy>
: boost::proto::
call<functors::functor< functors::terminal_
, Locality
> ( boost::proto::_value
, boost::proto::_state
, boost::proto::_data
)
>
{};
} }
namespace boost { namespace proto
{
template<class Actions>
struct is_callable<nt2::dsl::compiler<Actions> > : boost::mpl::true_ {};
} }
Alas, the compiler is not happy and complain about an incompelte
proto::apply_transform type:
/usr/local/include/boost-1_44/boost/proto/transform/impl.hpp:96: error:
invalid use of incomplete type struct
boost::proto::detail::apply_transform<boost::proto::call<nt2::functors::functor<boost::proto::tag_of<boost::proto::_>(),
nt2::simd::native<float, nt2::tag::sse_>
>(nt2::dsl::compiler<nt2::dsl::compute<nt2::simd::native<float,
nt2::tag::sse_> > >)>(nt2::simd::pack<float, 4u,
boost::proto::exprns_::is_proto_expr>&, const
nt2::simd::expression<boost::proto::exprns_::expr<boost::proto::tag::terminal,
boost::proto::argsns_::term<const int&>, 0l>, float, mpl_::size_t<4u>,
boost::proto::exprns_::is_proto_expr>&, int, int)>
/usr/local/include/boost-1_44/boost/proto/transform/impl.hpp:75: error:
declaration of struct
boost::proto::detail::apply_transform<boost::proto::call<nt2::functors::functor<boost::proto::tag_of<boost::proto::_>(),
nt2::simd::native<float, nt2::tag::sse_>
>(nt2::dsl::compiler<nt2::dsl::compute<nt2::simd::native<float,
nt2::tag::sse_> > >)>(nt2::simd::pack<float, 4u,
boost::proto::exprns_::is_proto_expr>&, const
nt2::simd::expression<boost::proto::exprns_::expr<boost::proto::tag::terminal,
boost::proto::argsns_::term<const int&>, 0l>, float, mpl_::size_t<4u>,
boost::proto::exprns_::is_proto_expr>&, int, int)>
Thomas and me tried to fix it but not to avail ...
Before bashing me, I strongly push the fact that tag dispatching is a
valid use-case, unless
anyone can provide me with such a scalable solution without ressorting
to this.
As for a small reproductible example, it's currently a bit hard. You can
look at the code
int he nT2 github repository (github.com/jfalcou/nt2).
Proto list run by eric at boostpro.com