Boost logo

Proto :

Subject: Re: [proto] Recursive functions in a mini language
From: Eric Niebler (eric_at_[hidden])
Date: 2010-08-06 19:53:31


On 8/6/2010 7:29 PM, Manjunath Kudlur wrote:
> I had asked boost-users for suggestions on how to define mutually
> recursive functions in a DSEL. Here is the original thread.
> http://lists.boost.org/boost-users/2010/07/60488.php
>
> I am thinking about a solution inspired by Spirit subrules, that looks
> as follows :
>
> #include <boost/fusion/container/vector.hpp>
> #include <boost/proto/proto.hpp>
> #include <vector>
> #include <iostream>
>
> using namespace std;
>
> namespace mpl=boost::mpl;
> namespace proto=boost::proto;
> namespace fusion=boost::fusion;
>
> template<typename>
> struct arg{};
>
> proto::terminal<arg<mpl::int_<0> > >::type const _1 = {{}};
> proto::terminal<arg<mpl::int_<1> > >::type const _2 = {{}};
> proto::terminal<arg<mpl::int_<2> > >::type const _3 = {{}};
>
> template<typename>
> struct func {};
>
> #define DECLARE_FUNC(n, x) \
> proto::terminal<func<mpl::int_<n> > >::type const x = {{}};
>
> struct _declare_module {};
> proto::terminal<_declare_module>::type const declare_module = {{}};
>
> struct _map {};
> proto::terminal<_map>::type const map = {{}};
>
> int main()
> {
> int i = 41;
>
> DECLARE_FUNC(0, det_inverse);
> DECLARE_FUNC(1, negmul);
> DECLARE_FUNC(2, vmul);
> DECLARE_FUNC(3, vadd);
> DECLARE_FUNC(4, precondition);
> DECLARE_FUNC(5, fib);
>
> BOOST_AUTO(preconditioner,(

Careful here. You want BOOST_PROTO_AUTO, or else put these things in a
domain defined such that intermediate expressions are not held by
reference. Or else, make declare_module an instance of a type with an
overloaded operator[] that deep-copies it's rhs to avoid all lifetime
issues. Proto expression templates are make entirely of temporary
object. Here be dragons.

> declare_module[
> vadd = _1+_2,
> negmul = -vmul(_1,_2),
> det_inverse = 1/(_1*_3-_2*_2),
> vmul = _1*_2,
> fib = fib(_1-1) + fib(_1-2),
> precondition = vmul(map(det_inverse, _1,_2,_3), _1)
> ]
> ));
>
> std::vector<int> a, b, c;
>
> preconditioner->*precondition(a,b,c);
>
> proto::display_expr((preconditioner->*precondition)(a,b,c));
>
> return 0;
> }
>
> Basically, the user is forced to declare all the functions using
> unique identifiers beforehand. He then declares a module containing
> the definitions of the function. He can then call the functions as
> module->*func(...). I imagine this can be made to work by parsing the
> module and executing the correct function based on the type. I would
> like to ask people's opinions on this forum. Do you guys see any
> problems? Are there more elegant approaches?

Let me understand. Your goal is to have something like spirit subrules,
except the subrules are like ordinary functions, and the functions
should be invokable by name, is that right? Spirit subrules are neat and
tidy and efficient because they are hidden away inside a grammar. But
that's not your case. Hence the need for the module and the operator->*.
Did I get that right?

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Proto list run by eric at boostpro.com