138 lines
5.7 KiB
C++
138 lines
5.7 KiB
C++
#ifndef PFOR_PFOR_EXPRESSION_OPERATORS_H
|
|
#define PFOR_PFOR_EXPRESSION_OPERATORS_H
|
|
|
|
#include "asexpression.h"
|
|
#include "expression.h"
|
|
#include "op.h"
|
|
|
|
#define PFOR_EXPR_DEF_UN_OP(OP, OPSYM) \
|
|
template<typename T, std::enable_if_t<isExpression<T>>* = nullptr> \
|
|
inline auto operator OPSYM(T const& t) { return Expression<OP, T>{{}, t}; }
|
|
|
|
#define PFOR_EXPR_DEF_BIN_OP(OP, OPSYM) \
|
|
template<typename Lhs, typename Rhs, std::enable_if_t<anyExpression<Lhs, Rhs>>* = nullptr> \
|
|
inline auto operator OPSYM(Lhs const& lhs, Rhs const& rhs) { \
|
|
return Expression<OP, AsExpression<Lhs>, AsExpression<Rhs>>{{}, lhs, rhs}; \
|
|
}
|
|
|
|
#define PFOR_EXPR_DEF_OPS() \
|
|
PFOR_EXPR_DEF_UN_OP (op::Plus, +) \
|
|
PFOR_EXPR_DEF_UN_OP (op::Minus, -) \
|
|
PFOR_EXPR_DEF_UN_OP (op::Not, !) \
|
|
PFOR_EXPR_DEF_UN_OP (op::BitNot, ~) \
|
|
PFOR_EXPR_DEF_UN_OP (op::Indirection, *) \
|
|
PFOR_EXPR_DEF_UN_OP (op::AddressOf, &) \
|
|
\
|
|
PFOR_EXPR_DEF_BIN_OP(op::Multiplication, *) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Division, /) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Modulo, %) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Addition, +) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Subtraction, -) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::LeftShift, <<) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::RightShift, >>) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Lower, <) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::LowerEqual, <=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Greater, >) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::GreaterEqual, >=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Equal, ==) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::NotEqual, !=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::BitAnd, &) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::BitXor, ^) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::BitOr, |) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::And, &&) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::Or, ||) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignAdd, +=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignSub, -=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignMul, *=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignDiv, /=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignMod, %=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignLS, <<=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignRS, >>=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignAnd, &=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignXor, ^=) \
|
|
PFOR_EXPR_DEF_BIN_OP(op::AssignOr, |=)
|
|
|
|
namespace pfor {
|
|
namespace expr {
|
|
|
|
PFOR_EXPR_DEF_OPS();
|
|
|
|
template<typename Cond, typename T, typename F>
|
|
inline decltype(auto) If(Cond const& cond, T const& t, F const& f) {
|
|
return Expression<op::If, Cond, T, F>{{}, cond, t, f};
|
|
}
|
|
|
|
/**
|
|
*/
|
|
template<typename, typename> struct CommaMergerImpl;
|
|
|
|
template<typename LOp, typename... LTs, typename ROp, typename... RTs>
|
|
struct CommaMergerImpl<Expression<LOp, LTs...>, Expression<ROp, RTs...>> {
|
|
using type = Expression<op::Comma, Expression<LOp, LTs...>, Expression<ROp, RTs...>>;
|
|
};
|
|
|
|
template<typename... LTs, typename ROp, typename... RTs>
|
|
struct CommaMergerImpl<Expression<op::Comma, LTs...>, Expression<ROp, RTs...>> {
|
|
using type = Expression<op::Comma, LTs..., Expression<ROp, RTs...>>;
|
|
};
|
|
|
|
template<typename LOp, typename... LTs, typename... RTs>
|
|
struct CommaMergerImpl<Expression<LOp, LTs...>, Expression<op::Comma, RTs...>> {
|
|
using type = Expression<op::Comma, Expression<LOp, LTs...>, RTs...>;
|
|
};
|
|
|
|
template<typename... LTs, typename... RTs>
|
|
struct CommaMergerImpl<Expression<op::Comma, LTs...>, Expression<op::Comma, RTs...>> {
|
|
using type = Expression<op::Comma, LTs..., RTs...>;
|
|
};
|
|
|
|
template<typename Lhs, typename Rhs>
|
|
using CommaMerger = typename CommaMergerImpl<Lhs, Rhs>::type;
|
|
|
|
/**
|
|
*/
|
|
template<typename... Ts, std::enable_if_t<allExpression<Ts...>>* = nullptr>
|
|
inline auto commaMerger(Ts... ts) {
|
|
return Expression<op::Comma, Ts...>{{}, ts...};
|
|
}
|
|
|
|
template<typename... LTs, std::size_t... lindices, typename... RTs, std::size_t... rindices>
|
|
inline auto commaMerger(std::tuple<LTs...> const& lhs,
|
|
std::index_sequence<lindices...> const&,
|
|
std::tuple<RTs...> const& rhs,
|
|
std::index_sequence<rindices...> const&) {
|
|
return Expression<op::Comma, LTs..., RTs...>{{}, std::get<lindices>(lhs)..., std::get<rindices>(rhs)...};
|
|
}
|
|
|
|
template<typename LOp, typename... LTs, typename ROp, typename... RTs,
|
|
std::enable_if_t<not std::is_same<LOp, op::Comma>::value>* = nullptr, std::enable_if_t<not std::is_same<ROp, op::Comma>::value>* = nullptr>
|
|
inline auto operator,(Expression<LOp, LTs...> const& lhs, Expression<ROp, RTs...> const& rhs) {
|
|
using Lhs = Expression<LOp, LTs...>;
|
|
using Rhs = Expression<ROp, RTs...>;
|
|
return CommaMerger<Lhs, Rhs>{{}, lhs, rhs};
|
|
}
|
|
|
|
template<typename LOp, typename... LTs, typename... RTs, std::enable_if_t<not std::is_same<LOp, op::Comma>::value>* = nullptr>
|
|
inline auto operator,(Expression<LOp, LTs...> const& lhs, Expression<op::Comma, RTs...> const& rhs) {
|
|
return commaMerger(std::make_tuple(lhs), std::make_index_sequence<1>{}, rhs.operands, std::make_index_sequence<sizeof...(RTs)>{});
|
|
}
|
|
|
|
template<typename... LTs, typename ROp, typename... RTs, std::enable_if_t<not std::is_same<ROp, op::Comma>::value>* = nullptr>
|
|
inline auto operator,(Expression<op::Comma, LTs...> const& lhs, Expression<ROp, RTs...> const& rhs) {
|
|
return commaMerger(lhs.operands, std::make_index_sequence<sizeof...(LTs)>{}, std::make_tuple(rhs), std::make_index_sequence<1>{});
|
|
}
|
|
|
|
template<typename... LTs, typename... RTs>
|
|
inline auto operator,(Expression<op::Comma, LTs...> const& lhs, Expression<op::Comma, RTs...> const& rhs) {
|
|
return commaMerger(lhs.operands, std::make_index_sequence<sizeof...(LTs)>{}, rhs.operands, std::make_index_sequence<sizeof...(RTs)>{});
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
#undef PFOR_EXPR_DEF_UN_OP
|
|
#undef PFOR_EXPR_DEF_BIN_OP
|
|
#undef PFOR_EXPR_DEF_OPS
|
|
|
|
#endif
|