algorithm_fwd.hpp 6.7 KB

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