// Copyright (C) 2016-2018 T. Zachary Laine // // 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 #include template using term = boost::yap::terminal; template using ref = boost::yap::expression_ref; namespace yap = boost::yap; namespace bh = boost::hana; namespace user { struct number { double value; }; struct eval_xform { auto operator()(yap::expr_tag, number const & n) { return n; } template decltype(auto) operator()( yap::expression> const & expr) { number const n = transform(yap::value(expr), *this); return number{-n.value}; } template decltype(auto) operator()(yap::expression< yap::expr_kind::plus, bh::tuple> const & expr) { number const lhs = transform(yap::left(expr), *this); number const rhs = transform(yap::right(expr), *this); return number{lhs.value + rhs.value}; } }; } template auto make_ref(Expr && expr) { using type = yap::detail::operand_type_t; return yap::detail::make_operand{}(static_cast(expr)); } int test_main(int, char * []) { { { term a{{1.0}}; { user::number result = transform(a, user::eval_xform{}); BOOST_CHECK(result.value == 1); } { user::number result = transform(make_ref(a), user::eval_xform{}); BOOST_CHECK(result.value == 1); } { user::number result = transform(-a, user::eval_xform{}); BOOST_CHECK(result.value == -1); } { auto expr = make_ref(a); user::number result = transform(-expr, user::eval_xform{}); BOOST_CHECK(result.value == -1); } { auto expr = -a; user::number result = transform(expr, user::eval_xform{}); BOOST_CHECK(result.value == -1); } { auto expr1 = make_ref(a); auto expr2 = make_ref(expr1); user::number result = transform(expr2, user::eval_xform{}); BOOST_CHECK(result.value == 1); } { auto expr1 = -a; auto expr2 = make_ref(expr1); user::number result = transform(expr2, user::eval_xform{}); BOOST_CHECK(result.value == -1); } { auto expr1 = make_ref(a); auto expr2 = -expr1; user::number result = transform(expr2, user::eval_xform{}); BOOST_CHECK(result.value == -1); } { auto expr1 = a; auto expr2 = make_ref(expr1); auto expr3 = make_ref(expr2); user::number result = transform(expr3, user::eval_xform{}); BOOST_CHECK(result.value == 1); } { auto expr1 = -a; auto expr2 = make_ref(expr1); auto expr3 = make_ref(expr2); user::number result = transform(expr3, user::eval_xform{}); BOOST_CHECK(result.value == -1); } { auto expr1 = make_ref(a); auto expr2 = -expr1; auto expr3 = make_ref(expr2); user::number result = transform(expr3, user::eval_xform{}); BOOST_CHECK(result.value == -1); } { auto expr1 = make_ref(a); auto expr2 = make_ref(expr1); auto expr3 = -expr2; user::number result = transform(expr3, user::eval_xform{}); BOOST_CHECK(result.value == -1); } } { user::number result = transform(-term{{1.0}}, user::eval_xform{}); BOOST_CHECK(result.value == -1); } } { term a{{1.0}}; term x{{41.0}}; { user::number result = transform(a + x, user::eval_xform{}); BOOST_CHECK(result.value == 42); } { user::number result = transform(make_ref(a) + make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == 42); } { user::number result = transform(make_ref(a) + x, user::eval_xform{}); BOOST_CHECK(result.value == 42); } { user::number result = transform(a + make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == 42); } { user::number result = transform(a + x, user::eval_xform{}); BOOST_CHECK(result.value == 42); } { user::number result = transform(-make_ref(a) + make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == 40); } { user::number result = transform(-make_ref(a) + x, user::eval_xform{}); BOOST_CHECK(result.value == 40); } { user::number result = transform(-a + make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == 40); } { user::number result = transform(-a + x, user::eval_xform{}); BOOST_CHECK(result.value == 40); } { user::number result = transform(make_ref(a) + -make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == -40); } { user::number result = transform(make_ref(a) + -x, user::eval_xform{}); BOOST_CHECK(result.value == -40); } { user::number result = transform(a + -make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == -40); } { user::number result = transform(a + -x, user::eval_xform{}); BOOST_CHECK(result.value == -40); } { user::number result = transform(-make_ref(a) + -make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == -42); } { user::number result = transform(-make_ref(a) + -x, user::eval_xform{}); BOOST_CHECK(result.value == -42); } { user::number result = transform(-a + -make_ref(x), user::eval_xform{}); BOOST_CHECK(result.value == -42); } { user::number result = transform(-a + -x, user::eval_xform{}); BOOST_CHECK(result.value == -42); } } return 0; }