212 lines
8.1 KiB
C++
212 lines
8.1 KiB
C++
#ifndef PFOR_PFOR_EXPRESSION_OP_H
|
|
#define PFOR_PFOR_EXPRESSION_OP_H
|
|
|
|
#include "access.h"
|
|
#include "optraits.h"
|
|
#include "traits.h"
|
|
|
|
#define PFOR_EXPR_DEF_OPERATION_UNARY(OPNAME, OPSYM) \
|
|
struct OPNAME { \
|
|
template<typename T, std::enable_if_t<expr::isExpression<T>>* = nullptr> \
|
|
inline static decltype(auto) eval(T&& value) { \
|
|
return OPSYM std::forward<T>(value).eval(); \
|
|
} \
|
|
template<typename T> \
|
|
inline static decltype(auto) eval(long i, T&& value) { \
|
|
return OPSYM std::forward<T>(value)[i]; \
|
|
} \
|
|
}
|
|
|
|
#define PFOR_EXPR_DEF_OPERATION_POST_UNARY(OPNAME, OPSYM) \
|
|
struct OPNAME { \
|
|
template<typename T, std::enable_if_t<expr::isExpression<T>>* = nullptr> \
|
|
inline static decltype(auto) eval(T&& value) { \
|
|
return std::forward<T>(value).eval() OPSYM; \
|
|
} \
|
|
template<typename T> \
|
|
inline static decltype(auto) eval(long i, T&& value) { \
|
|
return std::forward<T>(value)[i] OPSYM; \
|
|
} \
|
|
}
|
|
|
|
#define PFOR_EXPR_DEF_OPERATION_BINARY(OPNAME, OPSYM) \
|
|
struct OPNAME { \
|
|
template<typename Lhs, typename Rhs, \
|
|
std::enable_if_t<expr::isExpression<Lhs>>* = nullptr> \
|
|
inline static decltype(auto) eval(Lhs&& lhs, Rhs&& rhs) { \
|
|
return std::forward<Lhs>(lhs).eval() OPSYM std::forward<Rhs>(rhs).eval(); \
|
|
} \
|
|
template<typename Lhs, typename Rhs> \
|
|
inline static decltype(auto) eval(long i, Lhs&& lhs, Rhs&& rhs) { \
|
|
return std::forward<Lhs>(lhs)[i] OPSYM std::forward<Rhs>(rhs)[i]; \
|
|
} \
|
|
}
|
|
|
|
namespace pfor {
|
|
namespace expr {
|
|
namespace op {
|
|
|
|
/* from: http://en.cppreference.com/w/cpp/language/operator_precedence
|
|
* excluding non overloadable operators
|
|
*
|
|
* [02] a++, a--, a(), a[]
|
|
* [03] ++a, --a, +a, -a, !a, ~a, *a, &a
|
|
* [04] ->*
|
|
* [05] a*b, a/b, a%b
|
|
* [06] a+b, a-b
|
|
* [07] <<, >>
|
|
* [08] <, <=, >, >=
|
|
* [09] ==, !=
|
|
* [10] a&b
|
|
* [11] ^
|
|
* [12] |
|
|
* [13] &&
|
|
* [14] ||
|
|
* [15] =, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=
|
|
* [16] ,
|
|
*/
|
|
|
|
/* ===== Unary ===== */
|
|
PFOR_EXPR_DEF_OPERATION_POST_UNARY(PostIncr, ++);
|
|
PFOR_EXPR_DEF_OPERATION_POST_UNARY(PostDecr, --);
|
|
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(PreIncr, ++);
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(PreDecr, --);
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(Plus, +);
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(Minus, -);
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(Not, !);
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(BitNot, ~);
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(Indirection, *);
|
|
PFOR_EXPR_DEF_OPERATION_UNARY(AddressOf, &);
|
|
|
|
/* ===== Binary ===== */
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(PtrToMem, ->*);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Multiplication, *);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Division, /);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Modulo, %);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Addition, +);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Subtraction, -);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(LeftShift, <<);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(RightShift, >>);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Lower, <);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(LowerEqual, <=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Greater, >);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(GreaterEqual, >=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Equal, ==);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(NotEqual, !=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(BitAnd, &);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(BitXor, ^);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(BitOr, |);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(And, &&);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Or, ||);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(Assign, =);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignAdd, +=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignSub, -=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignMul, *=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignDiv, /=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignMod, %=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignLS, <<=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignRS, >>=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignAnd, &=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignXor, ^=);
|
|
PFOR_EXPR_DEF_OPERATION_BINARY(AssignOr, |=);
|
|
|
|
struct Subscript {
|
|
template<typename T, typename Index, std::enable_if_t<isExpression<T>>* = nullptr>
|
|
inline static decltype(auto) eval(T&& t, Index&& index) {
|
|
return std::forward<T>(t).eval()[std::forward<Index>(index).eval()];
|
|
}
|
|
|
|
template<typename T, typename Index>
|
|
inline static decltype(auto) eval(long i, T&& t, Index&& index) {
|
|
return std::forward<T>(t)[i][std::forward<Index>(index)[i]];
|
|
}
|
|
};
|
|
|
|
struct Comma {
|
|
template<typename Lhs, typename... Rhs, std::enable_if_t<isExpression<Lhs>>* = nullptr>
|
|
inline static decltype(auto) eval(Lhs&& lhs, Rhs&&... rhs) {
|
|
return std::forward<Lhs>(lhs).eval(), eval(std::forward<Rhs>(rhs)...);
|
|
}
|
|
|
|
template<typename Lhs, typename Rhs, std::enable_if_t<isExpression<Lhs>>* = nullptr>
|
|
inline static decltype(auto) eval(Lhs&& lhs, Rhs&& rhs) {
|
|
return std::forward<Lhs>(lhs).eval(), std::forward<Rhs>(rhs).eval();
|
|
}
|
|
|
|
template<typename Lhs, typename... Rhs>
|
|
inline static decltype(auto) eval(long i, Lhs&& lhs, Rhs&&... rhs) {
|
|
return std::forward<Lhs>(lhs)[i], eval(i, std::forward<Rhs>(rhs)...);
|
|
}
|
|
|
|
template<typename Lhs, typename Rhs>
|
|
inline static decltype(auto) eval(long i, Lhs&& lhs, Rhs&& rhs) {
|
|
return std::forward<Lhs>(lhs)[i], std::forward<Rhs>(rhs)[i];
|
|
}
|
|
|
|
template<typename Lhs>
|
|
inline static decltype(auto) eval(long i, Lhs&& lhs) {
|
|
return std::forward<Lhs>(lhs)[i];
|
|
}
|
|
};
|
|
|
|
/* ===== Ternary ===== */
|
|
struct If {
|
|
template<typename Cond, typename T, typename F, std::enable_if_t<isExpression<Cond>>* = nullptr>
|
|
inline static decltype(auto) eval(Cond&& cond, T&& t, F&& f) {
|
|
return std::forward<Cond>(cond).eval()? std::forward<T>(t).eval():std::forward<F>(f).eval();
|
|
}
|
|
|
|
template<typename Cond, typename T, typename F>
|
|
inline static decltype(auto) eval(long i, Cond&& cond, T&& t, F&& f) {
|
|
return std::forward<Cond>(cond)[i]? std::forward<T>(t)[i]:std::forward<F>(f)[i];
|
|
}
|
|
};
|
|
|
|
/* ==== N-ary ===== */
|
|
struct FunctionCall {
|
|
template<typename F, typename... Ts, std::enable_if_t<isExpression<F>>* = nullptr>
|
|
inline static decltype(auto) eval(F&& f, Ts&&... values) {
|
|
return std::forward<F>(f).eval()(std::forward<Ts>(values).eval()...);
|
|
}
|
|
|
|
template<typename F, typename... Ts>
|
|
inline static decltype(auto) eval(long i, F&& f, Ts&&... values) {
|
|
return std::forward<F>(f)[i](std::forward<Ts>(values)[i]...);
|
|
}
|
|
};
|
|
|
|
#undef PFOR_EXPR_DEF_OPERATION_POST_UNARY
|
|
#undef PFOR_EXPR_DEF_OPERATION_UNARY
|
|
#undef PFOR_EXPR_DEF_OPERATION_BINARY
|
|
|
|
template<typename Op>
|
|
struct View;
|
|
|
|
}
|
|
|
|
#define PFOR_EXPR_SPECIALIZE_ASSIGN(O) \
|
|
template<typename T> \
|
|
struct OperationTraits<op::O, T, 0> { \
|
|
static constexpr Access access = Access::write; \
|
|
}
|
|
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(Assign);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignAdd);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignSub);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignMul);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignDiv);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignMod);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignLS);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignRS);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignAnd);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignXor);
|
|
PFOR_EXPR_SPECIALIZE_ASSIGN(AssignOr);
|
|
|
|
#undef PFOR_EXPR_SPECIALIZE_ASSIGN
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|