Boost logo

Boost :

From: Maurizio Vitale (mav_at_[hidden])
Date: 2007-05-02 19:16:43


Here a smallish example. Ok for ARITY==2 and 6. Fails with ARITY==8 (I suspect anything above 6)
Best regards,

     Maurizio

#include <iostream>

#define ARITY 2

#if ARITY==2
#define NUMBER number<_,_>
#define NUMBER_TPL_DECL template<typename A, typename B>
#define NUMBER_TPL_INST number<A,B>
#define NUMBER_TPL_INST1 number<mpl::int_<0>,mpl::int_<0> >
#elif ARITY==6
#define BOOST_PROTO_MAX_ARITY 6
#define NUMBER number<_,_,_,_,_,_>
#define NUMBER_TPL_DECL template<typename A, typename B, typename C, typename D, typename E, typename F>
#define NUMBER_TPL_INST number<A,B,C,D,E,F>
#define NUMBER_TPL_INST1 number<mpl::int_<0>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0> >
#else
#define BOOST_PROTO_MAX_ARITY 8
#define NUMBER number<_,_,_,_,_,_,_,_>
#define NUMBER_TPL_DECL template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H>
#define NUMBER_TPL_INST number<A,B,C,D,E,F,G,H>
#define NUMBER_TPL_INST1 number<mpl::int_<0>,mpl::int_<0>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0>, mpl::int_<0> >
#endif

#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/context.hpp>
#include <boost/xpressive/proto/extends.hpp>
#include <boost/xpressive/proto/debug.hpp>
#include <boost/xpressive/proto/transform/arg.hpp>
#include <boost/xpressive/proto/transform/construct.hpp>
//#include <boost/xpressive/proto/transform/fold_to_list.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/typeof/std/ostream.hpp>

#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/vector.hpp>

#include <boost/test/unit_test.hpp>

namespace proto=boost::proto;
namespace mpl=boost::mpl;

struct my_domain : proto::domain<struct my_grammar> {};

template<typename> struct my_context;

template <typename Expr>
struct my_expr : proto::extends<Expr, my_expr<Expr>, my_domain> {
  typedef proto::extends<Expr, my_expr<Expr>, my_domain> base_type;

  my_expr (Expr const& expr = Expr()) : base_type (expr) {};

  using base_type::operator =;

  operator int () const {
    return static_cast<int>(proto::eval(*this, my_context<Expr> ()));
  }

  operator unsigned int () const {
    return static_cast<unsigned int>(proto::eval(*this, my_context<Expr> ()));
  }
};

NUMBER_TPL_DECL struct number;

NUMBER_TPL_DECL
std::ostream& operator << (std::ostream& os, const NUMBER_TPL_INST o);

NUMBER_TPL_DECL
struct number {
  friend std::ostream& operator << <> (std::ostream& os, const NUMBER_TPL_INST o);
  unsigned int m_data;
};

NUMBER_TPL_DECL
std::ostream& operator << (std::ostream& os, const NUMBER_TPL_INST n) { os << "~U~" << n.m_data << "~"; return os; }

using proto::_;

struct my_grammar : proto::or_ <
  proto::terminal< NUMBER > ,
  proto::terminal<int>,
  proto::terminal<unsigned int>,
  proto::unary_expr<proto::_, my_grammar> ,
  proto::binary_expr<proto::_, my_grammar, my_grammar>
>
{};

namespace boost { namespace proto {
  template<typename Expr>
  struct generate<my_domain, Expr> {
    typedef my_expr<Expr> type;
      
    static type make (Expr const& expr) {
      return type (expr);
    }
  };
} } // end namespace boost::proto

template<typename Expr>
struct my_context : proto::callable_context<const my_context<Expr> > {

  typedef unsigned int result_type;

  NUMBER_TPL_DECL
  unsigned int operator () (proto::tag::terminal, NUMBER_TPL_INST n) const { return n.m_data; }
};

template<int N>
struct my_int : my_expr<typename proto::terminal< NUMBER_TPL_INST1 >::type>
{
  typedef NUMBER_TPL_INST1 number_type;
  typedef my_expr<typename proto::terminal<number_type>::type> expr_type;

  my_int () {}
  my_int (int i) : expr_type (expr_type::type::make (i)) {}

  template<typename Expr>
  my_int& operator = (const my_expr<Expr>& e) {
    proto::arg (*this).m_data = static_cast<int>(proto::eval(e, my_context<Expr> ()));
    return *this;
  }

  template<typename T>
  my_int& operator = (T value) {
    proto::arg (*this).m_data = value;
    return *this;
  }

  friend std::ostream& operator << (std::ostream& os, const my_int n) { os << "my_int<" << proto::arg(n).m_data << ">"; return os; }
};

#include <boost/test/included/unit_test_framework.hpp>
using namespace boost::unit_test;

template<typename Expr>
void test (const Expr& expr) {
  std::cout << "Expression:\n";
    display_expr (expr);
  if (proto::matches<Expr, my_grammar>::value)
    std::cout << "matches my grammar\n\n";
  else
    std::cout << "doesn't matches my grammar\n\n";
}

void misc_test () {
  my_int<6> i4(-22);

  int i;
  unsigned int j;

  i4 = 5;
  i4 = 5*i4;

  i = i4/i4+4;
  j = i4/i4;

  display_expr (i4/i4+4);

  std::cout << "my_expr, -22/7 =" << i4 << "\n";
  // std::cout << "my_expr, -22/7 =" << i4*i4 << "\n"; // ambiguous
  std::cout << "my_expr, -22/7 [assigned to int]=" << i << "\n";
  std::cout << "my_expr, -22/7 [assigned to unsigned int]=" << j << "\n";
}

test_suite*
init_unit_test_suite (int, char**)
{
  test_suite* test= BOOST_TEST_SUITE( "boost::proto sandbox" );

  test->add (BOOST_TEST_CASE (&misc_test));

  return test;
}


/// Local Variables:
/// mode:c++
/// comment-column:80
/// fill-column:160
/// compilation-read-command:nil
/// compile-command:"g++ -I. -ope1 pe1.cpp"
/// End:


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk