Commit ee62b236 authored by neverlord's avatar neverlord

guards

parent cdd9aa4d
...@@ -80,7 +80,9 @@ class rvalue_builder ...@@ -80,7 +80,9 @@ class rvalue_builder
typedef util::arg_match_t arg_match_t; typedef util::arg_match_t arg_match_t;
typedef util::type_list<TypeList...> raw_types; typedef util::type_list<
typename detail::implicit_conversions<TypeList>::type...>
raw_types;
static constexpr bool is_complete = static constexpr bool is_complete =
!std::is_same<arg_match_t, typename raw_types::back>::value; !std::is_same<arg_match_t, typename raw_types::back>::value;
...@@ -94,12 +96,7 @@ class rvalue_builder ...@@ -94,12 +96,7 @@ class rvalue_builder
static_assert(util::tl_find<types, arg_match_t>::value == -1, static_assert(util::tl_find<types, arg_match_t>::value == -1,
"arg_match is allowed only as last parameter for on()"); "arg_match is allowed only as last parameter for on()");
typedef typename util::tl_apply<types, typedef typename pattern_from_type_list<types>::type pattern_type;
detail::implicit_conversions>::type
converted_types;
typedef typename pattern_from_type_list<converted_types>::type
pattern_type;
std::unique_ptr<value_matcher> m_vm; std::unique_ptr<value_matcher> m_vm;
...@@ -115,11 +112,11 @@ class rvalue_builder ...@@ -115,11 +112,11 @@ class rvalue_builder
{ {
using namespace ::cppa::util; using namespace ::cppa::util;
typedef typename get_callable_trait<F>::type ctrait; typedef typename get_callable_trait<F>::type ctrait;
typedef typename ctrait::arg_types raw_types; typedef typename ctrait::arg_types raw_arg_types;
static_assert(raw_types::size > 0, "functor has no arguments"); static_assert(raw_types::size > 0, "functor has no arguments");
typedef typename tl_apply<raw_types,rm_ref>::type new_types; typedef typename tl_apply<raw_arg_types,rm_ref>::type arg_types;
typedef typename tl_concat<converted_types,new_types>::type types; typedef typename tl_concat<types,arg_types>::type full_types;
typedef typename pattern_from_type_list<types>::type epattern; typedef typename pattern_from_type_list<full_types>::type epattern;
return get_invokable_impl<epattern>(std::forward<F>(f), return get_invokable_impl<epattern>(std::forward<F>(f),
std::move(m_vm)); std::move(m_vm));
} }
......
...@@ -87,13 +87,13 @@ struct value_matcher ...@@ -87,13 +87,13 @@ struct value_matcher
const bool is_dummy; const bool is_dummy;
inline value_matcher(bool dummy_impl = false) : is_dummy(dummy_impl) { } inline value_matcher(bool dummy_impl = false) : is_dummy(dummy_impl) { }
virtual ~value_matcher(); virtual ~value_matcher();
virtual bool operator()(any_tuple const&) = 0; virtual bool operator()(any_tuple const&) const = 0;
}; };
struct dummy_matcher : value_matcher struct dummy_matcher : value_matcher
{ {
inline dummy_matcher() : value_matcher(true) { } inline dummy_matcher() : value_matcher(true) { }
bool operator()(any_tuple const&); bool operator()(any_tuple const&) const;
}; };
struct cmp_helper struct cmp_helper
...@@ -135,7 +135,7 @@ class value_matcher_impl<wildcard_position::nil, ...@@ -135,7 +135,7 @@ class value_matcher_impl<wildcard_position::nil,
template<typename... Args> template<typename... Args>
value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { } value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { }
bool operator()(any_tuple const& tup) bool operator()(any_tuple const& tup) const
{ {
cmp_helper h{tup}; cmp_helper h{tup};
return util::static_foreach<0, sizeof...(Vs)>::eval(m_values, h); return util::static_foreach<0, sizeof...(Vs)>::eval(m_values, h);
...@@ -177,7 +177,7 @@ class value_matcher_impl<wildcard_position::leading, ...@@ -177,7 +177,7 @@ class value_matcher_impl<wildcard_position::leading,
template<typename... Args> template<typename... Args>
value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { } value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { }
bool operator()(any_tuple const& tup) bool operator()(any_tuple const& tup) const
{ {
cmp_helper h{tup, tup.size() - sizeof...(Ts)}; cmp_helper h{tup, tup.size() - sizeof...(Ts)};
return util::static_foreach<0, sizeof...(Vs)>::eval(m_values, h); return util::static_foreach<0, sizeof...(Vs)>::eval(m_values, h);
...@@ -198,7 +198,7 @@ class value_matcher_impl<wildcard_position::in_between, ...@@ -198,7 +198,7 @@ class value_matcher_impl<wildcard_position::in_between,
template<typename... Args> template<typename... Args>
value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { } value_matcher_impl(Args&&... args) : m_values(std::forward<Args>(args)...) { }
bool operator()(any_tuple const& tup) bool operator()(any_tuple const& tup) const
{ {
static constexpr size_t wcpos = static constexpr size_t wcpos =
static_cast<size_t>(util::tl_find<util::type_list<Ts...>, anything>::value); static_cast<size_t>(util::tl_find<util::type_list<Ts...>, anything>::value);
...@@ -225,7 +225,7 @@ class value_matcher_impl<wildcard_position::multiple, ...@@ -225,7 +225,7 @@ class value_matcher_impl<wildcard_position::multiple,
template<typename... Args> template<typename... Args>
value_matcher_impl(Args&&...) { } value_matcher_impl(Args&&...) { }
bool operator()(any_tuple const&) bool operator()(any_tuple const&) const
{ {
throw std::runtime_error("not implemented yet, sorry"); throw std::runtime_error("not implemented yet, sorry");
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#ifndef APPLY_TUPLE_HPP #ifndef APPLY_TUPLE_HPP
#define APPLY_TUPLE_HPP #define APPLY_TUPLE_HPP
#include "cppa/get.hpp"
#include "cppa/util/enable_if.hpp" #include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp" #include "cppa/util/disable_if.hpp"
#include "cppa/util/is_manipulator.hpp" #include "cppa/util/is_manipulator.hpp"
...@@ -38,40 +39,43 @@ ...@@ -38,40 +39,43 @@
namespace cppa { namespace util { namespace cppa { namespace util {
template<size_t... Range> template<typename Result, bool IsManipulator, size_t... Range>
struct apply_tuple_impl struct apply_tuple_impl
{ {
template<typename F, template<typename...> class Tuple, typename... T> template<typename F, template<typename...> class Tuple, typename... T>
static auto apply(F&& f, Tuple<T...> const& args, static Result apply(F&& f, Tuple<T...> const& args)
typename disable_if<is_manipulator<F>, int>::type = 0)
-> typename get_result_type<F>::type
{ {
return f(get<Range>(args)...); return f(get<Range>(args)...);
} }
};
template<typename Result, size_t... Range>
struct apply_tuple_impl<Result, true, Range...>
{
template<typename F, template<typename...> class Tuple, typename... T> template<typename F, template<typename...> class Tuple, typename... T>
static auto apply(F&& f, Tuple<T...>& args, static Result apply(F&& f, Tuple<T...>& args)
typename enable_if<is_manipulator<F>, int>::type = 0)
-> typename get_result_type<F>::type
{ {
return f(get_ref<Range>(args)...); return f(get_ref<Range>(args)...);
} }
}; };
template<int From, int To, int... Args> template<typename Result, bool IsManipulator, int From, int To, int... Args>
struct apply_tuple_util : apply_tuple_util<From, To-1, To, Args...> struct apply_tuple_util
: apply_tuple_util<Result, IsManipulator, From, To-1, To, Args...>
{ {
}; };
template<int X, int... Args> template<typename Result, bool IsManipulator, int X, int... Args>
struct apply_tuple_util<X, X, Args...> : apply_tuple_impl<X, Args...> struct apply_tuple_util<Result, IsManipulator, X, X, Args...>
: apply_tuple_impl<Result, IsManipulator, X, Args...>
{ {
}; };
template<> template<typename Result, bool IsManipulator>
struct apply_tuple_util<1, 0> struct apply_tuple_util<Result, IsManipulator, 1, 0>
{ {
template<typename F, class Unused> template<typename F, class Unused>
static auto apply(F&& f, Unused const&) -> typename get_result_type<F>::type static Result apply(F&& f, Unused const&)
{ {
return f(); return f();
} }
...@@ -81,6 +85,7 @@ template<typename F, template<typename...> class Tuple, typename... T> ...@@ -81,6 +85,7 @@ template<typename F, template<typename...> class Tuple, typename... T>
auto apply_tuple(F&& fun, Tuple<T...>& tup) auto apply_tuple(F&& fun, Tuple<T...>& tup)
-> typename get_result_type<F>::type -> typename get_result_type<F>::type
{ {
typedef typename get_result_type<F>::type result_type;
typedef typename get_arg_types<F>::types fun_args; typedef typename get_arg_types<F>::types fun_args;
static constexpr size_t tup_size = sizeof...(T); static constexpr size_t tup_size = sizeof...(T);
static_assert(tup_size >= fun_args::size, static_assert(tup_size >= fun_args::size,
...@@ -88,13 +93,15 @@ auto apply_tuple(F&& fun, Tuple<T...>& tup) ...@@ -88,13 +93,15 @@ auto apply_tuple(F&& fun, Tuple<T...>& tup)
static constexpr size_t args_size = fun_args::size; static constexpr size_t args_size = fun_args::size;
static constexpr size_t from = (args_size > 0) ? tup_size - args_size : 1; static constexpr size_t from = (args_size > 0) ? tup_size - args_size : 1;
static constexpr size_t to = (args_size > 0) ? tup_size - 1 : 0; static constexpr size_t to = (args_size > 0) ? tup_size - 1 : 0;
return apply_tuple_util<from, to>::apply(std::forward<F>(fun), tup); return apply_tuple_util<result_type, is_manipulator<F>::value, from, to>
::apply(std::forward<F>(fun), tup);
} }
template<typename F, template<typename...> class Tuple, typename... T> template<typename F, template<typename...> class Tuple, typename... T>
auto apply_tuple(F&& fun, Tuple<T...> const& tup) auto apply_tuple(F&& fun, Tuple<T...> const& tup)
-> typename get_result_type<F>::type -> typename get_result_type<F>::type
{ {
typedef typename get_result_type<F>::type result_type;
typedef typename get_arg_types<F>::types fun_args; typedef typename get_arg_types<F>::types fun_args;
static constexpr size_t tup_size = sizeof...(T); static constexpr size_t tup_size = sizeof...(T);
static_assert(tup_size >= fun_args::size, static_assert(tup_size >= fun_args::size,
...@@ -102,7 +109,18 @@ auto apply_tuple(F&& fun, Tuple<T...> const& tup) ...@@ -102,7 +109,18 @@ auto apply_tuple(F&& fun, Tuple<T...> const& tup)
static constexpr size_t args_size = fun_args::size; static constexpr size_t args_size = fun_args::size;
static constexpr size_t from = (args_size > 0) ? tup_size - args_size : 1; static constexpr size_t from = (args_size > 0) ? tup_size - args_size : 1;
static constexpr size_t to = (args_size > 0) ? tup_size - 1 : 0; static constexpr size_t to = (args_size > 0) ? tup_size - 1 : 0;
return apply_tuple_util<from, to>::apply(std::forward<F>(fun), tup); return apply_tuple_util<result_type, is_manipulator<F>::value, from, to>
::apply(std::forward<F>(fun), tup);
}
template<typename Result, typename F, template<typename...> class Tuple, typename... T>
Result unchecked_apply_tuple(F&& fun, Tuple<T...>& tup)
{
static constexpr size_t tup_size = sizeof...(T);
static constexpr size_t from = 0;
static constexpr size_t to = tup_size - 1;
return apply_tuple_util<Result, false, from, to>
::apply(std::forward<F>(fun), tup);
} }
} } // namespace cppa::util } } // namespace cppa::util
......
...@@ -50,6 +50,12 @@ struct static_foreach_impl ...@@ -50,6 +50,12 @@ struct static_foreach_impl
return f(get<Begin>(c)) return f(get<Begin>(c))
&& static_foreach_impl<Begin+1, End, (Begin+1 > End)>::eval(c, f); && static_foreach_impl<Begin+1, End, (Begin+1 > End)>::eval(c, f);
} }
template<typename Container, typename Fun>
static inline bool eval_or(Container const& c, Fun& f)
{
return f(get<Begin>(c))
|| static_foreach_impl<Begin+1, End, (Begin+1 > End)>::eval_or(c, f);
}
}; };
template<size_t X> template<size_t X>
...@@ -59,6 +65,8 @@ struct static_foreach_impl<X, X, false> ...@@ -59,6 +65,8 @@ struct static_foreach_impl<X, X, false>
static inline void _(Container const&, Fun&) { } static inline void _(Container const&, Fun&) { }
template<typename Container, typename Fun> template<typename Container, typename Fun>
static inline bool eval(Container const&, Fun&) { return true; } static inline bool eval(Container const&, Fun&) { return true; }
template<typename Container, typename Fun>
static inline bool eval_or(Container const&, Fun&) { return true; }
}; };
template<size_t X, size_t Y> template<size_t X, size_t Y>
...@@ -68,6 +76,8 @@ struct static_foreach_impl<X, Y, true> ...@@ -68,6 +76,8 @@ struct static_foreach_impl<X, Y, true>
static inline void _(Container const&, Fun&) { } static inline void _(Container const&, Fun&) { }
template<typename Container, typename Fun> template<typename Container, typename Fun>
static inline bool eval(Container const&, Fun&) { return true; } static inline bool eval(Container const&, Fun&) { return true; }
template<typename Container, typename Fun>
static inline bool eval_or(Container const&, Fun&) { return true; }
}; };
/** /**
......
...@@ -34,7 +34,7 @@ namespace cppa { ...@@ -34,7 +34,7 @@ namespace cppa {
value_matcher::~value_matcher() { } value_matcher::~value_matcher() { }
bool dummy_matcher::operator()(any_tuple const&) bool dummy_matcher::operator()(any_tuple const&) const
{ {
return true; return true;
} }
......
...@@ -11,58 +11,13 @@ using namespace cppa; ...@@ -11,58 +11,13 @@ using namespace cppa;
using std::vector; using std::vector;
using std::string; using std::string;
#define CPPA_GUARD_IMPL(GuardOperator) \
struct impl : util::guard<T> \
{ \
T m_val; \
impl(T&& val) : m_val(std::move(val)) { } \
bool operator()(T const& other) const { return other < m_val; } \
}; return std::unique_ptr<util::guard<T>>{new impl{std::move(value)}}
struct pattern_placeholder struct pattern_placeholder
{ {
constexpr pattern_placeholder() { } constexpr pattern_placeholder() { }
template<typename T>
std::unique_ptr<util::guard<T>> operator<(T value) const
{
CPPA_GUARD_IMPL(<);
}
template<typename T>
std::unique_ptr<util::guard<T>> operator<=(T value) const
{
CPPA_GUARD_IMPL(<=);
}
template<typename T>
std::unique_ptr<util::guard<T>> operator>(T value) const
{
CPPA_GUARD_IMPL(>);
}
template<typename T>
std::unique_ptr<util::guard<T>> operator>=(T value) const
{
CPPA_GUARD_IMPL(>=);
}
template<typename T>
T operator==(T value) const
{
return value;
}
template<typename T>
std::unique_ptr<util::guard<T>> operator!=(T value) const
{
CPPA_GUARD_IMPL(!=);
}
template<typename T> template<typename T>
std::unique_ptr<util::guard<T>> any_of(std::vector<T> vec) const std::unique_ptr<util::guard<T>> any_of(std::vector<T> vec) const
{ {
cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>" << endl;
typedef std::vector<T> vector_type; typedef std::vector<T> vector_type;
struct impl : util::guard<T> struct impl : util::guard<T>
{ {
...@@ -70,7 +25,6 @@ cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>" << endl; ...@@ -70,7 +25,6 @@ cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>" << endl;
impl(vector_type&& v) : m_vec(std::move(v)) { } impl(vector_type&& v) : m_vec(std::move(v)) { }
bool operator()(T const& value) const bool operator()(T const& value) const
{ {
cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>::operator()(" << value << ")" << endl;
return std::any_of(m_vec.begin(), m_vec.end(), return std::any_of(m_vec.begin(), m_vec.end(),
[&](T const& val) { return val == value; }); [&](T const& val) { return val == value; });
} }
...@@ -107,20 +61,428 @@ cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>" << endl; ...@@ -107,20 +61,428 @@ cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>" << endl;
return std::unique_ptr<util::guard<str_type>>{new impl{std::move(substr)}}; return std::unique_ptr<util::guard<str_type>>{new impl{std::move(substr)}};
} }
}; };
#define CPPA_GUARD_OPERATOR(Operator) \
template<typename T> \
std::unique_ptr<util::guard<T> > \
operator Operator (pattern_placeholder const&, T value) { \
struct impl : util::guard<T> { \
T m_val; \
impl(T&& val) : m_val(std::move(val)) { } \
bool operator()(T const& other) const \
{ return other Operator m_val; } \
}; \
return std::unique_ptr<util::guard<T> >{new impl{std::move(value)}}; \
} \
template<typename T> \
std::unique_ptr<util::guard<T> > \
operator Operator (T value, pattern_placeholder const&) { \
struct impl : util::guard<T> { \
T m_val; \
impl(T&& val) : m_val(std::move(val)) { } \
bool operator()(T const& other) const \
{ return m_val Operator other; } \
}; \
return std::unique_ptr<util::guard<T> >{new impl{std::move(value)}}; \
}
CPPA_GUARD_OPERATOR(<)
CPPA_GUARD_OPERATOR(<=)
CPPA_GUARD_OPERATOR(>)
CPPA_GUARD_OPERATOR(>=)
CPPA_GUARD_OPERATOR(==)
CPPA_GUARD_OPERATOR(!=)
static constexpr pattern_placeholder _x; static constexpr pattern_placeholder _x;
template<typename... Args> enum eval_op
void _on(Args&&...) {
addition_op,
subtraction_op,
multiplication_op,
division_op,
modulo_op,
less_op,
less_eq_op,
greater_op,
greater_eq_op,
equal_op,
not_equal_op,
exec_fun_op,
logical_and_op,
logical_or_op
};
#define CPPA_DISPATCH_OP(EnumValue, Operator) \
template<typename T1, typename T2> \
inline auto operator()(std::integral_constant<eval_op, EnumValue >, \
T1 const& lhs, T2 const& rhs) const \
-> decltype(lhs Operator rhs) { return lhs Operator rhs; }
struct op_dispatcher
{ {
constexpr op_dispatcher() { }
CPPA_DISPATCH_OP(addition_op, +)
CPPA_DISPATCH_OP(subtraction_op, -)
CPPA_DISPATCH_OP(multiplication_op, *)
CPPA_DISPATCH_OP(division_op, /)
CPPA_DISPATCH_OP(modulo_op, %)
CPPA_DISPATCH_OP(less_op, <)
CPPA_DISPATCH_OP(less_eq_op, <=)
CPPA_DISPATCH_OP(greater_op, >)
CPPA_DISPATCH_OP(greater_eq_op, >=)
CPPA_DISPATCH_OP(equal_op, ==)
CPPA_DISPATCH_OP(not_equal_op, !=)
template<typename T, typename Fun>
inline bool operator()(std::integral_constant<eval_op, exec_fun_op>,
T const& arg, Fun const& fun) const
{
return fun(arg);
}
};
static constexpr op_dispatcher s_opd;
template<eval_op, typename First, typename Second>
struct guard_expr;
template<int X>
struct guard_placeholder
{
constexpr guard_placeholder() { }
template<typename Fun>
guard_expr<exec_fun_op, guard_placeholder, Fun> operator()(Fun f) const
{
return {*this, std::move(f)};
}
};
template<eval_op OP, typename First, typename Second>
struct guard_expr;
template<typename... Ts, typename T>
T const& fetch(detail::tdata<Ts...> const&, T const& value)
{
return value;
}
template<typename... Ts, int X>
auto fetch(detail::tdata<Ts...> const& tup, guard_placeholder<X>)
-> decltype(*get<X>(tup))
{
return *get<X>(tup);
}
template<typename... Ts, eval_op OP, typename First, typename Second>
auto fetch(detail::tdata<Ts...> const& tup,
guard_expr<OP, First, Second> const& ge)
-> decltype(ge.eval(tup));
template<class Tuple, eval_op OP, typename First, typename Second>
auto eval_guard_expr(std::integral_constant<eval_op, OP> token,
Tuple const& tup,
First const& lhs,
Second const& rhs)
-> decltype(s_opd(token, fetch(tup, lhs), fetch(tup, rhs)))
{
return s_opd(token, fetch(tup, lhs), fetch(tup, rhs));
} }
template<class Tuple, typename First, typename Second>
bool eval_guard_expr(std::integral_constant<eval_op, logical_and_op>,
Tuple const& tup,
First const& lhs,
Second const& rhs)
{
// emulate short-circuit evaluation
if (fetch(tup, lhs)) return fetch(tup, rhs);
return false;
}
template<class Tuple, typename First, typename Second>
bool eval_guard_expr(std::integral_constant<eval_op, logical_or_op>,
Tuple const& tup,
First const& lhs,
Second const& rhs)
{
// emulate short-circuit evaluation
if (fetch(tup, lhs)) return true;
return fetch(tup, rhs);
}
template<typename T, class Tuple>
struct compute_
{
typedef T type;
};
template<int X, typename... Ts>
struct compute_<guard_placeholder<X>, detail::tdata<Ts...> >
{
typedef typename std::remove_pointer<typename util::at<X, Ts...>::type>::type type;
};
template<eval_op OP, typename First, typename Second, class Tuple>
struct compute_result_type
{
typedef bool type;
};
template<typename First, typename Second, class Tuple>
struct compute_result_type<addition_op, First, Second, Tuple>
{
typedef typename compute_<First, Tuple>::type lhs_type;
typedef typename compute_<Second, Tuple>::type rhs_type;
typedef decltype(lhs_type() + rhs_type()) type;
};
template<eval_op OP, typename First, typename Second>
struct guard_expr
{
std::pair<First, Second> m_args;
template<typename F, typename S>
guard_expr(F&& f, S&& s) : m_args(std::forward<F>(f), std::forward<S>(s)) { }
guard_expr() = default;
guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { }
guard_expr(guard_expr const&) = default;
template<typename... Args>
auto eval(detail::tdata<Args...> const& tup) const
-> typename compute_result_type<OP, First, Second, detail::tdata<Args...>>::type
{
std::integral_constant<eval_op, OP> token;
return eval_guard_expr(token, tup, m_args.first, m_args.second);
}
template<typename... Args>
auto operator()(Args const&... args) const
-> typename compute_result_type<OP, First, Second, detail::tdata<Args...>>::type
{
detail::tdata<Args const*...> tup{&args...};
return eval(tup);
}
};
template<typename... Ts, eval_op OP, typename First, typename Second>
auto fetch(detail::tdata<Ts...> const& tup,
guard_expr<OP, First, Second> const& ge)
-> decltype(ge.eval(tup))
{
return ge.eval(tup);
}
static constexpr guard_placeholder<0> _x1;
static constexpr guard_placeholder<1> _x2;
static constexpr guard_placeholder<2> _x3;
static constexpr guard_placeholder<3> _x4;
static constexpr guard_placeholder<4> _x5;
static constexpr guard_placeholder<5> _x6;
static constexpr guard_placeholder<6> _x7;
static constexpr guard_placeholder<7> _x8;
static constexpr guard_placeholder<8> _x9;
#define GUARD_PLACEHOLDER_OPERATOR(EnumValue, Operator) \
template<int Pos1, int Pos2> \
guard_expr< EnumValue , guard_placeholder<Pos1>, guard_placeholder<Pos2>> \
operator Operator (guard_placeholder<Pos1>, guard_placeholder<Pos2>) \
{ return {}; } \
template<int Pos, typename T> \
guard_expr< EnumValue , guard_placeholder<Pos>, \
typename detail::strip_and_convert<T>::type > \
operator Operator (guard_placeholder<Pos> gp, T value) \
{ return {std::move(gp), std::move(value)}; } \
template<typename T, int Pos> \
guard_expr< EnumValue , \
typename detail::strip_and_convert<T>::type, \
guard_placeholder<Pos> > \
operator Operator (T value, guard_placeholder<Pos> gp) \
{ return {std::move(value), std::move(gp)}; }
GUARD_PLACEHOLDER_OPERATOR(addition_op, +)
GUARD_PLACEHOLDER_OPERATOR(subtraction_op, -)
GUARD_PLACEHOLDER_OPERATOR(multiplication_op, *)
GUARD_PLACEHOLDER_OPERATOR(division_op, /)
GUARD_PLACEHOLDER_OPERATOR(modulo_op, %)
GUARD_PLACEHOLDER_OPERATOR(less_op, <)
GUARD_PLACEHOLDER_OPERATOR(less_eq_op, <=)
GUARD_PLACEHOLDER_OPERATOR(greater_op, >=)
GUARD_PLACEHOLDER_OPERATOR(greater_eq_op, >=)
GUARD_PLACEHOLDER_OPERATOR(equal_op, ==)
GUARD_PLACEHOLDER_OPERATOR(not_equal_op, !=)
template<eval_op OP1, typename F1, typename S1,
eval_op OP2, typename F2, typename S2>
guard_expr<logical_and_op, guard_expr<OP1, F1, S1>, guard_expr<OP2, F2, S2>>
operator&&(guard_expr<OP1, F1, S1> lhs,
guard_expr<OP2, F2, S2> rhs)
{
return {std::move(lhs), std::move(rhs)};
}
template<eval_op OP1, typename F1, typename S1,
eval_op OP2, typename F2, typename S2>
guard_expr<logical_or_op, guard_expr<OP1, F1, S1>, guard_expr<OP2, F2, S2>>
operator||(guard_expr<OP1, F1, S1> lhs,
guard_expr<OP2, F2, S2> rhs)
{
return {std::move(lhs), std::move(rhs)};
}
template<eval_op OP, typename F, typename S, typename T>
guard_expr<equal_op, guard_expr<OP, F, S>, T>
operator==(guard_expr<OP, F, S> lhs,
T rhs)
{
return {std::move(lhs), std::move(rhs)};
}
template<typename TupleTypes, class Fun>
bool eval_(any_tuple const& tup,
Fun const& fun)
{
typename util::tl_concat<TupleTypes, util::type_list<anything>>::type
cast_token;
auto x = tuple_cast(tup, cast_token);
CPPA_REQUIRE(static_cast<bool>(x) == true);
return util::unchecked_apply_tuple<bool>(fun, *x);
}
template<class GuardExpr, class TupleTypes>
struct guard_expr_value_matcher : value_matcher
{
GuardExpr m_expr;
guard_expr_value_matcher(GuardExpr&& ge) : m_expr(std::move(ge)) { }
bool operator()(any_tuple const& tup) const
{
typename util::tl_concat<TupleTypes, util::type_list<anything>>::type
cast_token;
auto x = tuple_cast(tup, cast_token);
CPPA_REQUIRE(static_cast<bool>(x) == true);
return util::unchecked_apply_tuple<bool>(m_expr, *x);
}
};
bool is_even(int i) { return i % 2 == 0; }
struct foobaz
{
template<typename... Args>
bool operator()(Args const&... args)
{
detail::tdata<Args const*...> tup{&args...};
cout << "0: " << fetch(tup, _x1) << endl;
return true;
}
};
template<eval_op OP, typename First, typename Second>
value_matcher* when(guard_expr<OP, First, Second> ge)
{
return nullptr;
}
std::string to_string(eval_op op)
{
switch (op)
{
case addition_op: return "+";
case less_op: return "<";
case less_eq_op: return "<=";
case greater_op: return ">";
case greater_eq_op: return ">=";
case equal_op: return "==";
case not_equal_op: return "!=";
case logical_and_op: return "&&";
case logical_or_op: return "||";
default: return "???";
}
}
/*
template<typename T>
std::string to_string(T const& value)
{
std::ostringstream oss;
oss << value;
return oss.str();
}
*/
template<int X>
std::string to_string(guard_placeholder<X>)
{
return "_x" + std::to_string(X+1);
}
template<typename... Ts, eval_op OP, typename First, typename Second>
std::string to_string(guard_expr<OP, First, Second> const& ge)
{
std::string result;
result += "(";
result += to_string(ge.m_args.first);
result += to_string(OP);
result += to_string(ge.m_args.second);
result += ")";
return result;
}
/*
*
* projection:
*
* on(_x.rsplit("--(.*)=(.*)")) >> [](std::vector<std::string> matched_groups) { }
*
*/
size_t test__match() size_t test__match()
{ {
CPPA_TEST(test__match); CPPA_TEST(test__match);
using namespace std::placeholders;
foobaz fb;
fb(1);
typedef util::type_list<int, int, int, int> ttypes;
any_tuple testee = make_cow_tuple(10, 20, 30, 40);
cout << "testee[0] < testee[1] = "
<< eval_<ttypes>(testee, _x1 < _x2)
<< " ---- > "
<< eval_<ttypes>(testee, _x1 < _x2 && _x2 < 50 && _x3 < _x4 && _x4 == 40)
<< " ---- > "
<< eval_<ttypes>(testee, 5 < _x1)
<< "; is_even(10): "
<< eval_<ttypes>(testee, _x1(is_even))
<< "; _x1 + _x2 < _x3: "
<< eval_<ttypes>(testee, _x1 + _x2 < _x3)
<< endl;
auto crazy_shit1 = _x1 < _x2 && _x2 < 50 && _x3 < _x4 && _x4 == 40;
auto crazy_shit2 = _x1 < _x2 && (_x2 < 50 && _x3 < _x4 && _x4 == 40);
cout << to_string(crazy_shit1) << endl;
cout << to_string(crazy_shit2) << endl;
auto expr1 = _x1 + _x2;
auto expr2 = _x1 + _x2 < _x3;
auto expr3 = _x1 % _x2 == 0;
CPPA_CHECK_EQUAL(5, (expr1(2, 3)));
CPPA_CHECK_EQUAL("12", (expr1(std::string{"1"}, std::string{"2"})));
CPPA_CHECK_EQUAL("((_x1+_x2)<_x3)", to_string(expr2));
CPPA_CHECK((expr3(100, 2)));
auto expr4 = _x1 == "-h" || _x1 == "--help";
CPPA_CHECK(expr4(std::string("-h")));
CPPA_CHECK(expr4(std::string("--help")));
CPPA_CHECK(!expr4(std::string("-g")));
exit(0);
/* /*
auto xfun = _x.any_of<int>({1, 2, 3}); auto xfun = _x.any_of<int>({1, 2, 3});
cout << "xfun(4) = " << xfun(4) << endl; cout << "xfun(4) = " << xfun(4) << endl;
...@@ -174,7 +536,6 @@ size_t test__match() ...@@ -174,7 +536,6 @@ size_t test__match()
); );
cout << endl; cout << endl;
} }
); );
match(5) match(5)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment