Boost logo

Boost Users :

Subject: [Boost-users] [proto] folding a proto tree in reverse
From: Maurizio Vitale (maurizio.vitale_at_[hidden])
Date: 2009-08-29 18:02:50


I need to traverse a proto tree from right to left so that given the
statement:

        (a, b, c) = expr;

I can assign in order c then b and lastly a.

A fragment that does the order a,b,c (and work, but not very
efficiently, which is why I want to go the other way) is:

template<typename E>
struct assign_aux {
  assign_aux (const E& rhs) : m_rhs (rhs) {}
      
  typedef int result_type;
  template<typename T>
  int operator()(const T& t, int offset) const {
    int next_offset = offset - actual_width_transform () (t);
    int value = systemc_eval (m_rhs.range (offset,next_offset+1));

    const_cast<T&>(t) = value;
        
    return next_offset;
  }
  const E& m_rhs;
};

template <typename E>
struct assign<E, proto::tag::comma> {
  template<typename RHS>
  const E& doit (const E& e, const RHS& rhs) {
    int width = actual_width_transform () (e);
    fusion::fold(proto::flatten (const_cast<systemc_expression&>(e)), width-1, assign_aux<RHS> (rhs));
    return e;
  }
};

template<typename E>
const systemc_expression& operator = (const E& e) const {
  BOOST_MPL_ASSERT ((proto::matches<systemc_expression, lhs_systemc_grammar>));

  return assign<systemc_expression>().doit (*this, e);
  return *this;
}

I've tried to use fusion::reverse_view to invert the fusion sequence,
but failed. I also suspect that the resulting code wouldn't be as good
as it could be, which in my application is critical.

So I looked at alternatives and tried proto::reverse_fold_tree. Here's
my attempt:

struct assign_terminal : proto::callable {
  typedef int result_type;
  template<typename T, typename O, typename R>
  int
  operator () (T& t, O o, const R& r) const {
    int width = actual_width_transform () (t);
    const_cast<T&>(t) = r.range (1,0);

    return o+width;
  }
};

template <typename E>
struct assign<E, proto::tag::comma> {
  template<typename RHS>
  const E& doit (const E& e, const RHS& rhs) {
    proto::reverse_fold_tree<_, int() , assign_terminal (_, proto::_state, proto::_data)>() (e, rhs);
        
    return e;
  }
};

template<typename E>
const systemc_expression& operator = (const E& e) const {
  BOOST_MPL_ASSERT ((proto::matches<systemc_expression, lhs_systemc_grammar>));

  return assign<systemc_expression>().doit (*this, e);

  return *this;
}

But this doesn't seem to pass the data (rhs) to
assign_terminal::operator () (expr, state, data). There're really very
few examples on how to use proto::fold_tree and even fewer using the
data parameter, so I don't have much to go on.

Would anybody whose name is Eric tell me why I'm this stupid?

TIA,

        Maurizio


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net