#include #include #include #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() namespace proto = boost::proto; using proto::_; struct program_tag {}; template struct program_variable {}; template struct fragment_expr; template struct program_expr; struct slot { template slot(program_variable const &var, Map &map) : i_((*map.insert(std::make_pair(&var, map.size())).first).second) {} int i_; }; BOOST_TYPEOF_REGISTER_TYPE(slot) BOOST_TYPEOF_REGISTER_TYPE(program_tag) BOOST_TYPEOF_REGISTER_TEMPLATE(fragment_expr, (typename)) BOOST_TYPEOF_REGISTER_TEMPLATE(program_expr, (typename)) struct program_args : proto::or_< proto::terminal > , proto::address_of > > > {}; struct program_decl : proto::nary_expr > {}; struct program_rewrite; struct compile_program : proto::callable { template struct result; template struct result { typedef typename boost::add_reference::type>::type expr_type; typedef typename boost::result_of::type program_type; typedef program_expr type; }; template typename result::type operator ()(Expr const &expr) const { std::map state; typedef result result_; typename result_::program_type prog = program_rewrite()(expr, state); typename result_::type that = {prog, state}; return that; } }; struct program_rewrite : proto::or_< proto::when< proto::terminal > , proto::_make_terminal(slot(proto::_value, proto::_state)) > , proto::when< proto::terminal<_> , proto::_make_terminal(proto::_byval(proto::_value)) > , proto::nary_expr<_, proto::vararg > > {}; struct program_generator : proto::or_< proto::when< proto::subscript , compile_program(_) > , proto::otherwise< proto::pod_generator(_) > > {}; struct program_domain : proto::domain {}; struct get_slot : proto::callable { typedef int &result_type; int &operator ()(slot const &s, std::vector &args) const { return args[s.i_]; } }; struct program_eval : proto::or_< proto::when< proto::terminal , get_slot(proto::_value, proto::_state) > , proto::otherwise< proto::_default > > {}; template struct program_expr { // E is "Program(args...)[ program ]". It is a binary subscript // expression. BOOST_PROTO_BASIC_EXTENDS(E, program_expr, program_domain) // TODO: generate this signature from information on the LHS void operator ()(int &ra, int b) const { std::vector state(slots_.size(), 0); state[0] = ra; state[1] = b; program_eval()(proto::right(*this), state); ra = state[0]; } std::map slots_; }; template struct fragment_expr { BOOST_PROTO_EXTENDS(E, fragment_expr, program_domain) }; typedef fragment_expr >::type> int_; #define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ template \ typename boost::proto::result_of::make_expr::type const \ Program(A_const_ref_a(N)) \ { \ return proto::make_expr(ref_a(N)); \ } \ /**/ #include BOOST_PROTO_LOCAL_ITERATE() int main() { int_ a,b,c; BOOST_AUTO( p, (Program(&a,b) [c = b*2, a = c]) ); int ra = 0; p(ra, 4); assert(8 == ra); std::cout << ra << std::endl; }