// 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) #ifndef BOOST_YAP_ALGORITHM_FWD_HPP_INCLUDED #define BOOST_YAP_ALGORITHM_FWD_HPP_INCLUDED #include #include #include #include namespace boost { namespace yap { /** The enumeration representing all the kinds of expressions supported in YAP. */ enum class expr_kind { expr_ref = 0, ///< A (possibly \c const) reference to another expression. terminal = 1, ///< A terminal expression. // unary unary_plus = 2, ///< \c + negate = 3, ///< \c - dereference = 4, ///< \c * complement = 5, ///< \c ~ address_of = 6, ///< \c & logical_not = 7, ///< \c ! pre_inc = 8, ///< \c ++ pre_dec = 9, ///< \c \-\- post_inc = 10, ///< \c ++(int) post_dec = 11, ///< \c \-\-(int) // binary shift_left = 12, ///< \c << shift_right = 13, ///< \c >> multiplies = 14, ///< \c * divides = 15, ///< \c / modulus = 16, ///< \c % plus = 17, ///< \c + minus = 18, ///< \c - less = 19, ///< \c < greater = 20, ///< \c > less_equal = 21, ///< \c <= greater_equal = 22, ///< \c >= equal_to = 23, ///< \c == not_equal_to = 24, ///< \c != logical_or = 25, ///< \c || logical_and = 26, ///< \c && bitwise_and = 27, ///< \c & bitwise_or = 28, ///< \c | bitwise_xor = 29, ///< \c ^ comma = 30, ///< \c , mem_ptr = 31, ///< \c ->* assign = 32, ///< \c = shift_left_assign = 33, ///< \c <<= shift_right_assign = 34, ///< \c >>= multiplies_assign = 35, ///< \c *= divides_assign = 36, ///< \c /= modulus_assign = 37, ///< \c %= plus_assign = 38, ///< \c += minus_assign = 39, ///< \c -= bitwise_and_assign = 40, ///< \c &= bitwise_or_assign = 41, ///< \c |= bitwise_xor_assign = 42, ///< \c ^= subscript = 43, ///< \c [] // ternary if_else = 44, ///< Analogous to \c ?: . // n-ary call = 45 ///< \c () }; /** The type used to represent the index of a placeholder terminal. */ template struct placeholder : hana::llong { }; #ifdef BOOST_YAP_DOXYGEN /** A metafunction that evaluates to std::true_type if \a Expr is an Expression, and std::false_type otherwise. */ template struct is_expr; #else template struct expression; namespace detail { // void_t template using void_t = void; // remove_cv_ref template struct remove_cv_ref : std::remove_cv> { }; template using remove_cv_ref_t = typename remove_cv_ref::type; } template< typename Expr, typename = detail::void_t<>, typename = detail::void_t<>> struct is_expr : std::false_type { }; template struct is_expr< Expr, detail::void_t::kind)>, detail::void_t().elements)>> : std::integral_constant< bool, std::is_same< std::remove_cv_t::kind)>, expr_kind>::value && hana::is_a< hana::tuple_tag, decltype(std::declval().elements)>> { }; #endif // BOOST_YAP_DOXYGEN /** A convenience alias for a terminal expression holding a \a T, instantiated from expression template \a expr_template. */ template class expr_template, typename T> using terminal = expr_template>; /** A convenience alias for a reference expression holding an expression \a T, instantiated from expression template \a expr_template. */ template class expr_template, typename T> using expression_ref = expr_template< expr_kind::expr_ref, hana::tuple *>>; #ifndef BOOST_YAP_DOXYGEN template decltype(auto) evaluate(Expr && expr, T &&... t); template constexpr decltype(auto) transform( Expr && expr, Transform && transform, Transforms &&... transforms); template decltype(auto) transform_strict( Expr && expr, Transform && transform, Transforms &&... transforms); template decltype(auto) deref(T && x); template decltype(auto) value(Expr && expr); #endif // BOOST_YAP_DOXYGEN namespace literals { /** Creates literal placeholders. Placeholder indices are 1-based. */ template constexpr auto operator"" _p() { using i = hana::llong({c...})>; static_assert(1 <= i::value, "Placeholders must be >= 1."); return expression< expr_kind::terminal, hana::tuple>>{}; } } /** Used as the tag-type passed to a transform function written in the tag-transform form. */ template struct expr_tag { static const expr_kind kind = Kind; }; /** Used as the expression template returned by some operations inside YAP when YAP does not have an expression template it was told to use. For instance, if transform() creates a new expression by transforming an existing expression's elements, it will attempt to create the new expression using the existing one's expression template. If no such template exists because the existing expression was not made from an expression template, minimal_expr is used. */ template struct minimal_expr { static expr_kind const kind = Kind; Tuple elements; }; }} #endif