Hi All,

I'm experimenting with Proto to build a DSEL that operates on geometric vectors. I'm trying to write a transform that would take an assign expression and unroll it component wise. For instance, I want to replace

    p = q + r;

by

    p[0] = q[0] + r[0],
    p[1] = q[1] + r[1],
    ...,
    p[N] = q[N] + r[N],
    p;

So far I have been able to *mostly* make it work by making a transform template unroll_vector_expr that recursively unrolls the expression for each vector component, in conjunction with a distribute_subscript transform (which I shamelessly took from Eric's article on C++Next).

I don't seem to understand whats the rationale for the 'parameters' used with `boost::result_of` and `result_of::make_expr`. The documentation, examples and internal code seem to mix `Expr`, `impl::expr` and `impl::expr_param`. I'm not sure what should I be using and when so that the `result_type` matches the actual result type. Currently I made it work by trial an error, by examining the error messages and fixing the `const` and `&` discrepancies (code for the transform attached). However, as soon as I deep copy the expression the terminals are no longer hold by reference and my code fails. Which incidentally brings me to my second question...

When deep copying an expression the 'identity' of the terminals is lost, as each reference to a terminal results in a new hold by value terminal. Consequently, expressions with side effects (like assignment) no longer evaluate correctly. Is it possible to customize the expression 'semantics' so that when a deep copy is made terminals are copied only the first time they are seen, and subsequent uses refer to that first copy? Or should I be taking a completely different approach, perhaps by leaving operations with side effects outside of the grammar?

Thanks in advance for any help, and sorry if any of my questions is trivial or erroneous.

Agustín K-ballo Bergé.-
http://fusionfenix.com
struct distribute_subscript
    : or_<
        scalar_grammar
        , when<
            vector_literal
            , _make_subscript( _, _state )
        >
        , plus< distribute_subscript, distribute_subscript >
        , minus< distribute_subscript, distribute_subscript >
        , multiplies< distribute_subscript, distribute_subscript >
        , divides< distribute_subscript, distribute_subscript >
        , assign< distribute_subscript, distribute_subscript >
    >
{};
        
template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c;
        
template< std::size_t N >
struct unroll_vector_expr_c< 0, N >
    : transform< unroll_vector_expr_c< 0, N > >
{
    template< typename Expr, typename State, typename Data >
    struct impl
        : transform_impl< Expr, State, Data >
    {
        typedef
            typename result_of::make_expr<
                tag::comma
                , typename boost::result_of<
                    unroll_vector_expr_c< 1, N >(
                        typename impl::expr
                    )
                >::type
                , typename impl::state
            >::type
            result_type;

        result_type operator ()(
            typename impl::expr_param expr
            , typename impl::state_param state
            , typename impl::data_param data
        ) const
        {
            return
                make_expr< tag::comma >(
                    unroll_vector_expr_c< 1, N >()(
                        expr
                    )
                    , state
                );
        }
    };
};

template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c
    : transform< unroll_vector_expr_c< I, N > >
{
    template< typename Expr, typename State, typename Data >
    struct impl
        : transform_impl< Expr, State, Data >
    {
        typedef
            typename result_of::make_expr<
                tag::comma
                , typename boost::result_of<
                    distribute_subscript(
                        typename impl::expr_param
                        , typename result_of::make_expr<
                            tag::terminal
                            , boost::mpl::size_t< I - 1 >
                        >::type const&
                    )
                >::type
                , typename boost::result_of<
                    unroll_vector_expr_c< I + 1, N >(
                        typename impl::expr_param
                    )
                >::type
            >::type
            result_type;

        result_type operator ()(
            typename impl::expr_param expr
            , typename impl::state_param state
            , typename impl::data_param data
        ) const
        {
            return
                make_expr< tag::comma >(
                    distribute_subscript()(
                        expr
                        , make_expr< tag::terminal >( 
                            boost::mpl::size_t< I - 1 >()
                        )
                    )
                    , unroll_vector_expr_c< I + 1, N >() (
                        expr
                    )
                );
        }
    };
};

template< std::size_t N >
struct unroll_vector_expr_c< N, N >
    : transform< unroll_vector_expr_c< N, N > >
{
    template< typename Expr, typename State, typename Data >
    struct impl
        : transform_impl< Expr, State, Data >
    {
        typedef
            typename boost::result_of<
                distribute_subscript(
                    typename impl::expr_param
                    , typename result_of::make_expr<
                        tag::terminal
                        , boost::mpl::size_t< N - 1 >
                    >::type const&
                )
            >::type
            result_type;

        result_type operator ()(
            typename impl::expr_param expr
            , typename impl::state_param state
            , typename impl::data_param data
        ) const
        {
            return
                distribute_subscript()(
                    expr
                    , make_expr< tag::terminal >( 
                        boost::mpl::size_t< N - 1 >()
                    )
                );
        }
    };
};

struct unroll_vector_expr
    : transform< unroll_vector_expr >
{
    template< typename Expr, typename State, typename Data >
    struct impl
        : transform_impl< Expr, State, Data >
    {
        typedef
            typename dimension<
                typename boost::remove_reference<
                    typename boost::result_of<
                        _value( State )
                    >::type
                >::type
            >::type
            dimension;

        typedef
            typename boost::result_of<
                unroll_vector_expr_c< 0, dimension::value >(
                    typename impl::expr_param
                    , typename impl::state_param
                )
            >::type
            result_type;

        result_type operator ()(
            typename impl::expr_param expr
            , typename impl::state_param state
            , typename impl::data_param data
        ) const
        {
            return
                unroll_vector_expr_c< 0, dimension::value >()(
                    expr
                    , state
                );
        }
    };
};
_______________________________________________
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto

Reply via email to