123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- ///////////////////////////////////////////////////////////////////////////////
- // proto::make_expr.hpp
- //
- // Copyright 2008 Eric Niebler. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #include <sstream>
- #include <boost/proto/core.hpp>
- #include <boost/proto/transform.hpp>
- #include <boost/utility/addressof.hpp>
- #include <boost/fusion/tuple.hpp>
- #include <boost/test/unit_test.hpp>
- namespace fusion = boost::fusion;
- namespace proto = boost::proto;
- template<typename E> struct ewrap;
- struct mydomain
- : proto::domain<proto::generator<ewrap> >
- {};
- template<typename E> struct ewrap
- : proto::extends<E, ewrap<E>, mydomain>
- {
- explicit ewrap(E const &e = E())
- : proto::extends<E, ewrap<E>, mydomain>(e)
- {}
- };
- void test_make_expr()
- {
- int i = 42;
- proto::terminal<int>::type t1 = proto::make_expr<proto::tag::terminal>(1);
- proto::terminal<int>::type t2 = proto::make_expr<proto::tag::terminal>(i);
- proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::make_expr<proto::tag::unary_plus>(1);
- proto::unary_plus<proto::terminal<int>::type>::type p2 = proto::make_expr<proto::tag::unary_plus>(i);
- BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::unary_plus
- , proto::list1<
- ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p3_type;
- p3_type p3 = proto::make_expr<proto::tag::unary_plus, mydomain>(i);
- BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::plus
- , proto::list2<
- p3_type
- , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p4_type;
- p4_type p4 = proto::make_expr<proto::tag::plus>(p3, 0);
- BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
- }
- void test_make_expr_ref()
- {
- int i = 42;
- int const ci = 84;
- proto::terminal<int const &>::type t1 = proto::make_expr<proto::tag::terminal>(boost::cref(ci));
- proto::terminal<int &>::type t2 = proto::make_expr<proto::tag::terminal>(boost::ref(i));
- BOOST_CHECK_EQUAL(&i, &proto::value(t2));
- proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::make_expr<proto::tag::unary_plus>(boost::cref(ci));
- proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::make_expr<proto::tag::unary_plus>(boost::ref(i));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::unary_plus
- , proto::list1<
- ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
- >
- >
- >
- p3_type;
- p3_type p3 = proto::make_expr<proto::tag::unary_plus, mydomain>(boost::ref(i));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::plus
- , proto::list2<
- p3_type &
- , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p4_type;
- p4_type p4 = proto::make_expr<proto::tag::plus>(boost::ref(p3), 0);
- BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
- }
- void test_make_expr_functional()
- {
- int i = 42;
- proto::terminal<int>::type t1 = proto::functional::make_expr<proto::tag::terminal>()(1);
- proto::terminal<int>::type t2 = proto::functional::make_expr<proto::tag::terminal>()(i);
- proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::functional::make_expr<proto::tag::unary_plus>()(1);
- proto::unary_plus<proto::terminal<int>::type>::type p2 = proto::functional::make_expr<proto::tag::unary_plus>()(i);
- BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::unary_plus
- , proto::list1<
- ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p3_type;
- p3_type p3 = proto::functional::make_expr<proto::tag::unary_plus, mydomain>()(i);
- BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::plus
- , proto::list2<
- p3_type
- , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p4_type;
- p4_type p4 = proto::functional::make_expr<proto::tag::plus>()(p3, 0);
- }
- void test_make_expr_functional_ref()
- {
- int i = 42;
- int const ci = 84;
- proto::terminal<int const &>::type t1 = proto::functional::make_expr<proto::tag::terminal>()(boost::cref(ci));
- proto::terminal<int &>::type t2 = proto::functional::make_expr<proto::tag::terminal>()(boost::ref(i));
- BOOST_CHECK_EQUAL(&i, &proto::value(t2));
- proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::functional::make_expr<proto::tag::unary_plus>()(boost::cref(ci));
- proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::functional::make_expr<proto::tag::unary_plus>()(boost::ref(i));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::unary_plus
- , proto::list1<
- ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
- >
- >
- >
- p3_type;
- p3_type p3 = proto::functional::make_expr<proto::tag::unary_plus, mydomain>()(boost::ref(i));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::plus
- , proto::list2<
- p3_type &
- , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p4_type;
- p4_type p4 = proto::functional::make_expr<proto::tag::plus>()(boost::ref(p3), 0);
- BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
- }
- void test_unpack_expr()
- {
- int i = 42;
- proto::terminal<int>::type t1 = proto::unpack_expr<proto::tag::terminal>(fusion::make_tuple(1));
- proto::terminal<int &>::type t2 = proto::unpack_expr<proto::tag::terminal>(fusion::make_tuple(boost::ref(i)));
- proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::unpack_expr<proto::tag::unary_plus>(fusion::make_tuple(1));
- proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::unpack_expr<proto::tag::unary_plus>(fusion::make_tuple(boost::ref(i)));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::unary_plus
- , proto::list1<
- ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
- >
- >
- >
- p3_type;
- p3_type p3 = proto::unpack_expr<proto::tag::unary_plus, mydomain>(fusion::make_tuple(boost::ref(i)));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::plus
- , proto::list2<
- p3_type &
- , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p4_type;
- p4_type p4 = proto::unpack_expr<proto::tag::plus>(fusion::make_tuple(boost::ref(p3), 0));
- BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
- }
- void test_unpack_expr_functional()
- {
- int i = 42;
- proto::terminal<int>::type t1 = proto::functional::unpack_expr<proto::tag::terminal>()(fusion::make_tuple(1));
- proto::terminal<int &>::type t2 = proto::functional::unpack_expr<proto::tag::terminal>()(fusion::make_tuple(boost::ref(i)));
- proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::functional::unpack_expr<proto::tag::unary_plus>()(fusion::make_tuple(1));
- proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::functional::unpack_expr<proto::tag::unary_plus>()(fusion::make_tuple(boost::ref(i)));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::unary_plus
- , proto::list1<
- ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
- >
- >
- >
- p3_type;
- p3_type p3 = proto::functional::unpack_expr<proto::tag::unary_plus, mydomain>()(fusion::make_tuple(boost::ref(i)));
- BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
- typedef
- ewrap<
- proto::basic_expr<
- proto::tag::plus
- , proto::list2<
- p3_type &
- , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
- >
- >
- >
- p4_type;
- p4_type p4 = proto::functional::unpack_expr<proto::tag::plus>()(fusion::make_tuple(boost::ref(p3), 0));
- BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
- }
- #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
- #define _byref(x) call<proto::_byref(x)>
- #define _byval(x) call<proto::_byval(x)>
- #define Minus(x) proto::call<Minus(x)>
- #endif
- // Turn all terminals held by reference into ones held by value
- struct ByVal
- : proto::or_<
- proto::when<proto::terminal<proto::_>, proto::_make_terminal(proto::_byval(proto::_value))>
- , proto::when<proto::nary_expr<proto::_, proto::vararg<ByVal> > >
- >
- {};
- // Turn all terminals held by value into ones held by reference (not safe in general)
- struct ByRef
- : proto::or_<
- proto::when<proto::terminal<proto::_>, proto::_make_terminal(proto::_byref(proto::_value))>
- , proto::when<proto::nary_expr<proto::_, proto::vararg<ByRef> > >
- >
- {};
- // turn all proto::plus nodes to minus nodes:
- struct Minus
- : proto::or_<
- proto::when<proto::terminal<proto::_> >
- , proto::when<proto::plus<Minus, Minus>, proto::_make_minus(Minus(proto::_left), Minus(proto::_right)) >
- >
- {};
- struct Square
- : proto::or_<
- // Not creating new proto::terminal nodes here,
- // so hold the existing terminals by reference:
- proto::when<proto::terminal<proto::_>, proto::_make_multiplies(proto::_, proto::_)>
- , proto::when<proto::plus<Square, Square> >
- >
- {};
- #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
- #undef _byref
- #undef _byval
- #undef Minus
- #endif
- void test_make_expr_transform()
- {
- proto::plus<
- proto::terminal<int>::type
- , proto::terminal<int>::type
- >::type t1 = ByVal()(proto::as_expr(1) + 1);
- proto::plus<
- proto::terminal<int const &>::type
- , proto::terminal<int const &>::type
- >::type t2 = ByRef()(proto::as_expr(1) + 1);
- proto::minus<
- proto::terminal<int>::type const &
- , proto::terminal<int const &>::type const &
- >::type t3 = Minus()(proto::as_expr(1) + 1);
- proto::plus<
- proto::multiplies<proto::terminal<int>::type const &, proto::terminal<int>::type const &>::type
- , proto::multiplies<proto::terminal<int const &>::type const &, proto::terminal<int const &>::type const &>::type
- >::type t4 = Square()(proto::as_expr(1) + 1);
- }
- struct length_impl {};
- struct dot_impl {};
- proto::terminal<length_impl>::type const length = {{}};
- proto::terminal<dot_impl>::type const dot = {{}};
- // work around msvc bugs...
- #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
- #define _byref(a) call<proto::_byref(a)>
- #define _byval(a) call<proto::_byval(a)>
- #define _child1(a) call<proto::_child1(a)>
- #define _make_terminal(a) call<proto::_make_terminal(a)>
- #define _make_function(a,b,c) call<proto::_make_function(a,b,c)>
- #define dot_impl() proto::make<dot_impl()>
- #endif
- // convert length(a) < length(b) to dot(a,a) < dot(b,b)
- struct Convert
- : proto::when<
- proto::less<
- proto::function<proto::terminal<length_impl>, proto::_>
- , proto::function<proto::terminal<length_impl>, proto::_>
- >
- , proto::_make_less(
- proto::_make_function(
- proto::_make_terminal(dot_impl())
- , proto::_child1(proto::_child0)
- , proto::_child1(proto::_child0)
- )
- , proto::_make_function(
- proto::_make_terminal(dot_impl())
- , proto::_child1(proto::_child1)
- , proto::_child1(proto::_child1)
- )
- )
- >
- {};
- template<typename Expr>
- void test_make_expr_transform2_test(Expr const &expr)
- {
- void const *addr1 = boost::addressof(proto::child_c<1>(proto::child_c<0>(expr)));
- void const *addr2 = boost::addressof(proto::child_c<1>(proto::child_c<0>(Convert()(expr))));
- BOOST_CHECK_EQUAL(addr1, addr2);
- BOOST_CHECK_EQUAL(1, proto::value(proto::child_c<1>(proto::child_c<0>(expr))));
- BOOST_CHECK_EQUAL(1, proto::value(proto::child_c<1>(proto::child_c<0>(Convert()(expr)))));
- }
- void test_make_expr_transform2()
- {
- test_make_expr_transform2_test(length(1) < length(2));
- }
- #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
- #undef _byref
- #undef _byval
- #undef _child1
- #undef _make_terminal
- #undef _make_function
- #undef dot_impl
- #endif
- using namespace boost::unit_test;
- ///////////////////////////////////////////////////////////////////////////////
- // init_unit_test_suite
- //
- test_suite* init_unit_test_suite( int argc, char* argv[] )
- {
- test_suite *test = BOOST_TEST_SUITE("test proto::make_expr, proto::unpack_expr and friends");
- test->add(BOOST_TEST_CASE(&test_make_expr));
- test->add(BOOST_TEST_CASE(&test_make_expr_ref));
- test->add(BOOST_TEST_CASE(&test_make_expr_functional));
- test->add(BOOST_TEST_CASE(&test_make_expr_functional_ref));
- test->add(BOOST_TEST_CASE(&test_unpack_expr));
- test->add(BOOST_TEST_CASE(&test_unpack_expr_functional));
- test->add(BOOST_TEST_CASE(&test_make_expr_transform));
- test->add(BOOST_TEST_CASE(&test_make_expr_transform2));
- return test;
- }
|