1 // Copyright (C) 2016-2018 T. Zachary Laine 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See 4 // accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 #ifndef BOOST_YAP_ALGORITHM_FWD_HPP_INCLUDED 7 #define BOOST_YAP_ALGORITHM_FWD_HPP_INCLUDED 8 9 #include <boost/yap/config.hpp> 10 11 #include <boost/hana/integral_constant.hpp> 12 #include <boost/hana/tuple.hpp> 13 #include <boost/hana/core/is_a.hpp> 14 15 16 namespace boost { namespace yap { 17 18 /** The enumeration representing all the kinds of expressions supported in 19 YAP. 20 */ 21 enum class expr_kind { 22 expr_ref = 23 0, ///< A (possibly \c const) reference to another expression. 24 25 terminal = 1, ///< A terminal expression. 26 27 // unary 28 unary_plus = 2, ///< \c + 29 negate = 3, ///< \c - 30 dereference = 4, ///< \c * 31 complement = 5, ///< \c ~ 32 address_of = 6, ///< \c & 33 logical_not = 7, ///< \c ! 34 pre_inc = 8, ///< \c ++ 35 pre_dec = 9, ///< \c \-\- 36 post_inc = 10, ///< \c ++(int) 37 post_dec = 11, ///< \c \-\-(int) 38 39 // binary 40 shift_left = 12, ///< \c << 41 shift_right = 13, ///< \c >> 42 multiplies = 14, ///< \c * 43 divides = 15, ///< \c / 44 modulus = 16, ///< \c % 45 plus = 17, ///< \c + 46 minus = 18, ///< \c - 47 less = 19, ///< \c < 48 greater = 20, ///< \c > 49 less_equal = 21, ///< \c <= 50 greater_equal = 22, ///< \c >= 51 equal_to = 23, ///< \c == 52 not_equal_to = 24, ///< \c != 53 logical_or = 25, ///< \c || 54 logical_and = 26, ///< \c && 55 bitwise_and = 27, ///< \c & 56 bitwise_or = 28, ///< \c | 57 bitwise_xor = 29, ///< \c ^ 58 comma = 30, ///< \c , 59 mem_ptr = 31, ///< \c ->* 60 assign = 32, ///< \c = 61 shift_left_assign = 33, ///< \c <<= 62 shift_right_assign = 34, ///< \c >>= 63 multiplies_assign = 35, ///< \c *= 64 divides_assign = 36, ///< \c /= 65 modulus_assign = 37, ///< \c %= 66 plus_assign = 38, ///< \c += 67 minus_assign = 39, ///< \c -= 68 bitwise_and_assign = 40, ///< \c &= 69 bitwise_or_assign = 41, ///< \c |= 70 bitwise_xor_assign = 42, ///< \c ^= 71 subscript = 43, ///< \c [] 72 73 // ternary 74 if_else = 44, ///< Analogous to \c ?: . 75 76 // n-ary 77 call = 45 ///< \c () 78 }; 79 80 /** The type used to represent the index of a placeholder terminal. */ 81 template<long long I> 82 struct placeholder : hana::llong<I> 83 { 84 }; 85 86 #ifdef BOOST_YAP_DOXYGEN 87 88 /** A metafunction that evaluates to std::true_type if \a Expr is an 89 Expression, and std::false_type otherwise. */ 90 template<typename Expr> 91 struct is_expr; 92 93 #else 94 95 template<expr_kind Kind, typename Tuple> 96 struct expression; 97 98 namespace detail { 99 100 // void_t 101 102 template<class...> 103 using void_t = void; 104 105 // remove_cv_ref 106 107 template<typename T> 108 struct remove_cv_ref : std::remove_cv<std::remove_reference_t<T>> 109 { 110 }; 111 112 template<typename T> 113 using remove_cv_ref_t = typename remove_cv_ref<T>::type; 114 } 115 116 template< 117 typename Expr, 118 typename = detail::void_t<>, 119 typename = detail::void_t<>> 120 struct is_expr : std::false_type 121 { 122 }; 123 124 template<typename Expr> 125 struct is_expr< 126 Expr, 127 detail::void_t<decltype(detail::remove_cv_ref_t<Expr>::kind)>, 128 detail::void_t<decltype(std::declval<Expr>().elements)>> 129 : std::integral_constant< 130 bool, 131 std::is_same< 132 std::remove_cv_t<decltype( 133 detail::remove_cv_ref_t<Expr>::kind)>, 134 expr_kind>::value && 135 hana::is_a< 136 hana::tuple_tag, 137 decltype(std::declval<Expr>().elements)>> 138 { 139 }; 140 141 #endif // BOOST_YAP_DOXYGEN 142 143 /** A convenience alias for a terminal expression holding a \a T, 144 instantiated from expression template \a expr_template. */ 145 template<template<expr_kind, class> class expr_template, typename T> 146 using terminal = expr_template<expr_kind::terminal, hana::tuple<T>>; 147 148 /** A convenience alias for a reference expression holding an expression 149 \a T, instantiated from expression template \a expr_template. */ 150 template<template<expr_kind, class> class expr_template, typename T> 151 using expression_ref = expr_template< 152 expr_kind::expr_ref, 153 hana::tuple<std::remove_reference_t<T> *>>; 154 155 #ifndef BOOST_YAP_DOXYGEN 156 157 template<typename Expr, typename... T> 158 constexpr decltype(auto) evaluate(Expr && expr, T &&... t); 159 160 template<typename Expr, typename Transform, typename... Transforms> 161 constexpr decltype(auto) transform( 162 Expr && expr, Transform && transform, Transforms &&... transforms); 163 164 template<typename Expr, typename Transform, typename... Transforms> 165 constexpr decltype(auto) transform_strict( 166 Expr && expr, Transform && transform, Transforms &&... transforms); 167 168 template<typename T> 169 constexpr decltype(auto) deref(T && x); 170 171 template<typename Expr> 172 constexpr decltype(auto) value(Expr && expr); 173 174 #endif // BOOST_YAP_DOXYGEN 175 176 namespace literals { 177 178 /** Creates literal placeholders. Placeholder indices are 1-based. */ 179 template<char... c> operator ""_p()180 constexpr auto operator"" _p() 181 { 182 using i = hana::llong<hana::ic_detail::parse<sizeof...(c)>({c...})>; 183 static_assert(1 <= i::value, "Placeholders must be >= 1."); 184 return expression< 185 expr_kind::terminal, 186 hana::tuple<placeholder<i::value>>>{}; 187 } 188 } 189 190 /** Used as the tag-type passed to a transform function written in the 191 tag-transform form. */ 192 template<expr_kind Kind> 193 struct expr_tag 194 { 195 static const expr_kind kind = Kind; 196 }; 197 198 /** Used as the expression template returned by some operations inside YAP 199 when YAP does not have an expression template it was told to use. For 200 instance, if transform() creates a new expression by transforming an 201 existing expression's elements, it will attempt to create the new 202 expression using the existing one's expression template. If no such 203 template exists because the existing expression was not made from an 204 expression template, minimal_expr is used. */ 205 template<expr_kind Kind, typename Tuple> 206 struct minimal_expr 207 { 208 static expr_kind const kind = Kind; 209 Tuple elements; 210 }; 211 212 }} 213 214 #endif 215