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