Commit 82504f3e authored by Dominik Charousset's avatar Dominik Charousset

improved pattern matching

this patch returns the result of a pattern matching expression
from detail::behavior_impl as optional<any_tuple>
parent e231a719
......@@ -31,14 +31,35 @@
#ifndef BEHAVIOR_IMPL_HPP
#define BEHAVIOR_IMPL_HPP
#include "cppa/optional.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/optional_variant.hpp"
#include "cppa/timeout_definition.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/type_traits.hpp"
namespace cppa { namespace detail {
struct optional_any_tuple_visitor {
typedef optional<any_tuple> result_type;
inline result_type operator()() const { return any_tuple{}; }
inline result_type operator()(const none_t&) const { return none; }
template<typename T>
inline result_type operator()(T& value) const {
return make_any_tuple(std::move(value));
}
};
template<typename... Ts>
struct has_match_hint {
static constexpr bool value = util::disjunction<
std::is_same<Ts, match_hint>::value...
>::value;
};
class behavior_impl : public ref_counted {
public:
......@@ -47,9 +68,9 @@ class behavior_impl : public ref_counted {
inline behavior_impl(util::duration tout) : m_timeout(tout) { }
virtual bool invoke(any_tuple&) = 0;
virtual bool invoke(const any_tuple&) = 0;
inline bool invoke(any_tuple&& arg) {
virtual optional<any_tuple> invoke(any_tuple&) = 0;
virtual optional<any_tuple> invoke(const any_tuple&) = 0;
inline optional<any_tuple> invoke(any_tuple&& arg) {
any_tuple tmp(std::move(arg));
return invoke(tmp);
}
......@@ -68,11 +89,15 @@ class behavior_impl : public ref_counted {
struct combinator : behavior_impl {
pointer first;
pointer second;
bool invoke(any_tuple& arg) {
return first->invoke(arg) || second->invoke(arg);
optional<any_tuple> invoke(any_tuple& arg) {
auto res = first->invoke(arg);
if (!res) return second->invoke(arg);
return res;
}
bool invoke(const any_tuple& arg) {
return first->invoke(arg) || second->invoke(arg);
optional<any_tuple> invoke(const any_tuple& arg) {
auto res = first->invoke(arg);
if (!res) return second->invoke(arg);
return res;
}
bool defined_at(const any_tuple& arg) {
return first->defined_at(arg) || second->defined_at(arg);
......@@ -110,6 +135,8 @@ class default_behavior_impl : public behavior_impl {
public:
typedef optional<any_tuple> invoke_result;
template<typename Expr>
default_behavior_impl(Expr&& expr, const timeout_definition<F>& d)
: super(d.timeout), m_expr(std::forward<Expr>(expr)), m_fun(d.handler) { }
......@@ -118,11 +145,11 @@ class default_behavior_impl : public behavior_impl {
default_behavior_impl(Expr&& expr, util::duration tout, F f)
: super(tout), m_expr(std::forward<Expr>(expr)), m_fun(f) { }
bool invoke(any_tuple& tup) {
invoke_result invoke(any_tuple& tup) {
return eval_res(m_expr(tup));
}
bool invoke(const any_tuple& tup) {
invoke_result invoke(const any_tuple& tup) {
return eval_res(m_expr(tup));
}
......@@ -138,22 +165,25 @@ class default_behavior_impl : public behavior_impl {
private:
template<typename T>
typename std::enable_if<T::has_match_hint == true, bool>::type
eval_res(const T& res) {
template<typename... Ts>
typename std::enable_if<has_match_hint<Ts...>::value, invoke_result>::type
eval_res(optional_variant<Ts...>&& res) {
if (res) {
if (res.template is<match_hint>()) {
return get<match_hint>(res) == match_hint::handle;
if (get<match_hint>(res) == match_hint::handle) {
return any_tuple{};
}
return none;
}
return true;
return apply_visitor(optional_any_tuple_visitor{}, res);
}
return false;
return none;
}
template<typename T>
typename std::enable_if<T::has_match_hint == false, bool>::type
eval_res(const T& res) {
return static_cast<bool>(res);
template<typename... Ts>
typename std::enable_if<!has_match_hint<Ts...>::value, invoke_result>::type
eval_res(optional_variant<Ts...>&& res) {
return apply_visitor(optional_any_tuple_visitor{}, res);
}
MatchExpr m_expr;
......@@ -188,19 +218,17 @@ class continuation_decorator : public behavior_impl {
}
template<typename T>
inline bool invoke_impl(T& tup) {
if (m_decorated->invoke(tup)) {
m_fun();
return true;
}
return false;
inline optional<any_tuple> invoke_impl(T& tup) {
auto res = m_decorated->invoke(tup);
if (res) m_fun();
return res;
}
bool invoke(any_tuple& tup) {
optional<any_tuple> invoke(any_tuple& tup) {
return invoke_impl(tup);
}
bool invoke(const any_tuple& tup) {
optional<any_tuple> invoke(const any_tuple& tup) {
return invoke_impl(tup);
}
......
......@@ -598,11 +598,6 @@ inline const void* fetch_native_data(const Ptr& ptr, std::false_type) {
return ptr->native_data();
}
} } // namespace cppa::detail
namespace cppa {
/** @cond PRIVATE */
template<typename T>
struct is_manipulator_case {
static constexpr bool value = T::second_type::manipulates_args;
......@@ -613,7 +608,9 @@ struct get_case_result {
typedef typename T::second_type::result_type type;
};
/** @endcond */
} } // namespace cppa::detail
namespace cppa {
/**
* @brief A match expression encapsulating cases <tt>Cs...</tt>.
......@@ -633,13 +630,16 @@ class match_expr {
typename util::tl_distinct<
typename util::tl_map<
cases_list,
get_case_result
detail::get_case_result
>::type
>::type
>::type
result_type;
static constexpr bool has_manipulator = util::tl_exists<cases_list, is_manipulator_case>::value;
static constexpr bool has_manipulator = util::tl_exists<
cases_list,
detail::is_manipulator_case
>::value;
typedef detail::long_constant<sizeof...(Cs)-1l> idx_token_type;
......@@ -658,21 +658,6 @@ class match_expr {
init();
}
/*
inline result_type invoke(const any_tuple& tup) {
return apply(tup);
}
inline result_type invoke(any_tuple& tup) {
return apply(tup);
}
inline result_type invoke(any_tuple&& tup) {
any_tuple tmp{tup};
return apply(tmp);
}
*/
bool can_invoke(const any_tuple& tup) {
auto type_token = tup.type_token();
if (not tup.dynamically_typed()) {
......@@ -755,6 +740,8 @@ class match_expr {
return {all_cases};
}
/** @cond PRIVATE */
inline const detail::tdata<Cs...>& cases() const {
return m_cases;
}
......@@ -766,6 +753,8 @@ class match_expr {
return new impl(*this, util::duration{}, lvoid);
}
/** @endcond */
private:
// structure: tdata< tdata<type_list<...>, ...>,
......@@ -790,7 +779,7 @@ class match_expr {
}
inline size_t find_token_pos(const std::type_info* type_token) {
for (size_t i = m_cache_begin ; i != m_cache_end; advance_(i)) {
for (size_t i = m_cache_begin ; i != m_cache_end; ++i) {
if (m_cache[i].first == type_token) return i;
}
return m_cache_end;
......
......@@ -71,7 +71,9 @@ template<class Expr, class Guard, typename Result, typename... Ts>
class tpartial_function {
typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename ctrait::arg_types ctrait_args;
static constexpr size_t num_expr_args = util::tl_size<ctrait_args>::value;
static_assert(util::tl_exists<util::type_list<Ts...>,
......@@ -82,6 +84,8 @@ class tpartial_function {
typedef util::type_list<Ts...> arg_types;
typedef Guard guard_type;
static constexpr size_t num_arguments = sizeof...(Ts);
static constexpr bool manipulates_args =
......
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