diff options
Diffstat (limited to 'src/boost/libs/yap/test')
45 files changed, 7020 insertions, 0 deletions
diff --git a/src/boost/libs/yap/test/CMakeLists.txt b/src/boost/libs/yap/test/CMakeLists.txt new file mode 100644 index 000000000..5ba83f2a5 --- /dev/null +++ b/src/boost/libs/yap/test/CMakeLists.txt @@ -0,0 +1,132 @@ +include_directories(${CMAKE_HOME_DIRECTORY}) + +include(CTest) + +enable_testing() + +add_custom_target(yap_check COMMAND ${CMAKE_CTEST_COMMAND} -VV -C ${CMAKE_CFG_INTDIR}) +if (NOT TARGET check) + add_custom_target(check DEPENDS yap_check) +else() + add_dependencies(check yap_check) +endif() + +set(coverage_gcda_files) + +macro(add_test_executable name) + add_executable(${name} ${name}.cpp) + target_link_libraries(${name} yap) + target_compile_definitions(${name} PRIVATE BOOST_NO_AUTO_PTR) + add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name}) + if (clang_on_linux) + target_link_libraries(${name} c++) + endif () + list(APPEND coverage_gcda_files ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${name}.dir/${name}.cpp.gcda) +endmacro() + +add_test_executable(deref) +add_test_executable(value) +add_test_executable(left) +add_test_executable(right) +add_test_executable(print) +add_test_executable(default_eval) +add_test_executable(user_expression_transform_1) +add_test_executable(user_expression_transform_2) +add_test_executable(placeholder_eval) +add_test_executable(call_expr) +add_test_executable(reference_returns) +add_test_executable(depth_stress_test_left) +add_test_executable(depth_stress_test_right) +add_test_executable(lazy_vector_alloc_test) +add_test_executable(vector_alloc_test) +add_test_executable(operators_unary) +add_test_executable(comma) +add_test_executable(if_else) +add_test_executable(expression_function) +add_test_executable(transform) +add_test_executable(supplied_transforms) + +add_executable( + compile_tests + compile_tests_main.cpp + compile_is_expr.cpp + compile_const_term.cpp + compile_placeholders.cpp + compile_term_plus_expr.cpp + compile_term_plus_term.cpp + compile_term_plus_x.cpp + compile_x_plus_term.cpp + compile_term_plus_x_this_ref_overloads.cpp + compile_const_term.cpp + compile_move_only_types.cpp + compile_user_macros.cpp +) +target_link_libraries(compile_tests yap) +if (clang_on_linux) + target_link_libraries(compile_tests c++) +endif () + +function(add_compile_fail_test name) + try_compile( + compiles + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp + COMPILE_DEFINITIONS + ${std_flag} -I${Boost_INCLUDE_DIRS} -I${CMAKE_SOURCE_DIR}/include + OUTPUT_VARIABLE foo + ) + #message("foo=${foo}") + if (compiles) + message(FATAL_ERROR "Compile-fail test ${name} does not fail to compile.") + endif () +endfunction() + +add_compile_fail_test(fail_transform) +add_compile_fail_test(fail_get) +add_compile_fail_test(fail_left) +add_compile_fail_test(fail_right) +add_compile_fail_test(fail_cond) +add_compile_fail_test(fail_then) +add_compile_fail_test(fail_else) +add_compile_fail_test(fail_callable) +add_compile_fail_test(fail_argument) +add_compile_fail_test(fail_make_expression) +add_compile_fail_test(fail_make_terminal) + +if (BUILD_COVERAGE AND UNIX) + if (APPLE) + add_custom_target( + coverage + rm -rf ${coverage_gcda_files} lcov-all.info lcov.info output + COMMAND + ${CMAKE_CTEST_COMMAND} -VV -C ${CMAKE_CFG_INTDIR} + COMMAND + cd ${CMAKE_BINARY_DIR} + COMMAND + llvm-cov gcov -f -b ${coverage_gcda_files} + COMMAND + lcov --directory . --base-directory . --gcov-tool ${CMAKE_SOURCE_DIR}/llvm-gcov.sh --capture -o lcov-all.info + COMMAND + lcov -e lcov-all.info ${CMAKE_SOURCE_DIR}/include/boost/yap/* ${CMAKE_SOURCE_DIR}/include/boost/yap/detail/* -o lcov.info + COMMAND + genhtml lcov.info -o output + ) + else () + add_custom_target( + coverage + rm -rf ${coverage_gcda_files} lcov-all.info lcov.info output + COMMAND + ${CMAKE_CTEST_COMMAND} -j4 -VV -C ${CMAKE_CFG_INTDIR} + COMMAND + cd ${CMAKE_BINARY_DIR} + COMMAND + gcov -f -b ${coverage_gcda_files} + COMMAND + lcov --directory . --base-directory . --capture -o lcov-all.info + COMMAND + lcov -e lcov-all.info ${CMAKE_SOURCE_DIR}/include/boost/yap/* ${CMAKE_SOURCE_DIR}/include/boost/yap/detail/* -o lcov.info + COMMAND + genhtml lcov.info -o output + ) + endif () +endif () diff --git a/src/boost/libs/yap/test/Jamfile.v2 b/src/boost/libs/yap/test/Jamfile.v2 new file mode 100644 index 000000000..38287264b --- /dev/null +++ b/src/boost/libs/yap/test/Jamfile.v2 @@ -0,0 +1,64 @@ +# Copyright (c) 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 + +import config : requires ; +import testing ; + +project + : requirements + [ requires + cxx14_constexpr + cxx14_decltype_auto + cxx14_generic_lambdas + cxx14_return_type_deduction + ] + ; + +run deref.cpp ; +run value.cpp ; +run left.cpp ; +run right.cpp ; +run print.cpp ; +run default_eval.cpp ; +run user_expression_transform_1.cpp ; +run user_expression_transform_2.cpp ; +run placeholder_eval.cpp ; +run call_expr.cpp ; +run reference_returns.cpp ; +run depth_stress_test_left.cpp ; +run depth_stress_test_right.cpp ; +run lazy_vector_alloc_test.cpp ; +run vector_alloc_test.cpp ; +run operators_unary.cpp ; +run comma.cpp ; +run if_else.cpp ; +run expression_function.cpp ; +run transform.cpp ; +run supplied_transforms.cpp ; + +compile compile_is_expr.cpp ; +compile compile_const_term.cpp ; +compile compile_placeholders.cpp ; +compile compile_term_plus_expr.cpp ; +compile compile_term_plus_term.cpp ; +compile compile_term_plus_x.cpp ; +compile compile_x_plus_term.cpp ; +compile compile_term_plus_x_this_ref_overloads.cpp ; +compile compile_move_only_types.cpp ; +compile compile_user_macros.cpp ; + +compile-fail fail_transform.cpp ; +compile-fail fail_get.cpp ; +compile-fail fail_left.cpp ; +compile-fail fail_right.cpp ; +compile-fail fail_cond.cpp ; +compile-fail fail_then.cpp ; +compile-fail fail_else.cpp ; +compile-fail fail_callable.cpp ; +compile-fail fail_argument.cpp ; +compile-fail fail_make_expression.cpp ; +compile-fail fail_make_terminal.cpp ; diff --git a/src/boost/libs/yap/test/call_expr.cpp b/src/boost/libs/yap/test/call_expr.cpp new file mode 100644 index 000000000..2e5c343f7 --- /dev/null +++ b/src/boost/libs/yap/test/call_expr.cpp @@ -0,0 +1,198 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +namespace user { + + struct number + { + explicit operator double() const { return value; } + + double value; + }; + + number naxpy(number a, number x, number y) + { + return number{a.value * x.value + y.value + 10.0}; + } + + struct tag_type + {}; + + inline number tag_function(double a, double b) { return number{a + b}; } + + struct eval_xform_tag + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::call>, tag_type, number a, double b) + { + return tag_function(a.value, b); + } + + int operator()( + yap::expr_tag<yap::expr_kind::call>, tag_type, double a, double b) + { + return 42; + } + + char const * operator()() { return "42"; } + }; + + struct empty_xform + {}; + + struct eval_xform_expr + { + decltype(auto) operator()(yap::expression< + yap::expr_kind::call, + bh::tuple< + ref<term<user::tag_type>>, + term<user::number>, + term<int>>> const & expr) + { + using namespace boost::hana::literals; + return tag_function( + (double)yap::value(expr.elements[1_c]).value, + (double)yap::value(expr.elements[2_c])); + } + + decltype(auto) operator()(yap::expression< + yap::expr_kind::call, + bh::tuple< + ref<term<user::tag_type>>, + ref<term<user::number>>, + term<int>>> const & expr) + { + using namespace boost::hana::literals; + return tag_function( + (double)yap::value(expr.elements[1_c]).value, + (double)yap::value(expr.elements[2_c])); + } + }; + + struct eval_xform_both + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::call>, + tag_type, + user::number a, + double b) + { + return tag_function(a.value, b); + } + + decltype(auto) operator()(yap::expression< + yap::expr_kind::call, + bh::tuple< + ref<term<user::tag_type>>, + term<user::number>, + term<int>>> const & expr) + { + using namespace boost::hana::literals; + throw std::logic_error("Oops! Picked the wrong overload!"); + return tag_function( + (double)yap::value(expr.elements[1_c]).value, + (double)yap::value(expr.elements[2_c])); + } + + decltype(auto) operator()(yap::expression< + yap::expr_kind::call, + bh::tuple< + ref<term<user::tag_type>>, + ref<term<user::number>>, + term<int>>> const & expr) + { + using namespace boost::hana::literals; + throw std::logic_error("Oops! Picked the wrong overload!"); + return tag_function( + (double)yap::value(expr.elements[1_c]).value, + (double)yap::value(expr.elements[2_c])); + } + }; +} + + +int test_main(int, char * []) +{ + { + using namespace boost::yap::literals; + + { + auto plus = yap::make_terminal(user::tag_type{}); + auto expr = plus(user::number{13}, 1); + + { + transform(expr, user::empty_xform{}); + } + + { + user::number result = transform(expr, user::eval_xform_tag{}); + BOOST_CHECK(result.value == 14); + } + + { + user::number result = transform(expr, user::eval_xform_expr{}); + BOOST_CHECK(result.value == 14); + } + + { + user::number result = transform(expr, user::eval_xform_both{}); + BOOST_CHECK(result.value == 14); + } + } + + { + auto plus = yap::make_terminal(user::tag_type{}); + auto thirteen = yap::make_terminal(user::number{13}); + auto expr = plus(thirteen, 1); + + { + user::number result = transform(expr, user::eval_xform_tag{}); + BOOST_CHECK(result.value == 14); + } + + { + user::number result = transform(expr, user::eval_xform_expr{}); + BOOST_CHECK(result.value == 14); + } + + { + user::number result = transform(expr, user::eval_xform_both{}); + BOOST_CHECK(result.value == 14); + } + } + + { + term<user::number> a{{1.0}}; + term<user::number> x{{42.0}}; + term<user::number> y{{3.0}}; + auto n = yap::make_terminal(user::naxpy); + + auto expr = n(a, x, y); + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 55); + } + } + } + + return 0; +} diff --git a/src/boost/libs/yap/test/comma.cpp b/src/boost/libs/yap/test/comma.cpp new file mode 100644 index 000000000..af3814cf5 --- /dev/null +++ b/src/boost/libs/yap/test/comma.cpp @@ -0,0 +1,126 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using term_ref = boost::yap::expression_ref<boost::yap::expression, term<T> &>; + +template<typename T> +using term_cref = + boost::yap::expression_ref<boost::yap::expression, term<T> const &>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +struct void_callable +{ + void operator()() { *called_ = (*call_count_)++; } + int * call_count_; + int * called_; +}; + +struct int_callable +{ + int operator()() + { + *called_ = (*call_count_)++; + return 42; + } + int * call_count_; + int * called_; +}; + +struct double_callable +{ + double operator()() + { + *called_ = (*call_count_)++; + return 13.0; + } + int * call_count_; + int * called_; +}; + + +int test_main(int, char * []) +{ +{ + { + int call_count = 0; + int int_called = -1; + int double_called = -1; + + auto int_double_expr = + (term<int_callable>{{&call_count, &int_called}}(), + term<double_callable>{{&call_count, &double_called}}()); + + BOOST_CHECK(evaluate(int_double_expr) == 13.0); + BOOST_CHECK(int_called == 0); + BOOST_CHECK(double_called == 1); + } + + { + int call_count = 0; + int int_called = -1; + int double_called = -1; + + auto double_int_expr = + (term<double_callable>{{&call_count, &double_called}}(), + term<int_callable>{{&call_count, &int_called}}()); + + BOOST_CHECK(evaluate(double_int_expr) == 42); + BOOST_CHECK(int_called == 1); + BOOST_CHECK(double_called == 0); + } +} + +{ + { + int call_count = 0; + int void_called = -1; + int int_called = -1; + + auto void_int_expr = + (term<void_callable>{{&call_count, &void_called}}(), + term<int_callable>{{&call_count, &int_called}}()); + + BOOST_CHECK(evaluate(void_int_expr) == 42); + BOOST_CHECK(void_called == 0); + BOOST_CHECK(int_called == 1); + } + + { + int call_count = 0; + int void_called = -1; + int int_called = -1; + + auto int_void_expr = + (term<int_callable>{{&call_count, &int_called}}(), + term<void_callable>{{&call_count, &void_called}}()); + + using eval_type = decltype(evaluate(int_void_expr)); + BOOST_MPL_ASSERT( + (std::is_same<void, eval_type>)); + + evaluate(int_void_expr); + BOOST_CHECK(void_called == 1); + BOOST_CHECK(int_called == 0); + } +} + +return 0; +} diff --git a/src/boost/libs/yap/test/compile_const_term.cpp b/src/boost/libs/yap/test/compile_const_term.cpp new file mode 100644 index 000000000..11ff761d2 --- /dev/null +++ b/src/boost/libs/yap/test/compile_const_term.cpp @@ -0,0 +1,77 @@ +// 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 <boost/yap/expression.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +void compile_const_term() +{ + { + term<double const> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double const> &>, term<int &&>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double const> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double const> &>, term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + { + term<double> const unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> const &>, term<int &&>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> const &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> const &>, term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int const &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const &>>> const expr = + unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const &>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } +} diff --git a/src/boost/libs/yap/test/compile_is_expr.cpp b/src/boost/libs/yap/test/compile_is_expr.cpp new file mode 100644 index 000000000..3bf030d41 --- /dev/null +++ b/src/boost/libs/yap/test/compile_is_expr.cpp @@ -0,0 +1,99 @@ +// 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 <boost/yap/expression.hpp> + + +namespace yap = boost::yap; + +struct alternate_expr_1 +{ + static const yap::expr_kind kind = yap::expr_kind::plus; + boost::hana::tuple<> elements; +}; + +struct alternate_expr_2 +{ + static const yap::expr_kind kind = yap::expr_kind::plus; + boost::hana::tuple<int, double> elements; +}; + + +struct non_expr_1 +{}; + +struct non_expr_2 +{ + boost::hana::tuple<int, double> elements; +}; + +struct non_expr_3 +{ + static const int kind = 0; + boost::hana::tuple<int, double> elements; +}; + +struct non_expr_4 +{ + int kind; + boost::hana::tuple<int, double> elements; +}; + +struct non_expr_5 +{ + static const yap::expr_kind kind = yap::expr_kind::plus; +}; + +struct non_expr_6 +{ + static const yap::expr_kind kind = yap::expr_kind::plus; + int elements; +}; + + +void compile_is_expr() +{ + static_assert( + yap::is_expr<yap::terminal<yap::expression, double>>::value, ""); + + static_assert( + yap::is_expr<yap::terminal<yap::expression, double> const>::value, ""); + static_assert( + yap::is_expr<yap::terminal<yap::expression, double> const &>::value, + ""); + static_assert( + yap::is_expr<yap::terminal<yap::expression, double> &>::value, ""); + static_assert( + yap::is_expr<yap::terminal<yap::expression, double> &&>::value, ""); + + { + using namespace yap::literals; + static_assert(yap::is_expr<decltype(1_p)>::value, ""); + } + + static_assert( + yap::is_expr<yap::expression< + yap::expr_kind::unary_plus, + boost::hana::tuple<yap::terminal<yap::expression, double>>>>::value, + ""); + static_assert( + yap::is_expr<yap::expression< + yap::expr_kind::plus, + boost::hana::tuple< + yap::terminal<yap::expression, double>, + yap::terminal<yap::expression, double>>>>::value, + ""); + + static_assert(yap::is_expr<alternate_expr_1>::value, ""); + static_assert(yap::is_expr<alternate_expr_2>::value, ""); + + static_assert(!yap::is_expr<int>::value, ""); + static_assert(!yap::is_expr<non_expr_1>::value, ""); + static_assert(!yap::is_expr<non_expr_2>::value, ""); + static_assert(!yap::is_expr<non_expr_3>::value, ""); + static_assert(!yap::is_expr<non_expr_4>::value, ""); + static_assert(!yap::is_expr<non_expr_5>::value, ""); + static_assert(!yap::is_expr<non_expr_6>::value, ""); +} diff --git a/src/boost/libs/yap/test/compile_move_only_types.cpp b/src/boost/libs/yap/test/compile_move_only_types.cpp new file mode 100644 index 000000000..2649ff00e --- /dev/null +++ b/src/boost/libs/yap/test/compile_move_only_types.cpp @@ -0,0 +1,46 @@ +// 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 <boost/yap/expression.hpp> + +#include <memory> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +inline auto double_to_float(term<double> expr) +{ + return term<float>{(float)expr.value()}; +} + +void compile_move_only_types() +{ + term<double> unity{1.0}; + term<std::unique_ptr<int>> i{new int{7}}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<std::unique_ptr<int>>>> + expr_1 = unity + std::move(i); + + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<std::unique_ptr<int>>>>>> + expr_2 = unity + std::move(expr_1); + + auto transformed_expr = transform(std::move(expr_2), double_to_float); + (void)transformed_expr; +} diff --git a/src/boost/libs/yap/test/compile_placeholders.cpp b/src/boost/libs/yap/test/compile_placeholders.cpp new file mode 100644 index 000000000..8a4e50aa3 --- /dev/null +++ b/src/boost/libs/yap/test/compile_placeholders.cpp @@ -0,0 +1,50 @@ +// 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 <boost/yap/expression.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<long long I> +using place_term = + boost::yap::terminal<boost::yap::expression, boost::yap::placeholder<I>>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +void compile_placeholders() +{ + using namespace boost::yap::literals; + + { + place_term<1> p1 = 1_p; + (void)p1; + } + + { + place_term<1> p1 = 1_p; + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<place_term<1> &>, ref<term<double> &>>> + expr = p1 + unity; + (void)expr; + } + + { + place_term<1> p1 = 1_p; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<place_term<1> &>, place_term<2>>> + expr = p1 + 2_p; + (void)expr; + } +} diff --git a/src/boost/libs/yap/test/compile_term_plus_expr.cpp b/src/boost/libs/yap/test/compile_term_plus_expr.cpp new file mode 100644 index 000000000..9a90f9ac8 --- /dev/null +++ b/src/boost/libs/yap/test/compile_term_plus_expr.cpp @@ -0,0 +1,308 @@ +// 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 <boost/yap/expression.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +void compile_term_plus_expr() +{ + // values + { + term<double> unity{1.0}; + term<int> i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int> &>>> + expr = unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int> &>>> &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + term<int const> i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const> &>>> + expr = unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const> &>>> &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + term<int> i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>> &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + // const value terminals/expressions + { + term<double> unity{1.0}; + term<int> const i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int> const &>>> const expr = + unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<term<int> const &>>> const &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + term<int> i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int> &>>> const expr = + unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int> &>>> const &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + // lvalue refs + { + term<double> unity{1.0}; + int i_ = 1; + term<int &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int &> &>>> + expr = unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int &> &>>> &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int const &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const &> &>>> + expr = unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<term<int const &> &>>> &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + ref<yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &>>> &>>> + unevaluated_expr = unity + expr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int &> &>>> + expr = unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int &> &>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int const &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const &> &>>> + expr = unity + i; + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const &> &>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + // rvalue refs + { + term<double> unity{1.0}; + int i_ = 1; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + (void)unevaluated_expr; + } +} diff --git a/src/boost/libs/yap/test/compile_term_plus_term.cpp b/src/boost/libs/yap/test/compile_term_plus_term.cpp new file mode 100644 index 000000000..d1037ce60 --- /dev/null +++ b/src/boost/libs/yap/test/compile_term_plus_term.cpp @@ -0,0 +1,221 @@ +// 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 <boost/yap/expression.hpp> + +#include <string> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +void compile_term_plus_term() +{ + using namespace std::literals; + + // char const * string + { + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<char const *>>> + unevaluated_expr = unity + term<char const *>{"3"}; + (void)unevaluated_expr; + } + + // std::string temporary + { + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<std::string>>> + unevaluated_expr = unity + term<std::string>{"3"s}; + (void)unevaluated_expr; + } + + // pointers + { + term<double> unity{1.0}; + int ints_[] = {1, 2}; + term<int *> ints = {ints_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int *> &>>> + unevaluated_expr = unity + ints; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints_[] = {1, 2}; + term<int const *> ints = {ints_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const *> &>>> + unevaluated_expr = unity + ints; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints_[] = {1, 2}; + term<int *> ints = {ints_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *>>> + unevaluated_expr = unity + std::move(ints); + (void)unevaluated_expr; + } + + // const pointers + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + term<int * const> int_ptr = {ints}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int * const> &>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + term<int const * const> int_ptr = {ints}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const * const> &>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + term<int * const> int_ptr = {ints}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int * const>>> + unevaluated_expr = unity + std::move(int_ptr); + (void)unevaluated_expr; + } + + // values + { + term<double> unity{1.0}; + term<int> i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int> &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + term<int const> i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const> &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + term<int> i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>> + unevaluated_expr = unity + std::move(i); + (void)unevaluated_expr; + } + + // const value terminals + { + term<double> unity{1.0}; + term<int> const i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int> const &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + term<int const> const i = {1}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const> const &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + // lvalue refs + { + term<double> unity{1.0}; + int i_ = 1; + term<int &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int &> &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int const &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<int const &> &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &> i{i_}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &>>> + unevaluated_expr = unity + std::move(i); + (void)unevaluated_expr; + } + + // rvalue refs + { + term<double> unity{1.0}; + int i_ = 1; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>> + unevaluated_expr = unity + std::move(i); + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i_ = 1; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>> + unevaluated_expr = unity + std::move(i); + (void)unevaluated_expr; + } +} diff --git a/src/boost/libs/yap/test/compile_term_plus_x.cpp b/src/boost/libs/yap/test/compile_term_plus_x.cpp new file mode 100644 index 000000000..1382abf95 --- /dev/null +++ b/src/boost/libs/yap/test/compile_term_plus_x.cpp @@ -0,0 +1,174 @@ +// 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 <boost/yap/expression.hpp> + +#include <string> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +void compile_term_plus_x() +{ + using namespace std::literals; + + // char const * string + { + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<char const *>>> + unevaluated_expr = unity + "3"; + (void)unevaluated_expr; + } + + // std::string temporary + { + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<std::string>>> + unevaluated_expr = unity + "3"s; + (void)unevaluated_expr; + } + + // arrays + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *>>> + unevaluated_expr = unity + ints; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const *>>> + unevaluated_expr = unity + ints; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *>>> + unevaluated_expr = unity + std::move(ints); + (void)unevaluated_expr; + } + + // pointers + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *&>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + int const * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const *&>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *>>> + unevaluated_expr = unity + std::move(int_ptr); + (void)unevaluated_expr; + } + + // const pointers + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int * const &>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + int const * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const * const &>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int * const>>> + unevaluated_expr = unity + std::move(int_ptr); + (void)unevaluated_expr; + } + + // values + { + term<double> unity{1.0}; + int i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>> + unevaluated_expr = unity + std::move(i); + (void)unevaluated_expr; + } +} diff --git a/src/boost/libs/yap/test/compile_term_plus_x_this_ref_overloads.cpp b/src/boost/libs/yap/test/compile_term_plus_x_this_ref_overloads.cpp new file mode 100644 index 000000000..585416097 --- /dev/null +++ b/src/boost/libs/yap/test/compile_term_plus_x_this_ref_overloads.cpp @@ -0,0 +1,174 @@ +// 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 <boost/yap/expression.hpp> + +#include <string> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +void compile_term_plus_x_this_ref_overloads() +{ + using namespace std::literals; + + // char const * string + { + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<char const *>>> + unevaluated_expr = unity + "3"; + (void)unevaluated_expr; + } + + // std::string temporary + { + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<std::string>>> + unevaluated_expr = unity + "3"s; + (void)unevaluated_expr; + } + + // arrays + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *>>> + unevaluated_expr = unity + ints; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const *>>> + unevaluated_expr = unity + ints; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *>>> + unevaluated_expr = unity + std::move(ints); + (void)unevaluated_expr; + } + + // pointers + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *&>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + int const * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const *&>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int *>>> + unevaluated_expr = unity + std::move(int_ptr); + (void)unevaluated_expr; + } + + // const pointers + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int * const &>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + int const * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const * const &>>> + unevaluated_expr = unity + int_ptr; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int * const>>> + unevaluated_expr = unity + std::move(int_ptr); + (void)unevaluated_expr; + } + + // values + { + term<double> unity{1.0}; + int i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int const &>>> + unevaluated_expr = unity + i; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>> + unevaluated_expr = unity + std::move(i); + (void)unevaluated_expr; + } +} diff --git a/src/boost/libs/yap/test/compile_tests_main.cpp b/src/boost/libs/yap/test/compile_tests_main.cpp new file mode 100644 index 000000000..7c77fc4ef --- /dev/null +++ b/src/boost/libs/yap/test/compile_tests_main.cpp @@ -0,0 +1,29 @@ +// 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) +void compile_is_expr(); +void compile_const_term(); +void compile_move_only_types(); +void compile_placeholders(); +void compile_term_plus_expr(); +void compile_term_plus_term(); +void compile_term_plus_x(); +void compile_term_plus_x_this_ref_overloads(); +void compile_x_plus_term(); +void compile_user_macros(); + +int main() +{ + compile_is_expr(); + compile_const_term(); + compile_move_only_types(); + compile_placeholders(); + compile_term_plus_expr(); + compile_term_plus_term(); + compile_term_plus_x(); + compile_term_plus_x_this_ref_overloads(); + compile_x_plus_term(); + compile_user_macros(); +} diff --git a/src/boost/libs/yap/test/compile_user_macros.cpp b/src/boost/libs/yap/test/compile_user_macros.cpp new file mode 100644 index 000000000..f9fd01f43 --- /dev/null +++ b/src/boost/libs/yap/test/compile_user_macros.cpp @@ -0,0 +1,58 @@ +// 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 <boost/yap/expression.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +template<yap::expr_kind Kind, typename Tuple> +struct expr +{ + static yap::expr_kind const kind = Kind; + Tuple elements; + + BOOST_YAP_USER_ASSIGN_OPERATOR(expr, ::expr); +}; + + +static_assert(yap::detail::copy_or_move<int, int const &>::value, ""); +static_assert(yap::detail::copy_or_move<int, int &>::value, ""); +static_assert(yap::detail::copy_or_move<int, int &&>::value, ""); +static_assert(!yap::detail::copy_or_move<int, int const &&>::value, ""); +static_assert(!yap::detail::copy_or_move<int, int>::value, ""); + + +void compile_user_macros() +{ + using namespace boost::hana::literals; + + expr<yap::expr_kind::negate, bh::tuple<int>> negation1; + negation1.elements[0_c] = 1; + expr<yap::expr_kind::negate, bh::tuple<int>> negation2; + negation2.elements[0_c] = 2; + + // Normal-rules assignment. + negation2 = negation1; + assert(negation2.elements[0_c] == 1); + + negation2.elements[0_c] = 2; + + // Normal-rules move assignment. + negation2 = std::move(negation1); + assert(negation2.elements[0_c] == 1); + + // Produce a new expression via BOOST_YAP_USER_ASSIGN_OPERATOR. + auto expr = negation1 = 2; + (void)expr; +} diff --git a/src/boost/libs/yap/test/compile_x_plus_term.cpp b/src/boost/libs/yap/test/compile_x_plus_term.cpp new file mode 100644 index 000000000..2eef6eba8 --- /dev/null +++ b/src/boost/libs/yap/test/compile_x_plus_term.cpp @@ -0,0 +1,174 @@ +// 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 <boost/yap/expression.hpp> + +#include <string> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +void compile_x_plus_term() +{ + using namespace std::literals; + + // char const * string + { + term<double> unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<char const *>, ref<term<double> &>>> + unevaluated_expr = "3" + unity; + (void)unevaluated_expr; + } + + // std::string temporary + { + term<double> const unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<std::string>, ref<term<double> const &>>> + unevaluated_expr = "3"s + unity; + (void)unevaluated_expr; + } + + // arrays + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int *>, ref<term<double> &>>> + unevaluated_expr = ints + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int const *>, ref<term<double> &>>> + unevaluated_expr = ints + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int *>, ref<term<double> &>>> + unevaluated_expr = std::move(ints) + unity; + (void)unevaluated_expr; + } + + // pointers + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int *&>, ref<term<double> &>>> + unevaluated_expr = int_ptr + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + int const * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int const *&>, ref<term<double> &>>> + unevaluated_expr = int_ptr + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int *>, ref<term<double> &>>> + unevaluated_expr = std::move(int_ptr) + unity; + (void)unevaluated_expr; + } + + // const pointers + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int * const &>, ref<term<double> &>>> + unevaluated_expr = int_ptr + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const ints[] = {1, 2}; + int const * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int const * const &>, ref<term<double> &>>> + unevaluated_expr = int_ptr + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int ints[] = {1, 2}; + int * const int_ptr = ints; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int * const>, ref<term<double> &>>> + unevaluated_expr = std::move(int_ptr) + unity; + (void)unevaluated_expr; + } + + // values + { + term<double> unity{1.0}; + int i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int &>, ref<term<double> &>>> + unevaluated_expr = i + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int const i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int const &>, ref<term<double> &>>> + unevaluated_expr = i + unity; + (void)unevaluated_expr; + } + + { + term<double> unity{1.0}; + int i = 1; + yap::expression< + yap::expr_kind::plus, + bh::tuple<term<int>, ref<term<double> &>>> + unevaluated_expr = std::move(i) + unity; + (void)unevaluated_expr; + } +} diff --git a/src/boost/libs/yap/test/default_eval.cpp b/src/boost/libs/yap/test/default_eval.cpp new file mode 100644 index 000000000..27087f953 --- /dev/null +++ b/src/boost/libs/yap/test/default_eval.cpp @@ -0,0 +1,103 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +int test_main(int, char * []) +{ + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::minus, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity - std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::minus, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr_1 = unity + std::move(expr); + + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<double> &>>> + unevaluated_expr_2 = unity + unity; + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + unevaluated_expr_3 = unity + const_unity; + + { + double result = evaluate(unity); + BOOST_CHECK(result == 1); + } + + { + double result = evaluate(expr); + BOOST_CHECK(result == -41); + } + + { + double result = evaluate(unevaluated_expr_1); + BOOST_CHECK(result == -40); + } + + { + double result = evaluate(unevaluated_expr_2); + BOOST_CHECK(result == 2); + } + + { + double result = evaluate(unevaluated_expr_3); + BOOST_CHECK(result == 2); + } + + { + double result = evaluate(unity, 5, 6, 7); + BOOST_CHECK(result == 1); + } + + { + double result = evaluate(expr); + BOOST_CHECK(result == -41); + } + + { + double result = evaluate(unevaluated_expr_1, std::string("15")); + BOOST_CHECK(result == -40); + } + + { + double result = evaluate(unevaluated_expr_2, std::string("15")); + BOOST_CHECK(result == 2); + } + + { + double result = evaluate(unevaluated_expr_3, std::string("15")); + BOOST_CHECK(result == 2); + } + } + + return 0; +} diff --git a/src/boost/libs/yap/test/depth_stress_test_left.cpp b/src/boost/libs/yap/test/depth_stress_test_left.cpp new file mode 100644 index 000000000..ec2724e12 --- /dev/null +++ b/src/boost/libs/yap/test/depth_stress_test_left.cpp @@ -0,0 +1,69 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template <typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +namespace yap = boost::yap; + + +int test_main(int, char * []) +{ +{ + term<double> unity{1.0}; + + { + auto expr = (unity + (unity + (unity + (unity + (unity + (unity + (unity + unity))))))); + double result = boost::yap::evaluate(expr); + BOOST_CHECK(result == 8.0); + } + + { + auto expr = + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + double result = boost::yap::evaluate(expr); + BOOST_CHECK(result == 64.0); + } + +#if 0 // This makes the Travis VMs barf. + { + auto expr = + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity + + (unity + (unity + (unity + (unity + (unity + (unity + (unity + (unity)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + double result = boost::yap::evaluate( + (expr + (expr + (expr + (expr + (expr + (expr + (expr + (expr + + (expr + (expr + (expr + (expr + (expr + (expr + (expr + (expr + + (expr + (expr + (expr + (expr + (expr + (expr + (expr + (expr + + (expr + (expr + (expr + (expr + (expr + (expr + (expr + (expr)))))))))))))))))))))))))))))))) + ); + BOOST_CHECK(result == 64.0 * 32.0); + } +#endif +} + +return 0; +} diff --git a/src/boost/libs/yap/test/depth_stress_test_right.cpp b/src/boost/libs/yap/test/depth_stress_test_right.cpp new file mode 100644 index 000000000..33c5be1bd --- /dev/null +++ b/src/boost/libs/yap/test/depth_stress_test_right.cpp @@ -0,0 +1,70 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +namespace yap = boost::yap; + + +int test_main(int, char * []) +{ + { + term<double> unity{1.0}; + + { + auto expr = + unity + unity + unity + unity + unity + unity + unity + unity; + double result = boost::yap::evaluate(expr); + BOOST_CHECK(result == 8.0); + } + + { + auto expr = + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity; + double result = boost::yap::evaluate(expr); + BOOST_CHECK(result == 64.0); + } + +#if 0 // This makes the Travis VMs barf. + { + auto expr = + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity + + unity + unity + unity + unity + unity + unity + unity + unity; + double result = boost::yap::evaluate( + expr + expr + expr + expr + expr + expr + expr + expr + + expr + expr + expr + expr + expr + expr + expr + expr + + expr + expr + expr + expr + expr + expr + expr + expr + + expr + expr + expr + expr + expr + expr + expr + expr + ); + BOOST_CHECK(result == 64.0 * 32.0); + } +#endif + } + + return 0; +} diff --git a/src/boost/libs/yap/test/deref.cpp b/src/boost/libs/yap/test/deref.cpp new file mode 100644 index 000000000..137b51e83 --- /dev/null +++ b/src/boost/libs/yap/test/deref.cpp @@ -0,0 +1,174 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +template<boost::yap::expr_kind Kind, typename Tuple> +struct user_expr +{ + static boost::yap::expr_kind const kind = Kind; + + Tuple elements; +}; + +BOOST_YAP_USER_BINARY_OPERATOR(plus, user_expr, user_expr) + +template<typename T> +using user_term = boost::yap::terminal<user_expr, T>; + +template<typename T> +using user_ref = boost::yap::expression_ref<user_expr, T>; + + +int test_main(int, char * []) +{ + { + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + + plus_expr_type plus_expr = unity + term<int>{{1}}; + + { + ref<term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(std::move(ref))), + term<double> &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + ref<term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::deref(ref)), term<double> &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + ref<term<double> &> const ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::deref(ref)), term<double> &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + term<double> const unity = {{1.0}}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> const &>, term<int>>> + plus_expr = unity + term<int>{{1}}; + + { + ref<term<double> const &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(std::move(ref))), + term<double> const &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + ref<term<double> const &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(ref)), + term<double> const &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + ref<term<double> const &> const ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(ref)), + term<double> const &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + } + } + + { + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + + { + user_ref<user_term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(std::move(ref))), + user_term<double> &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + user_ref<user_term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::deref(ref)), user_term<double> &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + user_ref<user_term<double> &> const ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::deref(ref)), user_term<double> &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + user_term<double> const unity = {{1.0}}; + user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> const &>, user_term<int>>> + plus_expr = unity + user_term<int>{{1}}; + + { + user_ref<user_term<double> const &> ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(std::move(ref))), + user_term<double> const &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + user_ref<user_term<double> const &> ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(ref)), + user_term<double> const &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + + { + user_ref<user_term<double> const &> const ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::deref(ref)), + user_term<double> const &>)); + BOOST_CHECK(yap::value(ref) == 1.0); + } + } + } + + return 0; +} diff --git a/src/boost/libs/yap/test/expression_function.cpp b/src/boost/libs/yap/test/expression_function.cpp new file mode 100644 index 000000000..4819e0f38 --- /dev/null +++ b/src/boost/libs/yap/test/expression_function.cpp @@ -0,0 +1,70 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +int test_main(int, char * []) +{ + { + term<int> number = {{42}}; + + auto fn = yap::make_expression_function(number); + auto fn_copy = fn; + + BOOST_CHECK(fn() == 42); + BOOST_CHECK(fn_copy() == 42); + + yap::value(number) = 21; + + BOOST_CHECK(fn() == 21); + BOOST_CHECK(fn_copy() == 21); + } + + { + term<int> number = {{42}}; + + auto fn = yap::make_expression_function(std::move(number)); + auto fn_copy = fn; + + BOOST_CHECK(fn() == 42); + BOOST_CHECK(fn_copy() == 42); + + yap::value(number) = 21; + + BOOST_CHECK(fn() == 42); + BOOST_CHECK(fn_copy() == 42); + } + + { + term<std::unique_ptr<int>> number = { + {std::unique_ptr<int>(new int(42))}}; + + auto fn = yap::make_expression_function(std::move(number)); + + BOOST_CHECK(*fn() == 42); + + auto fn_2 = std::move(fn); + BOOST_CHECK(*fn_2() == 42); + + yap::value(number) = std::unique_ptr<int>(new int(21)); + + BOOST_CHECK(*fn_2() == 42); + } + + return 0; +} diff --git a/src/boost/libs/yap/test/fail_argument.cpp b/src/boost/libs/yap/test/fail_argument.cpp new file mode 100644 index 000000000..69d2cc485 --- /dev/null +++ b/src/boost/libs/yap/test/fail_argument.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::argument(boost::yap::make_terminal(1), boost::hana::llong_c<0>); +} diff --git a/src/boost/libs/yap/test/fail_callable.cpp b/src/boost/libs/yap/test/fail_callable.cpp new file mode 100644 index 000000000..ebdfe0a09 --- /dev/null +++ b/src/boost/libs/yap/test/fail_callable.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::callable(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_cond.cpp b/src/boost/libs/yap/test/fail_cond.cpp new file mode 100644 index 000000000..73d2d6d49 --- /dev/null +++ b/src/boost/libs/yap/test/fail_cond.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::cond(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_else.cpp b/src/boost/libs/yap/test/fail_else.cpp new file mode 100644 index 000000000..a4a65ae80 --- /dev/null +++ b/src/boost/libs/yap/test/fail_else.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::then(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_get.cpp b/src/boost/libs/yap/test/fail_get.cpp new file mode 100644 index 000000000..c56f1efc8 --- /dev/null +++ b/src/boost/libs/yap/test/fail_get.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::get(boost::yap::make_terminal(1), boost::hana::llong_c<1>); +} diff --git a/src/boost/libs/yap/test/fail_left.cpp b/src/boost/libs/yap/test/fail_left.cpp new file mode 100644 index 000000000..0a6f1086e --- /dev/null +++ b/src/boost/libs/yap/test/fail_left.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::left(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_make_expression.cpp b/src/boost/libs/yap/test/fail_make_expression.cpp new file mode 100644 index 000000000..3509656a3 --- /dev/null +++ b/src/boost/libs/yap/test/fail_make_expression.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::make_expression<boost::yap::expr_kind::plus>(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_make_terminal.cpp b/src/boost/libs/yap/test/fail_make_terminal.cpp new file mode 100644 index 000000000..59e496472 --- /dev/null +++ b/src/boost/libs/yap/test/fail_make_terminal.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::make_terminal(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_right.cpp b/src/boost/libs/yap/test/fail_right.cpp new file mode 100644 index 000000000..2889df5e7 --- /dev/null +++ b/src/boost/libs/yap/test/fail_right.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::right(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_then.cpp b/src/boost/libs/yap/test/fail_then.cpp new file mode 100644 index 000000000..a4a65ae80 --- /dev/null +++ b/src/boost/libs/yap/test/fail_then.cpp @@ -0,0 +1,12 @@ +// 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 <boost/yap/expression.hpp> + + +int main() +{ + boost::yap::then(boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/fail_transform.cpp b/src/boost/libs/yap/test/fail_transform.cpp new file mode 100644 index 000000000..54f5916b6 --- /dev/null +++ b/src/boost/libs/yap/test/fail_transform.cpp @@ -0,0 +1,15 @@ +// 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 <boost/yap/expression.hpp> + + +struct xform +{}; + +int main() +{ + boost::yap::transform(xform{}, boost::yap::make_terminal(1)); +} diff --git a/src/boost/libs/yap/test/if_else.cpp b/src/boost/libs/yap/test/if_else.cpp new file mode 100644 index 000000000..c3ed5204f --- /dev/null +++ b/src/boost/libs/yap/test/if_else.cpp @@ -0,0 +1,114 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using term_ref = boost::yap::expression_ref<boost::yap::expression, term<T> &>; + +template<typename T> +using term_cref = + boost::yap::expression_ref<boost::yap::expression, term<T> const &>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +struct callable +{ + int operator()() { return 42; } +}; + +struct side_effect_callable_1 +{ + int operator()() + { + *value_ = 1; + return 0; + } + + int * value_; +}; + +struct side_effect_callable_2 +{ + int operator()() + { + *value_ = 2; + return 0; + } + + int * value_; +}; + + +int test_main(int, char * []) +{ + { + int one = 0; + int two = 0; + + auto true_nothrow_throw_expr = if_else( + term<bool>{{true}}, + term<callable>{}(), + term<side_effect_callable_1>{{&one}}()); + + BOOST_CHECK(yap::evaluate(true_nothrow_throw_expr) == 42); + BOOST_CHECK(one == 0); + BOOST_CHECK(two == 0); + } + + { + int one = 0; + int two = 0; + + auto false_nothrow_throw_expr = if_else( + term<bool>{{false}}, + term<callable>{}(), + term<side_effect_callable_1>{{&one}}()); + + BOOST_CHECK(yap::evaluate(false_nothrow_throw_expr) == 0); + BOOST_CHECK(one == 1); + BOOST_CHECK(two == 0); + } + + { + int one = 0; + int two = 0; + + auto true_throw1_throw2_expr = if_else( + term<bool>{{true}}, + term<side_effect_callable_1>{{&one}}(), + term<side_effect_callable_2>{{&two}}()); + + BOOST_CHECK(yap::evaluate(true_throw1_throw2_expr) == 0); + BOOST_CHECK(one == 1); + BOOST_CHECK(two == 0); + } + + { + int one = 0; + int two = 0; + + auto false_throw1_throw2_expr = if_else( + term<bool>{{false}}, + term<side_effect_callable_1>{{&one}}(), + term<side_effect_callable_2>{{&two}}()); + + BOOST_CHECK(yap::evaluate(false_throw1_throw2_expr) == 0); + BOOST_CHECK(one == 0); + BOOST_CHECK(two == 2); + } + + return 0; +} diff --git a/src/boost/libs/yap/test/lazy_vector_alloc_test.cpp b/src/boost/libs/yap/test/lazy_vector_alloc_test.cpp new file mode 100644 index 000000000..e074247ba --- /dev/null +++ b/src/boost/libs/yap/test/lazy_vector_alloc_test.cpp @@ -0,0 +1,108 @@ +// 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 <boost/yap/expression.hpp> + +#include <algorithm> +#include <cassert> +#include <iostream> +#include <vector> + +#include <boost/test/minimal.hpp> + + +int allocations = 0; + +void * operator new(std::size_t size) +{ + ++allocations; + void * retval = malloc(size); + if (!retval) + throw std::bad_alloc(); + return retval; +} + +void operator delete(void * ptr) noexcept { free(ptr); } + + +template<boost::yap::expr_kind Kind, typename Tuple> +struct lazy_vector_expr; + + +struct take_nth +{ + boost::yap::terminal<lazy_vector_expr, double> operator()( + boost::yap::terminal<lazy_vector_expr, std::vector<double>> const & + expr); + + std::size_t n; +}; + +template<boost::yap::expr_kind Kind, typename Tuple> +struct lazy_vector_expr +{ + static const boost::yap::expr_kind kind = Kind; + + Tuple elements; + + auto operator[](std::size_t n) const + { + return boost::yap::evaluate(boost::yap::transform(*this, take_nth{n})); + } +}; + +BOOST_YAP_USER_BINARY_OPERATOR(plus, lazy_vector_expr, lazy_vector_expr) +BOOST_YAP_USER_BINARY_OPERATOR(minus, lazy_vector_expr, lazy_vector_expr) + +boost::yap::terminal<lazy_vector_expr, double> take_nth::operator()( + boost::yap::terminal<lazy_vector_expr, std::vector<double>> const & expr) +{ + double x = boost::yap::value(expr)[n]; + return boost::yap::make_terminal<lazy_vector_expr, double>(std::move(x)); +} + +struct lazy_vector : lazy_vector_expr< + boost::yap::expr_kind::terminal, + boost::hana::tuple<std::vector<double>>> +{ + lazy_vector() {} + + explicit lazy_vector(std::vector<double> && vec) + { + elements = boost::hana::tuple<std::vector<double>>(std::move(vec)); + } + + template<boost::yap::expr_kind Kind, typename Tuple> + lazy_vector & operator+=(lazy_vector_expr<Kind, Tuple> const & rhs) + { + std::vector<double> & this_vec = boost::yap::value(*this); + for (int i = 0, size = (int)this_vec.size(); i < size; ++i) { + this_vec[i] += rhs[i]; + } + return *this; + } +}; + + +int test_main(int, char * []) +{ + lazy_vector v1{std::vector<double>(4, 1.0)}; + lazy_vector v2{std::vector<double>(4, 2.0)}; + lazy_vector v3{std::vector<double>(4, 3.0)}; + + // Reset allocation count. There should be none from this point on. + allocations = 0; + + double d1 = (v2 + v3)[2]; + std::cout << d1 << "\n"; + + v1 += v2 - v3; + std::cout << '{' << v1[0] << ',' << v1[1] << ',' << v1[2] << ',' << v1[3] + << '}' << "\n"; + + BOOST_CHECK(allocations == 0); + + return 0; +} diff --git a/src/boost/libs/yap/test/left.cpp b/src/boost/libs/yap/test/left.cpp new file mode 100644 index 000000000..7e045c2fd --- /dev/null +++ b/src/boost/libs/yap/test/left.cpp @@ -0,0 +1,329 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +template<boost::yap::expr_kind Kind, typename Tuple> +struct user_expr +{ + static boost::yap::expr_kind const kind = Kind; + + Tuple elements; +}; + +BOOST_YAP_USER_BINARY_OPERATOR(plus, user_expr, user_expr) + +template<typename T> +using user_term = boost::yap::terminal<user_expr, T>; + +template<typename T> +using user_ref = boost::yap::expression_ref<user_expr, T>; + + +int test_main(int, char * []) +{ + { + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + + { + plus_expr_type plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr))), + ref<term<double> &> &&>)); + } + + { + plus_expr_type plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr)), + ref<term<double> &> &>)); + } + + { + plus_expr_type const plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr)), + ref<term<double> &> const &>)); + } + + { + term<double> const unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> const &>, term<int>>>; + + { + plus_expr_type plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr))), + ref<term<double> const &> &&>)); + } + + { + plus_expr_type plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr)), + ref<term<double> const &> &>)); + } + + { + plus_expr_type const plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr)), + ref<term<double> const &> const &>)); + } + } + + { + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + plus_expr_type plus_expr = unity + term<int>{{1}}; + + using plus_plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<plus_expr_type &>, term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr_ref))), + ref<term<double> &> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + ref<term<double> &> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + ref<term<double> &> &>)); + } + } + + { + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + plus_expr_type const plus_expr = unity + term<int>{{1}}; + + using plus_plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<plus_expr_type const &>, term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr_ref))), + ref<term<double> &> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + ref<term<double> &> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type const &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + ref<term<double> &> const &>)); + } + } + } + + { + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + + { + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr))), + user_ref<user_term<double> &> &&>)); + } + + { + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr)), + user_ref<user_term<double> &> &>)); + } + + { + plus_expr_type const plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr)), + user_ref<user_term<double> &> const &>)); + } + + { + user_term<double> const unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> const &>, user_term<int>>>; + + { + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr))), + user_ref<user_term<double> const &> &&>)); + } + + { + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr)), + user_ref<user_term<double> const &> &>)); + } + + { + plus_expr_type const plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT( + (std::is_same< + decltype(yap::left(plus_expr)), + user_ref<user_term<double> const &> const &>)); + } + } + + { + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + + using plus_plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<plus_expr_type &>, user_term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr_ref))), + user_ref<user_term<double> &> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + user_ref<user_term<double> &> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + user_ref<user_term<double> &> &>)); + } + } + + { + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + plus_expr_type const plus_expr = unity + user_term<int>{{1}}; + + using plus_plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<plus_expr_type const &>, user_term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(std::move(plus_expr_ref))), + user_ref<user_term<double> &> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + user_ref<user_term<double> &> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type const &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::left(plus_expr_ref)), + user_ref<user_term<double> &> const &>)); + } + } + } + +#ifndef _MSC_VER // Tsk, tsk. + { + using term_t = term<int>; + constexpr auto expr = term_t{13} + term_t{42}; + constexpr auto result1 = expr.left().value(); + constexpr auto result2 = yap::value(left(expr)); + (void)result1; + (void)result2; + } +#endif + + return 0; +} diff --git a/src/boost/libs/yap/test/operators_unary.cpp b/src/boost/libs/yap/test/operators_unary.cpp new file mode 100644 index 000000000..6372f3d3f --- /dev/null +++ b/src/boost/libs/yap/test/operators_unary.cpp @@ -0,0 +1,174 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using term_ref = boost::yap::expression_ref<boost::yap::expression, term<T> &>; + +template<typename T> +using term_cref = + boost::yap::expression_ref<boost::yap::expression, term<T> const &>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +int test_main(int, char * []) +{ + { + term<uint32_t> x{{2u}}; + term<uint32_t> const cx{{3u}}; + + { + yap::expression< + yap::expr_kind::unary_plus, + bh::tuple<term<uint32_t>>> + term_expr = +term<uint32_t>{{1u}}; + yap::expression< + yap::expr_kind::unary_plus, + bh::tuple<term_ref<uint32_t>>> + term_ref_expr = +x; + yap::expression< + yap::expr_kind::unary_plus, + bh::tuple<term_cref<uint32_t>>> + term_const_ref_expr = +cx; + + BOOST_CHECK(evaluate(term_expr) == 1u); + BOOST_CHECK(evaluate(term_ref_expr) == 2u); + BOOST_CHECK(evaluate(term_const_ref_expr) == 3u); + } + + { + yap::expression<yap::expr_kind::negate, bh::tuple<term<uint32_t>>> + term_expr = -term<uint32_t>{{1u}}; + yap::expression< + yap::expr_kind::negate, + bh::tuple<term_ref<uint32_t>>> + term_ref_expr = -x; + yap::expression< + yap::expr_kind::negate, + bh::tuple<term_cref<uint32_t>>> + term_const_ref_expr = -cx; + + BOOST_CHECK(evaluate(term_expr) == 0u - 1u); + BOOST_CHECK(evaluate(term_ref_expr) == 0u - 2u); + BOOST_CHECK(evaluate(term_const_ref_expr) == 0u - 3u); + } + + { + yap::expression< + yap::expr_kind::complement, + bh::tuple<term<uint32_t>>> + term_expr = ~term<uint32_t>{{1u}}; + yap::expression< + yap::expr_kind::complement, + bh::tuple<term_ref<uint32_t>>> + term_ref_expr = ~x; + yap::expression< + yap::expr_kind::complement, + bh::tuple<term_cref<uint32_t>>> + term_const_ref_expr = ~cx; + + BOOST_CHECK(evaluate(term_expr) == 0xfffffffe); + BOOST_CHECK(evaluate(term_ref_expr) == 0xfffffffd); + BOOST_CHECK(evaluate(term_const_ref_expr) == 0xfffffffc); + } + + { + yap::expression< + yap::expr_kind::logical_not, + bh::tuple<term<uint32_t>>> + term_expr = !term<uint32_t>{{1u}}; + yap::expression< + yap::expr_kind::logical_not, + bh::tuple<term_ref<uint32_t>>> + term_ref_expr = !x; + yap::expression< + yap::expr_kind::logical_not, + bh::tuple<term_cref<uint32_t>>> + term_const_ref_expr = !cx; + + BOOST_CHECK(evaluate(term_expr) == false); + BOOST_CHECK(evaluate(term_ref_expr) == false); + BOOST_CHECK(evaluate(term_const_ref_expr) == false); + } + + { + yap::expression<yap::expr_kind::pre_inc, bh::tuple<term<uint32_t>>> + term_expr = ++term<uint32_t>{{1u}}; + yap::expression< + yap::expr_kind::pre_inc, + bh::tuple<term_ref<uint32_t>>> + term_ref_expr = ++x; + yap::expression< + yap::expr_kind::pre_inc, + bh::tuple<term_cref<uint32_t>>> + term_const_ref_expr = ++cx; + (void)term_const_ref_expr; + + BOOST_CHECK(evaluate(term_expr) == 2u); + BOOST_CHECK(evaluate(term_ref_expr) == 3u); + } + } + + { + { + uint32_t i = 1, j = 2, k = 3; + term<uint32_t &> x{{j}}; + term<uint32_t &> const cx{{k}}; + + yap::expression< + yap::expr_kind::address_of, + bh::tuple<term<uint32_t &>>> + term_expr = &term<uint32_t &>{{i}}; + yap::expression< + yap::expr_kind::address_of, + bh::tuple<term_ref<uint32_t &>>> + term_ref_expr = &x; + yap::expression< + yap::expr_kind::address_of, + bh::tuple<term_cref<uint32_t &>>> + term_const_ref_expr = &cx; + + BOOST_CHECK(evaluate(term_expr) == &i); + BOOST_CHECK(evaluate(term_ref_expr) == &j); + BOOST_CHECK(evaluate(term_const_ref_expr) == &k); + } + + { + uint32_t i = 1, j = 2, k = 3; + term<uint32_t *> x{{&j}}; + term<uint32_t *> const cx{{&k}}; + + yap::expression< + yap::expr_kind::dereference, + bh::tuple<term<uint32_t *>>> + term_expr = *term<uint32_t *>{{&i}}; + yap::expression< + yap::expr_kind::dereference, + bh::tuple<term_ref<uint32_t *>>> + term_ref_expr = *x; + yap::expression< + yap::expr_kind::dereference, + bh::tuple<term_cref<uint32_t *>>> + term_const_ref_expr = *cx; + + BOOST_CHECK(evaluate(term_expr) == i); + BOOST_CHECK(evaluate(term_ref_expr) == j); + BOOST_CHECK(evaluate(term_const_ref_expr) == k); + } + } + + return 0; +} diff --git a/src/boost/libs/yap/test/placeholder_eval.cpp b/src/boost/libs/yap/test/placeholder_eval.cpp new file mode 100644 index 000000000..76f9c378c --- /dev/null +++ b/src/boost/libs/yap/test/placeholder_eval.cpp @@ -0,0 +1,65 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<long long I> +using place_term = + boost::yap::terminal<boost::yap::expression, boost::yap::placeholder<I>>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +int test_main(int, char * []) +{ + { + using namespace boost::yap::literals; + + place_term<3> p3 = 3_p; + int i_ = 42; + term<int> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<place_term<3> &>, term<int>>> + expr = p3 + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<place_term<3> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<place_term<3> &>, term<int>>>>> + unevaluated_expr = p3 + std::move(expr); + + { + double result = evaluate(p3, 5, 6, 7); + BOOST_CHECK(result == 7); + } + + { + double result = evaluate(expr, std::string("15"), 3, 1); + BOOST_CHECK(result == 43); + } + + { + double result = evaluate(unevaluated_expr, std::string("15"), 2, 3); + BOOST_CHECK(result == 48); + } + } + + return 0; +} diff --git a/src/boost/libs/yap/test/print.cpp b/src/boost/libs/yap/test/print.cpp new file mode 100644 index 000000000..8d47b5958 --- /dev/null +++ b/src/boost/libs/yap/test/print.cpp @@ -0,0 +1,1605 @@ +// 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 <boost/yap/expression.hpp> +#include <boost/yap/print.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> +#include <regex> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +template<boost::yap::expr_kind Kind, typename Tuple> +struct user_expr +{ + static boost::yap::expr_kind const kind = Kind; + + Tuple elements; +}; + +BOOST_YAP_USER_BINARY_OPERATOR(plus, user_expr, user_expr) + +template<typename T> +using user_term = boost::yap::terminal<user_expr, T>; + +template<typename T> +using user_ref = boost::yap::expression_ref<user_expr, T>; + +struct thing +{}; + +std::string fix_tti(std::string s) +{ + // msvc: remove struct/class prefixes + static const std::regex estruct("(struct|class) "); + s = std::regex_replace(s, estruct, ""); + + // gcc/clang: strip integral literals suffixes + static const std::regex eint("(\\d)u?l{0,2}"); + s = std::regex_replace(s, eint, "$1"); + + return s; +} + +int test_main(int, char * []) +{ + { + BOOST_CHECK( + yap::op_string(yap::expr_kind::terminal) == std::string("term")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::unary_plus) == std::string("+")); + BOOST_CHECK(yap::op_string(yap::expr_kind::negate) == std::string("-")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::dereference) == std::string("*")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::complement) == std::string("~")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::address_of) == std::string("&")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::logical_not) == std::string("!")); + + BOOST_CHECK(yap::op_string(yap::expr_kind::pre_inc) == std::string("++")); + BOOST_CHECK(yap::op_string(yap::expr_kind::pre_dec) == std::string("--")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::post_inc) == std::string("++(int)")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::post_dec) == std::string("--(int)")); + + BOOST_CHECK( + yap::op_string(yap::expr_kind::shift_left) == std::string("<<")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::shift_right) == std::string(">>")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::multiplies) == std::string("*")); + BOOST_CHECK(yap::op_string(yap::expr_kind::divides) == std::string("/")); + BOOST_CHECK(yap::op_string(yap::expr_kind::modulus) == std::string("%")); + + BOOST_CHECK( + yap::op_string(yap::expr_kind::multiplies_assign) == + std::string("*=")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::divides_assign) == + std::string("/=")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::modulus_assign) == + std::string("%=")); + + BOOST_CHECK( + yap::op_string(yap::expr_kind::plus_assign) == std::string("+=")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::minus_assign) == std::string("-=")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::bitwise_and_assign) == + std::string("&=")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::bitwise_or_assign) == + std::string("|=")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::bitwise_xor_assign) == + std::string("^=")); + BOOST_CHECK( + yap::op_string(yap::expr_kind::subscript) == std::string("[]")); + BOOST_CHECK(yap::op_string(yap::expr_kind::if_else) == std::string("?:")); + BOOST_CHECK(yap::op_string(yap::expr_kind::call) == std::string("()")); + BOOST_CHECK( + yap::op_string(yap::expr_kind(-1)) == + std::string("** ERROR: UNKNOWN OPERATOR! **")); + } + + { + user_term<double> unity{1.0}; + int i_ = 42; + user_term<int &&> i{std::move(i_)}; + user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int &&>>> + expr = unity + std::move(i); + user_expr< + yap::expr_kind::plus, + bh::tuple< + user_ref<user_term<double> &>, + user_expr< + yap::expr_kind::plus, + bh::tuple< + user_ref<user_term<double> &>, + user_term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + expr<+> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + user_term<thing> a_thing{bh::make_tuple(thing{})}; + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + user_term<double> const const_unity{1.0}; + user_expr< + yap::expr_kind::plus, + bh::tuple< + user_ref<user_term<double> &>, + user_ref<user_term<double> const &>>> + nonconst_plus_const = unity + const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_plus_const); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + auto nonconst_plus_nonconst_plus_const = unity + nonconst_plus_const; + + { + std::ostringstream oss; + yap::print(oss, nonconst_plus_nonconst_plus_const); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + expr<+> & + term<double>[=1] & + term<double>[=1] const & +)"); + } + + auto const const_nonconst_plus_const = nonconst_plus_const; + auto nonconst_plus_nonconst_plus_const_2 = + unity + const_nonconst_plus_const; + + { + std::ostringstream oss; + yap::print(oss, nonconst_plus_nonconst_plus_const_2); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + expr<+> const & + term<double>[=1] & + term<double>[=1] const & +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity + std::move(i); + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity + std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + expr<+> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_plus_const = unity + const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_plus_const); + BOOST_CHECK(oss.str() == R"(expr<+> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::minus, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity - std::move(i); + yap::expression< + yap::expr_kind::minus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::minus, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity - std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<-> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<-> + term<double>[=1] & + expr<-> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::minus, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_minus_const = unity - const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_minus_const); + BOOST_CHECK(oss.str() == R"(expr<-> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::less, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity < std::move(i); + yap::expression< + yap::expr_kind::less, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::less, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity < std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<<> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<<> + term<double>[=1] & + expr<<> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::less, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_less_const = unity < const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_less_const); + BOOST_CHECK(oss.str() == R"(expr<<> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::greater, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity > std::move(i); + yap::expression< + yap::expr_kind::greater, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::greater, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity > std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<>> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<>> + term<double>[=1] & + expr<>> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::greater, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_greater_const = unity > const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_greater_const); + BOOST_CHECK(oss.str() == R"(expr<>> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::less_equal, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity <= std::move(i); + yap::expression< + yap::expr_kind::less_equal, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::less_equal, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity <= std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<<=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<<=> + term<double>[=1] & + expr<<=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::less_equal, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_less_equal_const = unity <= const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_less_equal_const); + BOOST_CHECK(oss.str() == R"(expr<<=> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::greater_equal, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity >= std::move(i); + yap::expression< + yap::expr_kind::greater_equal, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::greater_equal, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity >= std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<>=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<>=> + term<double>[=1] & + expr<>=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::greater_equal, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_greater_equal_const = unity >= const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_greater_equal_const); + BOOST_CHECK(oss.str() == R"(expr<>=> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::equal_to, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity == std::move(i); + yap::expression< + yap::expr_kind::equal_to, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::equal_to, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity == std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<==> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<==> + term<double>[=1] & + expr<==> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::equal_to, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_equal_to_const = unity == const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_equal_to_const); + BOOST_CHECK(oss.str() == R"(expr<==> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::not_equal_to, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity != std::move(i); + yap::expression< + yap::expr_kind::not_equal_to, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::not_equal_to, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity != std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<!=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<!=> + term<double>[=1] & + expr<!=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::not_equal_to, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_not_equal_to_const = unity != const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_not_equal_to_const); + BOOST_CHECK(oss.str() == R"(expr<!=> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::logical_or, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity || std::move(i); + yap::expression< + yap::expr_kind::logical_or, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::logical_or, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity || std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<||> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<||> + term<double>[=1] & + expr<||> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::logical_or, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_logical_or_const = unity || const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_logical_or_const); + BOOST_CHECK(oss.str() == R"(expr<||> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::logical_and, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity && std::move(i); + yap::expression< + yap::expr_kind::logical_and, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::logical_and, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity && std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<&&> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<&&> + term<double>[=1] & + expr<&&> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::logical_and, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_logical_and_const = unity && const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_logical_and_const); + BOOST_CHECK(oss.str() == R"(expr<&&> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::bitwise_and, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity & std::move(i); + yap::expression< + yap::expr_kind::bitwise_and, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::bitwise_and, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity & std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<&> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<&> + term<double>[=1] & + expr<&> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::bitwise_and, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_bitwise_and_const = unity & const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_bitwise_and_const); + BOOST_CHECK(oss.str() == R"(expr<&> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::bitwise_or, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity | std::move(i); + yap::expression< + yap::expr_kind::bitwise_or, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::bitwise_or, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity | std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<|> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<|> + term<double>[=1] & + expr<|> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::bitwise_or, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_bitwise_or_const = unity | const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_bitwise_or_const); + BOOST_CHECK(oss.str() == R"(expr<|> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::bitwise_xor, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity ^ std::move(i); + yap::expression< + yap::expr_kind::bitwise_xor, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::bitwise_xor, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity ^ std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<^> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<^> + term<double>[=1] & + expr<^> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::bitwise_xor, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_bitwise_xor_const = unity ^ const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_bitwise_xor_const); + BOOST_CHECK(oss.str() == R"(expr<^> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::comma, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = (unity, std::move(i)); + yap::expression< + yap::expr_kind::comma, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::comma, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = (unity, std::move(expr)); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<,> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<,> + term<double>[=1] & + expr<,> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::comma, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_comma_const = (unity, const_unity); + + { + std::ostringstream oss; + yap::print(oss, nonconst_comma_const); + BOOST_CHECK(oss.str() == R"(expr<,> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::mem_ptr, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity->*std::move(i); + yap::expression< + yap::expr_kind::mem_ptr, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::mem_ptr, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity->*std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<->*> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<->*> + term<double>[=1] & + expr<->*> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::mem_ptr, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_mem_ptr_const = unity->*const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_mem_ptr_const); + BOOST_CHECK(oss.str() == R"(expr<->*> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::assign, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity = std::move(i); + yap::expression< + yap::expr_kind::assign, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::assign, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity = std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<=> + term<double>[=1] & + expr<=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::shift_left_assign, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity <<= std::move(i); + yap::expression< + yap::expr_kind::shift_left_assign, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::shift_left_assign, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity <<= std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<<<=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<<<=> + term<double>[=1] & + expr<<<=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::shift_left_assign, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_shift_left_assign_const = unity <<= const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_shift_left_assign_const); + BOOST_CHECK(oss.str() == R"(expr<<<=> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + term<double> unity{1.0}; + int i_ = 42; + term<int &&> i{std::move(i_)}; + yap::expression< + yap::expr_kind::shift_right_assign, + bh::tuple<ref<term<double> &>, term<int &&>>> + expr = unity >>= std::move(i); + yap::expression< + yap::expr_kind::shift_right_assign, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::shift_right_assign, + bh::tuple<ref<term<double> &>, term<int &&>>>>> + unevaluated_expr = unity >>= std::move(expr); + + { + std::ostringstream oss; + yap::print(oss, unity); + BOOST_CHECK(oss.str() == R"(term<double>[=1] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, expr); + BOOST_CHECK(oss.str() == R"(expr<>>=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + { + std::ostringstream oss; + yap::print(oss, unevaluated_expr); + BOOST_CHECK(oss.str() == R"(expr<>>=> + term<double>[=1] & + expr<>>=> + term<double>[=1] & + term<int &&>[=42] +)"); + } + + term<thing> a_thing(thing{}); + + { + std::ostringstream oss; + yap::print(oss, a_thing); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>] +)"); + } + + term<double> const const_unity{1.0}; + yap::expression< + yap::expr_kind::shift_right_assign, + bh::tuple<ref<term<double> &>, ref<term<double> const &>>> + nonconst_shift_right_assign_const = unity >>= const_unity; + + { + std::ostringstream oss; + yap::print(oss, nonconst_shift_right_assign_const); + BOOST_CHECK(oss.str() == R"(expr<>>=> + term<double>[=1] & + term<double>[=1] const & +)"); + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, 1_p); + BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1] +)"); + } + } + + { + using namespace yap::literals; + std::ostringstream oss; + yap::print(oss, replace_placeholders(1_p + 2_p,7,8)); + BOOST_CHECK(fix_tti(oss.str()) == R"(expr<+> + term<int>[=7] + term<int>[=8] +)"); + } + + return 0; +} diff --git a/src/boost/libs/yap/test/reference_returns.cpp b/src/boost/libs/yap/test/reference_returns.cpp new file mode 100644 index 000000000..e03e9a3c5 --- /dev/null +++ b/src/boost/libs/yap/test/reference_returns.cpp @@ -0,0 +1,89 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +namespace yap = boost::yap; + +namespace reference_returning { + + struct number + { + double value; + }; + + number a_result{3.0}; + number const the_result{13.0}; + + number const & operator+(number a, number b) { return the_result; } + + number & operator-(number a, number b) { return a_result; } +} + +int test_main(int, char * []) +{ + { + term<reference_returning::number> unity = {{1.0}}; + auto plus_expr = unity + reference_returning::number{1.0}; + + { + reference_returning::number const & n = evaluate(plus_expr); + BOOST_CHECK(&n == &reference_returning::the_result); + } + + using plus_eval_type = decltype(evaluate(plus_expr)); + BOOST_MPL_ASSERT((std::is_same< + plus_eval_type, + reference_returning::number const &>)); + + auto minus_expr = unity - reference_returning::number{1.0}; + + { + reference_returning::number & n = evaluate(minus_expr); + BOOST_CHECK(&n == &reference_returning::a_result); + } + + using minus_eval_type = decltype(evaluate(minus_expr)); + BOOST_MPL_ASSERT((std::is_same< + minus_eval_type, + reference_returning::number &>)); + + using namespace yap::literals; + + { + reference_returning::number & n = + evaluate(1_p, reference_returning::a_result); + BOOST_CHECK(&n == &reference_returning::a_result); + } + + using a_eval_type = decltype(evaluate(1_p, reference_returning::a_result)); + BOOST_MPL_ASSERT( + (std::is_same< + a_eval_type, + reference_returning::number &>)); + + { + reference_returning::number const & n = + evaluate(1_p, reference_returning::the_result); + BOOST_CHECK(&n == &reference_returning::the_result); + } + + using the_eval_type = decltype(evaluate(1_p, reference_returning::the_result)); + BOOST_MPL_ASSERT( + (std::is_same< + the_eval_type, + reference_returning::number const &>)); + } + + return 0; +} diff --git a/src/boost/libs/yap/test/right.cpp b/src/boost/libs/yap/test/right.cpp new file mode 100644 index 000000000..1adb7fa09 --- /dev/null +++ b/src/boost/libs/yap/test/right.cpp @@ -0,0 +1,275 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +template<boost::yap::expr_kind Kind, typename Tuple> +struct user_expr +{ + static boost::yap::expr_kind const kind = Kind; + + Tuple elements; +}; + +BOOST_YAP_USER_BINARY_OPERATOR(plus, user_expr, user_expr) + +template<typename T> +using user_term = boost::yap::terminal<user_expr, T>; + +template<typename T> +using user_ref = boost::yap::expression_ref<user_expr, T>; + + +int test_main(int, char * []) +{ + { + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + + { + plus_expr_type plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(std::move(plus_expr))), + term<int> &&>)); + } + + { + plus_expr_type plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::right(plus_expr)), term<int> &>)); + } + + { + plus_expr_type const plus_expr = unity + term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr)), + term<int> const &>)); + } + + { + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + plus_expr_type plus_expr = unity + term<int>{{1}}; + + using plus_plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<plus_expr_type &>, term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same< + decltype(yap::right(std::move(plus_expr_ref))), + term<int> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + term<int> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + term<int> &>)); + } + } + + { + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + plus_expr_type const plus_expr = unity + term<int>{{1}}; + + using plus_plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<plus_expr_type const &>, term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same< + decltype(yap::right(std::move(plus_expr_ref))), + term<int> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + term<int> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = plus_expr + term<int>{{1}}; + ref<plus_expr_type const &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + term<int> const &>)); + } + } + } + + { + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + + { + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(std::move(plus_expr))), + user_term<int> &&>)); + } + + { + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr)), + user_term<int> &>)); + } + + { + plus_expr_type const plus_expr = unity + user_term<int>{{1}}; + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr)), + user_term<int> const &>)); + } + + { + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + + using plus_plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<plus_expr_type &>, user_term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same< + decltype(yap::right(std::move(plus_expr_ref))), + user_term<int> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + user_term<int> &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + user_term<int> &>)); + } + } + + { + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + plus_expr_type const plus_expr = unity + user_term<int>{{1}}; + + using plus_plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<plus_expr_type const &>, user_term<int>>>; + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same< + decltype(yap::right(std::move(plus_expr_ref))), + user_term<int> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type const &> plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + user_term<int> const &>)); + } + + { + plus_plus_expr_type plus_plus_expr = + plus_expr + user_term<int>{{1}}; + user_ref<plus_expr_type const &> const plus_expr_ref = + bh::front(plus_plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::right(plus_expr_ref)), + user_term<int> const &>)); + } + } + } + +#ifndef _MSC_VER // Tsk, tsk. + { + using term_t = term<int>; + constexpr auto expr = term_t{13} + term_t{42}; + constexpr auto result1 = expr.right().value(); + constexpr auto result2 = yap::value(right(expr)); + (void)result1; + (void)result2; + } +#endif + + return 0; +} diff --git a/src/boost/libs/yap/test/supplied_transforms.cpp b/src/boost/libs/yap/test/supplied_transforms.cpp new file mode 100644 index 000000000..fa70eb439 --- /dev/null +++ b/src/boost/libs/yap/test/supplied_transforms.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Paul Keir +// +// 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 <boost/yap/yap.hpp> + +#include <boost/test/minimal.hpp> + +namespace yap = boost::yap; + +int test_main(int, char * []) +{ + // Test replacements(), which returns a transform object + { + using namespace boost::yap::literals; + + auto expr_in = 1_p * 2_p; + auto xform = yap::replacements(6,9); + auto expr_out = yap::transform(expr_in,xform); + auto result = yap::evaluate(expr_out); + BOOST_CHECK(result == 54); + } + + // Test evaluation(), which returns a transform object + { + using namespace boost::yap::literals; + + auto expr_in = 1_p * 2_p; + auto xform = yap::evaluation(7,10); + auto result = yap::transform(expr_in,xform); + BOOST_CHECK(result == 70); + } + + // Test replace_placeholders(), which returns an expression + { + using namespace boost::yap::literals; + + auto expr_in = 1_p * 2_p; + auto expr_out = yap::replace_placeholders(expr_in,8,11); + auto result = yap::evaluate(expr_out); + BOOST_CHECK(result == 88); + } + + return 0; +} + diff --git a/src/boost/libs/yap/test/transform.cpp b/src/boost/libs/yap/test/transform.cpp new file mode 100644 index 000000000..edca16702 --- /dev/null +++ b/src/boost/libs/yap/test/transform.cpp @@ -0,0 +1,78 @@ +// 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 <boost/yap/yap.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/test/minimal.hpp> + +#include <sstream> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::minimal_expr, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +struct iota_terminal_transform +{ + template<typename T> + auto operator()(boost::yap::expr_tag<boost::yap::expr_kind::terminal>, T && t) + { + return boost::yap::make_terminal(index_++); + } + + template<typename CallableExpr, typename... Arg> + auto operator()(boost::yap::expr_tag<boost::yap::expr_kind::call>, + CallableExpr callable, Arg &&... arg) + { + return boost::yap::make_expression<boost::yap::expr_kind::call>( + callable, boost::yap::transform(arg, *this)...); + } + + int index_; +}; + +struct plus_expr_t +{ + static yap::expr_kind const kind = yap::expr_kind::plus; + + bh::tuple<term<int>, term<int>> elements; +}; + +int test_main(int, char * []) +{ + // Each node instantiated from from yap::expression. + { + auto plus_expr = yap::terminal<yap::expression, int>{{5}} + 6; + + BOOST_CHECK(yap::evaluate(plus_expr) == 11); + + BOOST_CHECK( + yap::evaluate( + yap::transform(plus_expr, iota_terminal_transform{0})) == 1); + } + + // Each node instantiated from from yap::minimal_expr. + { + yap::minimal_expr<yap::expr_kind::plus, bh::tuple<term<int>, term<int>>> + plus_expr; + + yap::evaluate(yap::transform(plus_expr, iota_terminal_transform{0}), 1); + } + + // Leaves are instantiated from from yap::minimal_expr; nonterminal + // expr_kind::plus does not even come from a template. + { + plus_expr_t plus_expr; + + yap::evaluate(yap::transform(plus_expr, iota_terminal_transform{0}), 1); + } + + return 0; +} diff --git a/src/boost/libs/yap/test/user_expression_transform_1.cpp b/src/boost/libs/yap/test/user_expression_transform_1.cpp new file mode 100644 index 000000000..b58b6e25d --- /dev/null +++ b/src/boost/libs/yap/test/user_expression_transform_1.cpp @@ -0,0 +1,948 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +namespace user { + + struct number + { + double value; + + friend number operator+(number lhs, number rhs) + { + return number{lhs.value + rhs.value}; + } + + friend number operator-(number lhs, number rhs) + { + return number{lhs.value - rhs.value}; + } + + friend number operator*(number lhs, number rhs) + { + return number{lhs.value * rhs.value}; + } + + friend number operator-(number n) { return number{-n.value}; } + + friend bool operator<(number lhs, double rhs) + { + return lhs.value < rhs; + } + + friend bool operator<(double lhs, number rhs) + { + return lhs < rhs.value; + } + }; + + number naxpy(number a, number x, number y) + { + return number{a.value * x.value + y.value + 10.0}; + } + + struct empty_xform + {}; + + struct eval_xform_tag + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::terminal>, user::number const & n) + { + return n; + } + }; + + struct eval_xform_expr + { + decltype(auto) operator()(term<user::number> const & expr) + { + return ::boost::yap::value(expr); + } + }; + + struct eval_xform_both + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::terminal>, user::number const & n) + { + return n; + } + + decltype(auto) operator()(term<user::number> const & expr) + { + throw std::logic_error("Oops! Picked the wrong overload!"); + return ::boost::yap::value(expr); + } + }; + + struct plus_to_minus_xform_tag + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::plus>, + user::number const & lhs, + user::number const & rhs) + { + return yap::make_expression<yap::expr_kind::minus>( + term<user::number>{lhs}, term<user::number>{rhs}); + } + }; + + struct plus_to_minus_xform_expr + { + template<typename Expr1, typename Expr2> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple<Expr1, Expr2>> const & expr) + { + return yap::make_expression<yap::expr_kind::minus>( + ::boost::yap::left(expr), ::boost::yap::right(expr)); + } + }; + + struct plus_to_minus_xform_both + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::plus>, + user::number const & lhs, + user::number const & rhs) + { + return yap::make_expression<yap::expr_kind::minus>( + term<user::number>{lhs}, term<user::number>{rhs}); + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple<Expr1, Expr2>> const & expr) + { + throw std::logic_error("Oops! Picked the wrong overload!"); + return yap::make_expression<yap::expr_kind::minus>( + ::boost::yap::left(expr), ::boost::yap::right(expr)); + } + }; + + struct term_nonterm_xform_tag + { + auto operator()( + yap::expr_tag<yap::expr_kind::terminal>, user::number const & n) + { + return yap::make_terminal(n * user::number{2.0}); + } + + auto operator()( + yap::expr_tag<yap::expr_kind::plus>, + user::number const & lhs, + user::number const & rhs) + { + return yap::make_expression<yap::expr_kind::minus>( + yap::transform(::boost::yap::make_terminal(lhs), *this), + yap::transform(::boost::yap::make_terminal(rhs), *this)); + } + }; + + struct term_nonterm_xform_expr + { + decltype(auto) operator()(term<user::number> const & expr) + { + return yap::make_terminal( + ::boost::yap::value(expr) * user::number{2.0}); + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple<Expr1, Expr2>> const & expr) + { + return yap::make_expression<yap::expr_kind::minus>( + yap::transform(::boost::yap::left(expr), *this), + yap::transform(::boost::yap::right(expr), *this)); + } + }; + + struct term_nonterm_xform_both + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::terminal>, user::number const & n) + { + return yap::make_terminal(n * user::number{2.0}); + } + + decltype(auto) operator()(term<user::number> const & expr) + { + return yap::make_terminal( + ::boost::yap::value(expr) * user::number{2.0}); + } + + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::plus>, + user::number const & lhs, + user::number const & rhs) + { + return yap::make_expression<yap::expr_kind::minus>( + yap::transform(::boost::yap::make_terminal(lhs), *this), + yap::transform(::boost::yap::make_terminal(rhs), *this)); + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple<Expr1, Expr2>> const & expr) + { + return yap::make_expression<yap::expr_kind::minus>( + yap::transform(::boost::yap::left(expr), *this), + yap::transform(::boost::yap::right(expr), *this)); + } + }; + + struct eval_term_nonterm_xform_tag + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::terminal>, user::number const & n) + { + return n * user::number{2.0}; + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::plus>, + Expr1 const & lhs, + Expr2 const & rhs) + { + return boost::yap::transform(::boost::yap::as_expr(lhs), *this) - + boost::yap::transform(::boost::yap::as_expr(rhs), *this); + } + }; + + struct eval_term_nonterm_xform_expr + { + decltype(auto) operator()(term<user::number> const & expr) + { + return ::boost::yap::value(expr) * user::number{2.0}; + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple<Expr1, Expr2>> const & expr) + { + return boost::yap::transform(::boost::yap::left(expr), *this) - + boost::yap::transform(::boost::yap::right(expr), *this); + } + }; + + struct eval_term_nonterm_xform_both + { + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::terminal>, user::number const & n) + { + return n * user::number{2.0}; + } + + decltype(auto) operator()(term<user::number> const & expr) + { + return ::boost::yap::value(expr) * user::number{2.0}; + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::plus>, + Expr1 const & lhs, + Expr2 const & rhs) + { + return boost::yap::transform(::boost::yap::as_expr(lhs), *this) - + boost::yap::transform(::boost::yap::as_expr(rhs), *this); + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple<Expr1, Expr2>> const & expr) + { + return boost::yap::transform(::boost::yap::left(expr), *this) - + boost::yap::transform(::boost::yap::right(expr), *this); + } + }; + + decltype(auto) + naxpy_eager_nontemplate_xform(yap::expression< + yap::expr_kind::plus, + bh::tuple< + yap::expression< + yap::expr_kind::multiplies, + bh::tuple< + ref<term<user::number> &>, + ref<term<user::number> &>>>, + ref<term<user::number> &>>> const & expr) + { + auto a = evaluate(expr.left().left()); + auto x = evaluate(expr.left().right()); + auto y = evaluate(expr.right()); + return yap::make_terminal(naxpy(a, x, y)); + } + + decltype(auto) + naxpy_lazy_nontemplate_xform(yap::expression< + yap::expr_kind::plus, + bh::tuple< + yap::expression< + yap::expr_kind::multiplies, + bh::tuple< + ref<term<user::number> &>, + ref<term<user::number> &>>>, + ref<term<user::number> &>>> const & expr) + { + decltype(auto) a = expr.left().left().value(); + decltype(auto) x = expr.left().right().value(); + decltype(auto) y = expr.right().value(); + return yap::make_terminal(naxpy)(a, x, y); + } + + struct naxpy_xform + { + template<typename Expr1, typename Expr2, typename Expr3> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple< + yap::expression< + yap::expr_kind::multiplies, + bh::tuple<Expr1, Expr2>>, + Expr3>> const & expr) + { + return yap::make_terminal(naxpy)( + transform(expr.left().left(), naxpy_xform{}), + transform(expr.left().right(), naxpy_xform{}), + transform(expr.right(), naxpy_xform{})); + } + }; + + + // unary transforms + + struct disable_negate_xform_tag + { + auto + operator()(yap::expr_tag<yap::expr_kind::negate>, user::number value) + { + return yap::make_terminal(std::move(value)); + } + + template<typename Expr> + auto + operator()(yap::expr_tag<yap::expr_kind::negate>, Expr const & expr) + { + return expr; + } + }; + + struct disable_negate_xform_expr + { + template<typename Expr> + decltype(auto) operator()( + yap::expression<yap::expr_kind::negate, bh::tuple<Expr>> const & + expr) + { + return ::boost::yap::value(expr); + } + }; + + struct disable_negate_xform_both + { + decltype(auto) + operator()(yap::expr_tag<yap::expr_kind::negate>, user::number value) + { + return yap::make_terminal(std::move(value)); + } + + template<typename Expr> + decltype(auto) + operator()(yap::expr_tag<yap::expr_kind::negate>, Expr const & expr) + { + return expr; + } + + template<typename Expr> + decltype(auto) operator()( + yap::expression<yap::expr_kind::negate, bh::tuple<Expr>> const & + expr) + { + throw std::logic_error("Oops! Picked the wrong overload!"); + return ::boost::yap::value(expr); + } + }; + + + // ternary transforms + + //[ tag_xform + struct ternary_to_else_xform_tag + { + template<typename Expr> + decltype(auto) operator()( + boost::yap::expr_tag<yap::expr_kind::if_else>, + Expr const & cond, + user::number then, + user::number else_) + { + return boost::yap::make_terminal(std::move(else_)); + } + }; + //] + + //[ expr_xform + struct ternary_to_else_xform_expr + { + template<typename Cond, typename Then, typename Else> + decltype(auto) + operator()(boost::yap::expression< + boost::yap::expr_kind::if_else, + boost::hana::tuple<Cond, Then, Else>> const & expr) + { + return ::boost::yap::else_(expr); + } + }; + //] + + struct ternary_to_else_xform_both + { + template<typename Expr> + decltype(auto) operator()( + yap::expr_tag<yap::expr_kind::if_else>, + Expr const & cond, + user::number then, + user::number else_) + { + return yap::make_terminal(std::move(else_)); + } + + template<typename Cond, typename Then, typename Else> + decltype(auto) operator()(yap::expression< + yap::expr_kind::if_else, + bh::tuple<Cond, Then, Else>> const & expr) + { + throw std::logic_error("Oops! Picked the wrong overload!"); + return ::boost::yap::else_(expr); + } + }; +} + +auto double_to_float(term<double> expr) +{ + return term<float>{(float)expr.value()}; +} + +auto check_unique_ptrs_equal_7(term<std::unique_ptr<int>> && expr) +{ + using namespace boost::hana::literals; + BOOST_CHECK(*expr.elements[0_c] == 7); + return std::move(expr); +} + +int test_main(int, char * []) +{ + { + term<user::number> a{{1.0}}; + term<user::number> x{{42.0}}; + term<user::number> y{{3.0}}; + + { + auto expr = a; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 1); + } + + { + auto transformed_expr = transform(expr, user::empty_xform{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 1); + } + + { + auto transformed_expr = transform(expr, user::eval_xform_tag{}); + BOOST_CHECK(transformed_expr.value == 1); + } + + { + auto transformed_expr = + transform(expr, user::eval_xform_expr{}); + BOOST_CHECK(transformed_expr.value == 1); + } + + { + auto transformed_expr = + transform(expr, user::eval_xform_both{}); + BOOST_CHECK(transformed_expr.value == 1); + } + } + + { + auto expr = x + y; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45); + } + + { + auto transformed_expr = + transform(expr, user::plus_to_minus_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39); + } + + { + auto transformed_expr = + transform(expr, user::plus_to_minus_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39); + } + + { + auto transformed_expr = + transform(expr, user::plus_to_minus_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39); + } + } + + { + auto expr = x + user::number{3.0}; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39 * 2); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39 * 2); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39 * 2); + } + } + + { + auto expr = x + y; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39 * 2); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39 * 2); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 39 * 2); + } + } + + { + auto expr = (x + y) + user::number{1.0}; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 46); + } + + { + // Differs from those below, because it matches terminals, not + // expressions. + auto transformed_expr = + transform(expr, user::term_nonterm_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 40 * 2); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 38 * 2); + } + + { + auto transformed_expr = + transform(expr, user::term_nonterm_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 38 * 2); + } + } + + { + auto expr = x + user::number{3.0}; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_tag{}); + BOOST_CHECK(result.value == 39 * 2); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_expr{}); + BOOST_CHECK(result.value == 39 * 2); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_both{}); + BOOST_CHECK(result.value == 39 * 2); + } + } + + { + auto expr = x + y; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_tag{}); + BOOST_CHECK(result.value == 39 * 2); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_expr{}); + BOOST_CHECK(result.value == 39 * 2); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_both{}); + BOOST_CHECK(result.value == 39 * 2); + } + } + + { + auto expr = (x + y) + user::number{1.0}; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 46); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_tag{}); + BOOST_CHECK(result.value == 38 * 2); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_expr{}); + BOOST_CHECK(result.value == 38 * 2); + } + + { + user::number result = + transform(expr, user::eval_term_nonterm_xform_both{}); + BOOST_CHECK(result.value == 38 * 2); + } + } + + { + auto expr = a * x + y; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45); + } + + auto transformed_expr = + transform(expr, user::naxpy_eager_nontemplate_xform); + { + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 55); + } + } + + { + auto expr = a + (a * x + y); + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 46); + } + + auto transformed_expr = + transform(expr, user::naxpy_eager_nontemplate_xform); + { + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 56); + } + } + + { + auto expr = a * x + y; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45); + } + + auto transformed_expr = + transform(expr, user::naxpy_lazy_nontemplate_xform); + { + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 55); + } + } + + { + auto expr = a + (a * x + y); + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 46); + } + + auto transformed_expr = + transform(expr, user::naxpy_lazy_nontemplate_xform); + { + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 56); + } + } + + { + auto expr = (a * x + y) * (a * x + y) + (a * x + y); + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 45 * 45 + 45); + } + + auto transformed_expr = transform(expr, user::naxpy_xform{}); + { + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 55 * 55 + 55 + 10); + } + } + } + + { + term<double> unity{1.0}; + term<std::unique_ptr<int>> i{new int{7}}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<std::unique_ptr<int>>>> + expr_1 = unity + std::move(i); + + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + yap::expression< + yap::expr_kind::plus, + bh::tuple< + ref<term<double> &>, + term<std::unique_ptr<int>>>>>> + expr_2 = unity + std::move(expr_1); + + auto transformed_expr = transform(std::move(expr_2), double_to_float); + + transform(std::move(transformed_expr), check_unique_ptrs_equal_7); + } + + { + term<user::number> a{{1.0}}; + term<user::number> x{{42.0}}; + term<user::number> y{{3.0}}; + + { + auto expr = -x; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == -42); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 42); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 42); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 42); + } + } + + { + auto expr = a * -x + y; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == -39); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 45); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 45); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 45); + } + } + + { + auto expr = -(x + y); + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == -45); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 45); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 45); + } + + { + auto transformed_expr = + transform(expr, user::disable_negate_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 45); + } + } + } + + { + term<user::number> a{{1.0}}; + term<user::number> x{{42.0}}; + term<user::number> y{{3.0}}; + + { + auto expr = if_else(0 < a, x, y); + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 42); + } + + { + auto transformed_expr = + transform(expr, user::ternary_to_else_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 3); + } + + { + auto transformed_expr = + transform(expr, user::ternary_to_else_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 3); + } + + { + auto transformed_expr = + transform(expr, user::ternary_to_else_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 3); + } + } + + { + auto expr = y * if_else(0 < a, x, y) + user::number{0.0}; + { + user::number result = evaluate(expr); + BOOST_CHECK(result.value == 126); + } + + { + auto transformed_expr = + transform(expr, user::ternary_to_else_xform_tag{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 9); + } + + { + auto transformed_expr = + transform(expr, user::ternary_to_else_xform_expr{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 9); + } + + { + auto transformed_expr = + transform(expr, user::ternary_to_else_xform_both{}); + user::number result = evaluate(transformed_expr); + BOOST_CHECK(result.value == 9); + } + } + } + + return 0; +} diff --git a/src/boost/libs/yap/test/user_expression_transform_2.cpp b/src/boost/libs/yap/test/user_expression_transform_2.cpp new file mode 100644 index 000000000..da231b4b2 --- /dev/null +++ b/src/boost/libs/yap/test/user_expression_transform_2.cpp @@ -0,0 +1,257 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +namespace user { + + struct number + { + double value; + }; + + struct eval_xform + { + auto + operator()(yap::expr_tag<yap::expr_kind::terminal>, number const & n) + { + return n; + } + + template<typename Expr> + decltype(auto) operator()( + yap::expression<yap::expr_kind::negate, bh::tuple<Expr>> const & + expr) + { + number const n = transform(yap::value(expr), *this); + return number{-n.value}; + } + + template<typename Expr1, typename Expr2> + decltype(auto) operator()(yap::expression< + yap::expr_kind::plus, + bh::tuple<Expr1, Expr2>> 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<typename Expr> +auto make_ref(Expr && expr) +{ + using type = yap::detail::operand_type_t<yap::expression, Expr>; + return yap::detail::make_operand<type>{}(static_cast<Expr &&>(expr)); +} + +int test_main(int, char * []) +{ +{ + { + term<user::number> 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<user::number>{{1.0}}, user::eval_xform{}); + BOOST_CHECK(result.value == -1); + } +} + +{ + term<user::number> a{{1.0}}; + term<user::number> 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; +} diff --git a/src/boost/libs/yap/test/value.cpp b/src/boost/libs/yap/test/value.cpp new file mode 100644 index 000000000..5ca933afc --- /dev/null +++ b/src/boost/libs/yap/test/value.cpp @@ -0,0 +1,208 @@ +// 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 <boost/yap/expression.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/test/minimal.hpp> + + +template<typename T> +using term = boost::yap::terminal<boost::yap::expression, T>; + +template<typename T> +using ref = boost::yap::expression_ref<boost::yap::expression, T>; + +namespace yap = boost::yap; +namespace bh = boost::hana; + + +template<boost::yap::expr_kind Kind, typename Tuple> +struct user_expr +{ + static boost::yap::expr_kind const kind = Kind; + + Tuple elements; +}; + +BOOST_YAP_USER_BINARY_OPERATOR(plus, user_expr, user_expr) + +template<typename T> +using user_term = boost::yap::terminal<user_expr, T>; + +template<typename T> +using user_ref = boost::yap::expression_ref<user_expr, T>; + + +int test_main(int, char * []) +{ + { + { + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(1.0)), double &&>)); + BOOST_CHECK(yap::value(1.0) == 1.0); + } + + { + double d = 2.0; + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(d)), double &>)); + BOOST_CHECK(yap::value(d) == 2.0); + } + + { + double const d = 3.0; + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(d)), double const &>)); + BOOST_CHECK(yap::value(d) == 3.0); + } + } + + { + { + term<double> td = {{1.0}}; + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(std::move(td))), double &&>)); + BOOST_CHECK(yap::value(std::move(td)) == 1.0); + } + + { + term<double> td = {{2.0}}; + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(td)), double &>)); + BOOST_CHECK(yap::value(td) == 2.0); + } + + { + term<double> const td = {{3.0}}; + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(td)), double const &>)); + BOOST_CHECK(yap::value(td) == 3.0); + } + + term<double> unity = {{1.0}}; + using plus_expr_type = yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> &>, term<int>>>; + plus_expr_type plus_expr = unity + term<int>{{1}}; + + { + ref<term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(std::move(ref))), double &>)); + } + + { + ref<term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>)); + } + + { + ref<term<double> &> const ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>)); + } + + { + term<double> const unity = {{1.0}}; + yap::expression< + yap::expr_kind::plus, + bh::tuple<ref<term<double> const &>, term<int>>> + plus_expr = unity + term<int>{{1}}; + + { + ref<term<double> const &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::value(std::move(ref))), + double const &>)); + } + + { + ref<term<double> const &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(ref)), double const &>)); + } + + { + ref<term<double> const &> const ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(ref)), double const &>)); + } + } + } + + { + { + user_term<double> td = {{1.0}}; + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(std::move(td))), double &&>)); + BOOST_CHECK(yap::value(std::move(td)) == 1.0); + } + + { + user_term<double> td = {{2.0}}; + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(td)), double &>)); + BOOST_CHECK(yap::value(td) == 2.0); + } + + { + user_term<double> const td = {{3.0}}; + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(td)), double const &>)); + BOOST_CHECK(yap::value(td) == 3.0); + } + + user_term<double> unity = {{1.0}}; + using plus_expr_type = user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> &>, user_term<int>>>; + plus_expr_type plus_expr = unity + user_term<int>{{1}}; + + { + user_ref<user_term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(std::move(ref))), double &>)); + } + + { + user_ref<user_term<double> &> ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>)); + } + + { + user_ref<user_term<double> &> const ref = bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>)); + } + + { + user_term<double> const unity = {{1.0}}; + user_expr< + yap::expr_kind::plus, + bh::tuple<user_ref<user_term<double> const &>, user_term<int>>> + plus_expr = unity + user_term<int>{{1}}; + + { + user_ref<user_term<double> const &> ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT((std::is_same< + decltype(yap::value(std::move(ref))), + double const &>)); + } + + { + user_ref<user_term<double> const &> ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(ref)), double const &>)); + } + + { + user_ref<user_term<double> const &> const ref = + bh::front(plus_expr.elements); + BOOST_MPL_ASSERT( + (std::is_same<decltype(yap::value(ref)), double const &>)); + } + } + } + + return 0; +} diff --git a/src/boost/libs/yap/test/vector_alloc_test.cpp b/src/boost/libs/yap/test/vector_alloc_test.cpp new file mode 100644 index 000000000..8ab808c21 --- /dev/null +++ b/src/boost/libs/yap/test/vector_alloc_test.cpp @@ -0,0 +1,172 @@ +// 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 <boost/yap/yap.hpp> + +#include <vector> +#include <iostream> + +#include <boost/test/minimal.hpp> + + +int allocations = 0; + +void * operator new(std::size_t size) +{ + ++allocations; + void * retval = malloc(size); + if (!retval) + throw std::bad_alloc(); + return retval; +} + +void operator delete(void * ptr) noexcept { free(ptr); } + + +struct take_nth +{ + template<typename T> + auto operator()( + boost::yap::expr_tag<boost::yap::expr_kind::terminal>, + std::vector<T> const & vec) + { + return boost::yap::make_terminal(vec[n]); + } + + std::size_t n; +}; + +struct equal_sizes_impl +{ + template<typename T> + auto operator()( + boost::yap::expr_tag<boost::yap::expr_kind::terminal>, + std::vector<T> const & vec) + { + auto const expr_size = vec.size(); + if (expr_size != size) + value = false; + return 0; + } + + std::size_t const size; + bool value; +}; + +template<typename Expr> +bool equal_sizes(std::size_t size, Expr const & expr) +{ + equal_sizes_impl impl{size, true}; + boost::yap::transform(boost::yap::as_expr(expr), impl); + return impl.value; +} + + +template<typename T, typename Expr> +std::vector<T> & assign(std::vector<T> & vec, Expr const & e) +{ + decltype(auto) expr = boost::yap::as_expr(e); + assert(equal_sizes(vec.size(), expr)); + for (std::size_t i = 0, size = vec.size(); i < size; ++i) { + vec[i] = boost::yap::evaluate( + boost::yap::transform(boost::yap::as_expr(expr), take_nth{i})); + } + return vec; +} + +template<typename T, typename Expr> +std::vector<T> & operator+=(std::vector<T> & vec, Expr const & e) +{ + decltype(auto) expr = boost::yap::as_expr(e); + assert(equal_sizes(vec.size(), expr)); + for (std::size_t i = 0, size = vec.size(); i < size; ++i) { + vec[i] += boost::yap::evaluate( + boost::yap::transform(boost::yap::as_expr(expr), take_nth{i})); + } + return vec; +} + +template<typename T> +struct is_vector : std::false_type +{ +}; + +template<typename T, typename A> +struct is_vector<std::vector<T, A>> : std::true_type +{ +}; + +BOOST_YAP_USER_UDT_UNARY_OPERATOR( + negate, boost::yap::expression, is_vector); // - +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + multiplies, boost::yap::expression, is_vector); // * +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + divides, boost::yap::expression, is_vector); // / +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + modulus, boost::yap::expression, is_vector); // % +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + plus, boost::yap::expression, is_vector); // + +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + minus, boost::yap::expression, is_vector); // - +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + less, boost::yap::expression, is_vector); // < +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + greater, boost::yap::expression, is_vector); // > +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + less_equal, boost::yap::expression, is_vector); // <= +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + greater_equal, boost::yap::expression, is_vector); // >= +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + equal_to, boost::yap::expression, is_vector); // == +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + not_equal_to, boost::yap::expression, is_vector); // != +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + logical_or, boost::yap::expression, is_vector); // || +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + logical_and, boost::yap::expression, is_vector); // && +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + bitwise_and, boost::yap::expression, is_vector); // & +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + bitwise_or, boost::yap::expression, is_vector); // | +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( + bitwise_xor, boost::yap::expression, is_vector); // ^ + +int test_main(int, char * []) +{ + int i; + int const n = 10; + std::vector<int> a(n), b(n), c(n), d(n); + std::vector<double> e(n); + + // Reset allocation count. There should be none from this point on. + allocations = 0; + + for (i = 0; i < n; ++i) { + a[i] = i; + b[i] = 2 * i; + c[i] = 3 * i; + d[i] = i; + } + + assign(b, 2); + assign(d, a + b * c); + + if_else(d < 30, b, c); + a += if_else(d < 30, b, c); + + assign(e, c); + e += e - 4 / (c + 1); + + for (i = 0; i < n; ++i) { + std::cout << " a(" << i << ") = " << a[i] << " b(" << i + << ") = " << b[i] << " c(" << i << ") = " << c[i] << " d(" + << i << ") = " << d[i] << " e(" << i << ") = " << e[i] + << std::endl; + } + + BOOST_CHECK(allocations == 0); + + return 0; +} |