diff --git a/detail/default_eval.hpp b/detail/default_eval.hpp index 3309697..2cec467 100644 --- a/detail/default_eval.hpp +++ b/detail/default_eval.hpp @@ -23,19 +23,63 @@ namespace boost::proto17 { } else if constexpr (Kind == expr_kind::placeholder) { static_assert(sizeof...(T) == 1); return args[expr.elements[0_c]]; - } else if constexpr (Kind == expr_kind::plus) { - return - eval_plus( - default_eval_expr(expr.elements[0_c], static_cast(args)), - default_eval_expr(expr.elements[1_c], static_cast(args)) - ); - } else if constexpr (Kind == expr_kind::minus) { - return - eval_minus( - default_eval_expr(expr.elements[0_c], static_cast(args)), - default_eval_expr(expr.elements[1_c], static_cast(args)) - ); - } else if constexpr (Kind == expr_kind::call) { + } + + // TODO: Unary ops. + +#define BOOST_PROTO17_BINARY_OPERATOR_CASE(op_name) \ + else if constexpr (Kind == expr_kind:: op_name) { \ + return \ + eval_## op_name( \ + default_eval_expr(expr.elements[0_c], static_cast(args)), \ + default_eval_expr(expr.elements[1_c], static_cast(args)) \ + ); \ + } + + BOOST_PROTO17_BINARY_OPERATOR_CASE(shift_left) // << + BOOST_PROTO17_BINARY_OPERATOR_CASE(shift_right) // >> + BOOST_PROTO17_BINARY_OPERATOR_CASE(multiplies) // * + BOOST_PROTO17_BINARY_OPERATOR_CASE(divides) // / + BOOST_PROTO17_BINARY_OPERATOR_CASE(modulus) // % + BOOST_PROTO17_BINARY_OPERATOR_CASE(plus) // + + BOOST_PROTO17_BINARY_OPERATOR_CASE(minus) // - + BOOST_PROTO17_BINARY_OPERATOR_CASE(less) // < + BOOST_PROTO17_BINARY_OPERATOR_CASE(greater) // > + BOOST_PROTO17_BINARY_OPERATOR_CASE(less_equal) // <= + BOOST_PROTO17_BINARY_OPERATOR_CASE(greater_equal) // >= + BOOST_PROTO17_BINARY_OPERATOR_CASE(equal_to) // == + BOOST_PROTO17_BINARY_OPERATOR_CASE(not_equal_to) // != + BOOST_PROTO17_BINARY_OPERATOR_CASE(logical_or) // || + BOOST_PROTO17_BINARY_OPERATOR_CASE(logical_and) // && + BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_and) // & + BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_or) // | + BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_xor) // ^ + + else if constexpr (Kind == expr_kind::comma) { + return + eval_comma( + default_eval_expr(expr.elements[0_c], static_cast(args)), + default_eval_expr(expr.elements[1_c], static_cast(args)) + ); + } + + BOOST_PROTO17_BINARY_OPERATOR_CASE(mem_ptr) // ->* + BOOST_PROTO17_BINARY_OPERATOR_CASE(assign) // = + BOOST_PROTO17_BINARY_OPERATOR_CASE(shift_left_assign) // <<= + BOOST_PROTO17_BINARY_OPERATOR_CASE(shift_right_assign) // >>= + BOOST_PROTO17_BINARY_OPERATOR_CASE(multiplies_assign) // *= + BOOST_PROTO17_BINARY_OPERATOR_CASE(divides_assign) // /= + BOOST_PROTO17_BINARY_OPERATOR_CASE(modulus_assign) // %= + BOOST_PROTO17_BINARY_OPERATOR_CASE(plus_assign) // += + BOOST_PROTO17_BINARY_OPERATOR_CASE(minus_assign) // -= + BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_and_assign) // &= + BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_or_assign) // |= + BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_xor_assign) // ^= + BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_xor_assign) // [] + +#undef BOOST_PROTO17_BINARY_OPERATOR_CASE + + else if constexpr (Kind == expr_kind::call) { return hana::unpack( hana::transform(expr.elements, [&args] (auto && element) { return default_eval_expr(element, static_cast(args)); diff --git a/expression.hpp b/expression.hpp index 055dd50..5ac0f91 100644 --- a/expression.hpp +++ b/expression.hpp @@ -75,39 +75,81 @@ namespace boost::proto17 { operator R () { return eval_expression_as(*this, hana::basic_type{}); } + // TODO: Unary ops. + +#define BOOST_PROTO17_BINARY_MEMBER_OPERATOR(op, op_name) \ + template \ + decltype(auto) operator op (U && rhs) const & \ + { \ + using rhs_type = typename detail::rhs_type::type; \ + return expression{ \ + hana::tuple{ \ + *this, \ + static_cast(rhs) \ + } \ + }; \ + } \ + template \ + decltype(auto) operator op (U && rhs) && \ + { \ + using rhs_type = typename detail::rhs_type::type; \ + return expression{ \ + hana::tuple{ \ + std::move(*this), \ + static_cast(rhs) \ + } \ + }; \ + } + + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(<<, shift_left) // << + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(>>, shift_right) // >> + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(*, multiplies) // * + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(/, divides) // / + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(%, modulus) // % + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(+, plus) // + + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(-, minus) // - + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(<, less) // < + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(>, greater) // > + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(<=, less_equal) // <= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(>=, greater_equal) // >= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(==, equal_to) // == + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(!=, not_equal_to) // != + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(||, logical_or) // || + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(&&, logical_and) // && + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(&, bitwise_and) // & + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(|, bitwise_or) // | + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(^, bitwise_xor) // ^ + template - decltype(auto) operator+ (U && rhs) const & + decltype(auto) operator, (U && rhs) const & { using rhs_type = typename detail::rhs_type::type; - return expression{ + return expression{ hana::tuple{*this, static_cast(rhs)} }; } template - decltype(auto) operator+ (U && rhs) && + decltype(auto) operator, (U && rhs) && { using rhs_type = typename detail::rhs_type::type; - return expression{ + return expression{ hana::tuple{std::move(*this), static_cast(rhs)} }; } - template - decltype(auto) operator- (U && rhs) const & - { - using rhs_type = typename detail::rhs_type::type; - return expression{ - hana::tuple{*this, static_cast(rhs)} - }; - } - template - decltype(auto) operator- (U && rhs) && - { - using rhs_type = typename detail::rhs_type::type; - return expression{ - hana::tuple{std::move(*this), static_cast(rhs)} - }; - } + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(->*, mem_ptr) // ->* + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(=, assign) // = + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(<<=, shift_left_assign) // <<= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(>>=, shift_right_assign) // >>= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(*=, multiplies_assign) // *= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(/=, divides_assign) // /= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(%=, modulus_assign) // %= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(+=, plus_assign) // += + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(-=, minus_assign) // -= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(&=, bitwise_and_assign) // &= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(|=, bitwise_or_assign) // |= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR(^=, bitwise_xor_assign) // ^= + BOOST_PROTO17_BINARY_MEMBER_OPERATOR([], subscript) // [] template decltype(auto) operator() (U && ...u) const & diff --git a/operators.hpp b/operators.hpp index eb47863..ebc7739 100644 --- a/operators.hpp +++ b/operators.hpp @@ -9,30 +9,79 @@ namespace boost::proto17 { namespace adl_detail { + // TODO: Unary ops. + +#define BOOST_PROTO17_BINARY_OPERATOR(op, op_name) \ + template \ + constexpr auto eval_ ## op_name (T && t, U && u) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( \ + static_cast(t) op static_cast(u) \ + ) \ + struct eval_ ## op_name ## _fn \ + { \ + template \ + constexpr auto operator() (T && t, U && u) const BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( \ + eval_ ## op_name(static_cast(t), static_cast(u)) \ + ) \ + }; + + BOOST_PROTO17_BINARY_OPERATOR(<<, shift_left) // << + BOOST_PROTO17_BINARY_OPERATOR(>>, shift_right) // >> + BOOST_PROTO17_BINARY_OPERATOR(*, multiplies) // * + BOOST_PROTO17_BINARY_OPERATOR(/, divides) // / + BOOST_PROTO17_BINARY_OPERATOR(%, modulus) // % + BOOST_PROTO17_BINARY_OPERATOR(+, plus) // + + BOOST_PROTO17_BINARY_OPERATOR(-, minus) // - + BOOST_PROTO17_BINARY_OPERATOR(<, less) // < + BOOST_PROTO17_BINARY_OPERATOR(>, greater) // > + BOOST_PROTO17_BINARY_OPERATOR(<=, less_equal) // <= + BOOST_PROTO17_BINARY_OPERATOR(>=, greater_equal) // >= + BOOST_PROTO17_BINARY_OPERATOR(==, equal_to) // == + BOOST_PROTO17_BINARY_OPERATOR(!=, not_equal_to) // != + BOOST_PROTO17_BINARY_OPERATOR(||, logical_or) // || + BOOST_PROTO17_BINARY_OPERATOR(&&, logical_and) // && + BOOST_PROTO17_BINARY_OPERATOR(&, bitwise_and) // & + BOOST_PROTO17_BINARY_OPERATOR(|, bitwise_or) // | + BOOST_PROTO17_BINARY_OPERATOR(^, bitwise_xor) // ^ + template - constexpr auto eval_plus (T && t, U && u) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( - static_cast(t) + static_cast(u) + constexpr auto eval_comma (T && t, U && u) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( + (static_cast(t) , static_cast(u)) ) - struct eval_plus_fn + struct eval_comma_fn { template constexpr auto operator() (T && t, U && u) const BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( - eval_plus(static_cast(t), static_cast(u)) + eval_comma(static_cast(t), static_cast(u)) ) }; + BOOST_PROTO17_BINARY_OPERATOR(->*, mem_ptr) // ->* + BOOST_PROTO17_BINARY_OPERATOR(=, assign) // = + BOOST_PROTO17_BINARY_OPERATOR(<<=, shift_left_assign) // <<= + BOOST_PROTO17_BINARY_OPERATOR(>>=, shift_right_assign) // >>= + BOOST_PROTO17_BINARY_OPERATOR(*=, multiplies_assign) // *= + BOOST_PROTO17_BINARY_OPERATOR(/=, divides_assign) // /= + BOOST_PROTO17_BINARY_OPERATOR(%=, modulus_assign) // %= + BOOST_PROTO17_BINARY_OPERATOR(+=, plus_assign) // += + BOOST_PROTO17_BINARY_OPERATOR(-=, minus_assign) // -= + BOOST_PROTO17_BINARY_OPERATOR(&=, bitwise_and_assign) // &= + BOOST_PROTO17_BINARY_OPERATOR(|=, bitwise_or_assign) // |= + BOOST_PROTO17_BINARY_OPERATOR(^=, bitwise_xor_assign) // ^= + template - constexpr auto eval_minus (T && t, U && u) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( - static_cast(t) - static_cast(u) + constexpr auto eval_subscript (T && t, U && u) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( + static_cast(t)[static_cast(u)] ) - struct eval_minus_fn + struct eval_subscript_fn { template constexpr auto operator() (T && t, U && u) const BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( - eval_minus(static_cast(t), static_cast(u)) + eval_subscript(static_cast(t), static_cast(u)) ) }; +#undef BOOST_PROTO17_BINARY_OPERATOR + template constexpr auto eval_call (F && f, T && ...t) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN( static_cast(f)(static_cast(t)...) @@ -49,15 +98,84 @@ namespace boost::proto17 { #undef BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN - using adl_detail::eval_plus_fn; - using adl_detail::eval_minus_fn; - using adl_detail::eval_call_fn; +#define BOOST_PROTO17_USING_OPERATOR_FN(op_name) using adl_detail::eval_ ## op_name ## _fn; + + BOOST_PROTO17_USING_OPERATOR_FN(shift_left) // << + BOOST_PROTO17_USING_OPERATOR_FN(shift_right) // >> + BOOST_PROTO17_USING_OPERATOR_FN(multiplies) // * + BOOST_PROTO17_USING_OPERATOR_FN(divides) // / + BOOST_PROTO17_USING_OPERATOR_FN(modulus) // % + BOOST_PROTO17_USING_OPERATOR_FN(plus) // + + BOOST_PROTO17_USING_OPERATOR_FN(minus) // - + BOOST_PROTO17_USING_OPERATOR_FN(less) // < + BOOST_PROTO17_USING_OPERATOR_FN(greater) // > + BOOST_PROTO17_USING_OPERATOR_FN(less_equal) // <= + BOOST_PROTO17_USING_OPERATOR_FN(greater_equal) // >= + BOOST_PROTO17_USING_OPERATOR_FN(equal_to) // == + BOOST_PROTO17_USING_OPERATOR_FN(not_equal_to) // != + BOOST_PROTO17_USING_OPERATOR_FN(logical_or) // || + BOOST_PROTO17_USING_OPERATOR_FN(logical_and) // && + BOOST_PROTO17_USING_OPERATOR_FN(bitwise_and) // & + BOOST_PROTO17_USING_OPERATOR_FN(bitwise_or) // | + BOOST_PROTO17_USING_OPERATOR_FN(bitwise_xor) // ^ + BOOST_PROTO17_USING_OPERATOR_FN(comma) // , + BOOST_PROTO17_USING_OPERATOR_FN(mem_ptr) // ->* + BOOST_PROTO17_USING_OPERATOR_FN(assign) // = + BOOST_PROTO17_USING_OPERATOR_FN(shift_left_assign) // <<= + BOOST_PROTO17_USING_OPERATOR_FN(shift_right_assign) // >>= + BOOST_PROTO17_USING_OPERATOR_FN(multiplies_assign) // *= + BOOST_PROTO17_USING_OPERATOR_FN(divides_assign) // /= + BOOST_PROTO17_USING_OPERATOR_FN(modulus_assign) // %= + BOOST_PROTO17_USING_OPERATOR_FN(plus_assign) // += + BOOST_PROTO17_USING_OPERATOR_FN(minus_assign) // -= + BOOST_PROTO17_USING_OPERATOR_FN(bitwise_and_assign) // &= + BOOST_PROTO17_USING_OPERATOR_FN(bitwise_or_assign) // |= + BOOST_PROTO17_USING_OPERATOR_FN(bitwise_xor_assign) // ^= + BOOST_PROTO17_USING_OPERATOR_FN(subscript) // [] + BOOST_PROTO17_USING_OPERATOR_FN(call) // () + +#undef BOOST_PROTO17_USING_OPERATOR_FN inline namespace function_objects { - inline constexpr eval_plus_fn eval_plus{}; - inline constexpr eval_minus_fn eval_minus{}; - inline constexpr eval_call_fn eval_call{}; +#define BOOST_PROTO17_DECLARE_OPERATOR_FN(op_name) \ + inline constexpr eval_ ## op_name ## _fn eval_ ## op_name{}; + + BOOST_PROTO17_DECLARE_OPERATOR_FN(shift_left) // << + BOOST_PROTO17_DECLARE_OPERATOR_FN(shift_right) // >> + BOOST_PROTO17_DECLARE_OPERATOR_FN(multiplies) // * + BOOST_PROTO17_DECLARE_OPERATOR_FN(divides) // / + BOOST_PROTO17_DECLARE_OPERATOR_FN(modulus) // % + BOOST_PROTO17_DECLARE_OPERATOR_FN(plus) // + + BOOST_PROTO17_DECLARE_OPERATOR_FN(minus) // - + BOOST_PROTO17_DECLARE_OPERATOR_FN(less) // < + BOOST_PROTO17_DECLARE_OPERATOR_FN(greater) // > + BOOST_PROTO17_DECLARE_OPERATOR_FN(less_equal) // <= + BOOST_PROTO17_DECLARE_OPERATOR_FN(greater_equal) // >= + BOOST_PROTO17_DECLARE_OPERATOR_FN(equal_to) // == + BOOST_PROTO17_DECLARE_OPERATOR_FN(not_equal_to) // != + BOOST_PROTO17_DECLARE_OPERATOR_FN(logical_or) // || + BOOST_PROTO17_DECLARE_OPERATOR_FN(logical_and) // && + BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_and) // & + BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_or) // | + BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_xor) // ^ + BOOST_PROTO17_DECLARE_OPERATOR_FN(comma) // , + BOOST_PROTO17_DECLARE_OPERATOR_FN(mem_ptr) // ->* + BOOST_PROTO17_DECLARE_OPERATOR_FN(assign) // = + BOOST_PROTO17_DECLARE_OPERATOR_FN(shift_left_assign) // <<= + BOOST_PROTO17_DECLARE_OPERATOR_FN(shift_right_assign) // >>= + BOOST_PROTO17_DECLARE_OPERATOR_FN(multiplies_assign) // *= + BOOST_PROTO17_DECLARE_OPERATOR_FN(divides_assign) // /= + BOOST_PROTO17_DECLARE_OPERATOR_FN(modulus_assign) // %= + BOOST_PROTO17_DECLARE_OPERATOR_FN(plus_assign) // += + BOOST_PROTO17_DECLARE_OPERATOR_FN(minus_assign) // -= + BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_and_assign) // &= + BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_or_assign) // |= + BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_xor_assign) // ^= + BOOST_PROTO17_DECLARE_OPERATOR_FN(subscript) // [] + BOOST_PROTO17_DECLARE_OPERATOR_FN(call) // () + +#undef BOOST_PROTO17_DECLARE_OPERATOR_FN } diff --git a/print.hpp b/print.hpp index 95a3b32..9ece967 100644 --- a/print.hpp +++ b/print.hpp @@ -15,9 +15,52 @@ namespace boost::proto17 { inline std::ostream & print_kind (std::ostream & os, expr_kind kind) { switch (kind) { + case expr_kind::unary_plus: return os << "+"; + case expr_kind::negate: return os << "-"; + case expr_kind::dereference: return os << "*"; + case expr_kind::complement: return os << "~"; + case expr_kind::address_of: return os << "&"; + case expr_kind::logical_not: return os << "!"; + case expr_kind::pre_inc: return os << "++"; + case expr_kind::pre_dec: return os << "--"; + case expr_kind::post_inc: return os << "++(int)"; + case expr_kind::post_dec: return os << "--(int)"; + + case expr_kind::shift_left: return os << "<<"; + case expr_kind::shift_right: return os << ">>"; + case expr_kind::multiplies: return os << "*"; + case expr_kind::divides: return os << "/"; + case expr_kind::modulus: return os << "%"; case expr_kind::plus: return os << "+"; case expr_kind::minus: return os << "-"; - // TODO + case expr_kind::less: return os << "<"; + case expr_kind::greater: return os << ">"; + case expr_kind::less_equal: return os << "<="; + case expr_kind::greater_equal: return os << ">="; + case expr_kind::equal_to: return os << "=="; + case expr_kind::not_equal_to: return os << "!="; + case expr_kind::logical_or: return os << "||"; + case expr_kind::logical_and: return os << "&&"; + case expr_kind::bitwise_and: return os << "&"; + case expr_kind::bitwise_or: return os << "|"; + case expr_kind::bitwise_xor: return os << "^"; + case expr_kind::comma: return os << ","; + case expr_kind::mem_ptr: return os << "->*"; + case expr_kind::assign: return os << "="; + case expr_kind::shift_left_assign: return os << "<<="; + case expr_kind::shift_right_assign: return os << ">>="; + case expr_kind::multiplies_assign: return os << "*="; + case expr_kind::divides_assign: return os << "/="; + case expr_kind::modulus_assign: return os << "%="; + case expr_kind::plus_assign: return os << "+="; + case expr_kind::minus_assign: return os << "-="; + case expr_kind::bitwise_and_assign: return os << "&="; + case expr_kind::bitwise_or_assign: return os << "|="; + case expr_kind::bitwise_xor_assign: return os << "^="; + case expr_kind::subscript: return os << "[]"; + + case expr_kind::call: return os << "()"; + default: return os << "** ERROR: UNKNOWN OPERATOR! **"; } }