2
0
mirror of https://github.com/boostorg/yap.git synced 2026-02-23 16:22:09 +00:00

Add detail::expr_arity and expression tag types.

This commit is contained in:
Zach Laine
2016-11-26 18:36:12 -06:00
parent d1601f7da6
commit e36bc36c5a
4 changed files with 213 additions and 14 deletions

View File

@@ -156,7 +156,7 @@ namespace boost::proto17 {
template <typename Expr, typename Tuple, typename Transform>
auto transform_nonterminal (Expr const & expr, Tuple && tuple, Transform && transform);
template <typename Expr, typename Transform, typename = std::void_t<>>
template <typename Expr, typename Transform, expr_arity Arity, typename = std::void_t<>>
struct default_transform_expression
{
auto operator() (Expr && expr, Transform && transform)
@@ -164,7 +164,11 @@ namespace boost::proto17 {
constexpr expr_kind kind = remove_cv_ref_t<Expr>::kind;
if constexpr (kind == expr_kind::expr_ref) {
decltype(auto) ref = ::boost::proto17::value(expr);
default_transform_expression<decltype(ref), Transform> transformer;
default_transform_expression<
decltype(ref),
Transform,
detail::arity_of<kind>()
> transformer;
return transformer(ref, static_cast<Transform &&>(transform));
} else if constexpr (kind == expr_kind::terminal || kind == expr_kind::placeholder) {
return static_cast<Expr &&>(expr);
@@ -186,10 +190,11 @@ namespace boost::proto17 {
}
};
template <typename Expr, typename Transform>
template <typename Expr, typename Transform, expr_arity Arity>
struct default_transform_expression<
Expr,
Transform,
Arity,
std::void_t<decltype(std::declval<Transform>()(std::declval<Expr>()))>
>
{
@@ -213,7 +218,7 @@ namespace boost::proto17 {
static_cast<Tuple &&>(tuple),
[&transform](auto && element) {
using element_t = decltype(element);
default_transform_expression<element_t, Transform> transformer;
default_transform_expression<element_t, Transform, detail::arity_of<Expr::kind>()> transformer;
return transformer(
static_cast<element_t &&>(element),
static_cast<Transform &&>(transform)

View File

@@ -4,6 +4,7 @@
#include "../expression_fwd.hpp"
#include <boost/hana/tuple.hpp>
#include <boost/hana/size.hpp>
#include <type_traits>
@@ -191,6 +192,142 @@ namespace boost::proto17 {
U
>::type;
enum class expr_arity {
invalid,
one,
two,
n
};
template <expr_kind Kind>
constexpr expr_arity arity_of ()
{
switch (Kind) {
case expr_kind::expr_ref:
case expr_kind::terminal:
case expr_kind::placeholder:
// unary
case expr_kind::unary_plus: // +
case expr_kind::negate: // -
case expr_kind::dereference: // *
case expr_kind::complement: // ~
case expr_kind::address_of: // &
case expr_kind::logical_not: // !
case expr_kind::pre_inc: // ++
case expr_kind::pre_dec: // --
case expr_kind::post_inc: // ++(int)
case expr_kind::post_dec: // --(int)
return expr_arity::one;
// binary
case expr_kind::shift_left: // <<
case expr_kind::shift_right: // >>
case expr_kind::multiplies: // *
case expr_kind::divides: // /
case expr_kind::modulus: // %
case expr_kind::plus: // +
case expr_kind::minus: // -
case expr_kind::less: // <
case expr_kind::greater: // >
case expr_kind::less_equal: // <=
case expr_kind::greater_equal: // >=
case expr_kind::equal_to: // ==
case expr_kind::not_equal_to: // !=
case expr_kind::logical_or: // ||
case expr_kind::logical_and: // &&
case expr_kind::bitwise_and: // &
case expr_kind::bitwise_or: // |
case expr_kind::bitwise_xor: // ^
case expr_kind::comma: // :
case expr_kind::mem_ptr: // ->*
case expr_kind::assign: // =
case expr_kind::shift_left_assign: // <<=
case expr_kind::shift_right_assign: // >>=
case expr_kind::multiplies_assign: // *=
case expr_kind::divides_assign: // /=
case expr_kind::modulus_assign: // %=
case expr_kind::plus_assign: // +=
case expr_kind::minus_assign: // -=
case expr_kind::bitwise_and_assign: // &=
case expr_kind::bitwise_or_assign: // |=
case expr_kind::bitwise_xor_assign: // ^=
case expr_kind::subscript: // []
return expr_arity::two;
// n-ary
case expr_kind::call: // ()
return expr_arity::n;
default:
return expr_arity::invalid;
}
}
template <expr_kind Kind>
constexpr auto tag_for ()
{
#define CASE(x) if constexpr (Kind == expr_kind::x) return x ## _tag{}
CASE(expr_ref);
CASE(terminal);
CASE(placeholder);
// unary
CASE(unary_plus); // +
CASE(negate); // -
CASE(dereference); // *
CASE(complement); // ~
CASE(address_of); // &
CASE(logical_not); // !
CASE(pre_inc); // ++
CASE(pre_dec); // --
CASE(post_inc); // ++(int)
CASE(post_dec); // --(int)
// binary
CASE(shift_left); // <<
CASE(shift_right); // >>
CASE(multiplies); // *
CASE(divides); // /
CASE(modulus); // %
CASE(plus); // +
CASE(minus); // -
CASE(less); // <
CASE(greater); // >
CASE(less_equal); // <=
CASE(greater_equal); // >=
CASE(equal_to); // ==
CASE(not_equal_to); // !=
CASE(logical_or); // ||
CASE(logical_and); // &&
CASE(bitwise_and); // &
CASE(bitwise_or); // |
CASE(bitwise_xor); // ^
CASE(comma); // );
CASE(mem_ptr); // ->*
CASE(assign); // =
CASE(shift_left_assign); // <<=
CASE(shift_right_assign); // >>=
CASE(multiplies_assign); // *=
CASE(divides_assign); // /=
CASE(modulus_assign); // %=
CASE(plus_assign); // +=
CASE(minus_assign); // -=
CASE(bitwise_and_assign); // &=
CASE(bitwise_or_assign); // |=
CASE(bitwise_xor_assign); // ^=
CASE(subscript); // []
// n-ary
CASE(call); // ()
#undef CASE
};
}
}

View File

@@ -295,7 +295,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 1UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::one,
"value() is only defined for unary expressions."
);
if constexpr (Expr::kind == expr_kind::expr_ref) {
@@ -310,7 +310,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 1UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::one,
"value() is only defined for unary expressions."
);
if constexpr (Expr::kind == expr_kind::expr_ref) {
@@ -325,7 +325,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 1UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::one,
"value() is only defined for unary expressions."
);
if constexpr (Expr::kind == expr_kind::expr_ref) {
@@ -340,7 +340,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 2UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::two,
"left() and right() are only defined for binary expressions."
);
return expr.elements[0_c];
@@ -351,7 +351,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 2UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::two,
"left() and right() are only defined for binary expressions."
);
return expr.elements[0_c];
@@ -362,7 +362,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 2UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::two,
"left() and right() are only defined for binary expressions."
);
return std::move(expr.elements)[0_c];
@@ -373,7 +373,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 2UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::two,
"left() and right() are only defined for binary expressions."
);
return expr.elements[1_c];
@@ -384,7 +384,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 2UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::two,
"left() and right() are only defined for binary expressions."
);
return expr.elements[1_c];
@@ -395,7 +395,7 @@ namespace boost::proto17 {
{
using namespace hana::literals;
static_assert(
decltype(hana::size(expr.elements))::value == 2UL,
detail::arity_of<Expr::kind>() == detail::expr_arity::two,
"left() and right() are only defined for binary expressions."
);
return std::move(expr.elements)[1_c];
@@ -516,7 +516,8 @@ namespace boost::proto17 {
template <typename Expr, typename Transform>
auto transform (Expr && expr, Transform && transform)
{
return detail::default_transform_expression<Expr, Transform>{}(
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
return detail::default_transform_expression<Expr, Transform, detail::arity_of<kind>()>{}(
static_cast<Expr &&>(expr),
static_cast<Transform &&>(transform)
);

View File

@@ -120,6 +120,62 @@ namespace boost::proto17 {
}
// Tag types -- one per expr_kind:
struct expr_ref_tag {}; // TODO: Needed?
struct terminal_tag {};
struct placeholder_tag {};
// unary
struct unary_plus_tag {}; // +
struct negate_tag {}; // -
struct dereference_tag {}; // *
struct complement_tag {}; // ~
struct address_of_tag {}; // &
struct logical_not_tag {}; // !
struct pre_inc_tag {}; // ++
struct pre_dec_tag {}; // --
struct post_inc_tag {}; // ++(int)
struct post_dec_tag {}; // --(int)
// binary
struct shift_left_tag {}; // <<
struct shift_right_tag {}; // >>
struct multiplies_tag {}; // *
struct divides_tag {}; // /
struct modulus_tag {}; // %
struct plus_tag {}; // +
struct minus_tag {}; // -
struct less_tag {}; // <
struct greater_tag {}; // >
struct less_equal_tag {}; // <=
struct greater_equal_tag {}; // >=
struct equal_to_tag {}; // ==
struct not_equal_to_tag {}; // !=
struct logical_or_tag {}; // ||
struct logical_and_tag {}; // &&
struct bitwise_and_tag {}; // &
struct bitwise_or_tag {}; // |
struct bitwise_xor_tag {}; // ^
struct comma_tag {}; // _tag {};
struct mem_ptr_tag {}; // ->*
struct assign_tag {}; // =
struct shift_left_assign_tag {}; // <<=
struct shift_right_assign_tag {}; // >>=
struct multiplies_assign_tag {}; // *=
struct divides_assign_tag {}; // /=
struct modulus_assign_tag {}; // %=
struct plus_assign_tag {}; // +=
struct minus_assign_tag {}; // -=
struct bitwise_and_assign_tag {}; // &=
struct bitwise_or_assign_tag {}; // |=
struct bitwise_xor_assign_tag {}; // ^=
struct subscript_tag {}; // []
// n-ary
struct call_tag {}; // ()
}
#endif