Commit f2f60445 authored by Dominik Charousset's avatar Dominik Charousset

Simplify advanced match case a bit

parent d90a8554
...@@ -209,7 +209,7 @@ intrusive_ptr<R> make_behavior_ra(timeout_definition<F>& td, ...@@ -209,7 +209,7 @@ intrusive_ptr<R> make_behavior_ra(timeout_definition<F>& td,
} }
template <class R, class... Ts> template <class R, class... Ts>
intrusive_ptr<R> make_behavior_ra(tail_argument_token&, Ts... xs) { intrusive_ptr<R> make_behavior_ra(tail_argument_token&, Ts&... xs) {
return make_behavior_eor<R>(std::tuple_cat(to_match_case_tuple(xs)...)); return make_behavior_eor<R>(std::tuple_cat(to_match_case_tuple(xs)...));
} }
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "caf/match_case.hpp" #include "caf/match_case.hpp"
#include "caf/timeout_definition.hpp" #include "caf/timeout_definition.hpp"
#include "caf/detail/tail_argument_token.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
...@@ -105,79 +107,97 @@ struct tuple_maker { ...@@ -105,79 +107,97 @@ struct tuple_maker {
struct variadic_ctor {}; struct variadic_ctor {};
template <class Expr, class Transformers, class Pattern> template <class F, class Projections, class Pattern>
struct get_advanced_match_case { struct advanced_match_case_factory {
using ctrait = typename get_callable_trait<Expr>::type; static constexpr bool uses_arg_match =
std::is_same<
arg_match_t,
typename detail::tl_back<Pattern>::type
>::value;
using filtered_pattern = using fargs = typename get_callable_trait<F>::arg_types;
typename tl_filter_not_type<
Pattern, static constexpr size_t fargs_size =
anything detail::tl_size<
fargs
>::value;
using decayed_fargs =
typename tl_map<
fargs,
std::decay
>::type; >::type;
using padded_transformers = using concatenated_pattern =
typename tl_pad_right< typename detail::tl_concat<
Transformers, typename detail::tl_pop_back<Pattern>::type,
tl_size<filtered_pattern>::value decayed_fargs
>::type; >::type;
using base_signature = using full_pattern =
typename tl_map< typename std::conditional<
filtered_pattern, uses_arg_match,
std::add_const, concatenated_pattern,
std::add_lvalue_reference Pattern
>::type; >::type;
using padded_expr_args = using filtered_pattern =
typename tl_map_conditional< typename detail::tl_filter_not_type<
typename tl_pad_left< full_pattern,
typename ctrait::arg_types, anything
tl_size<filtered_pattern>::value
>::type,
std::is_lvalue_reference,
false,
std::add_const,
std::add_lvalue_reference
>::type; >::type;
// override base signature with required argument types of Expr using padded_projections =
// and result types of transformation typename detail::tl_pad_right<
using partial_fun_signature = Projections,
typename tl_zip< detail::tl_size<filtered_pattern>::value
typename tl_map< >::type;
padded_transformers,
map_to_result_type, using projection_funs =
rm_optional, typename detail::tl_apply<
std::add_lvalue_reference padded_projections,
std::tuple
>::type;
using tuple_type =
typename detail::tl_apply<
typename detail::tl_zip_right<
typename detail::tl_map<
padded_projections,
projection_result
>::type, >::type,
typename tl_zip< fargs,
padded_expr_args, detail::left_or_right,
base_signature, fargs_size
left_or_right
>::type, >::type,
left_or_right std::tuple
>::type; >::type;
// 'inherit' mutable references from partial_fun_signature using padding =
// for arguments without transformation typename detail::tl_apply<
using projection_signature = typename detail::tl_replicate<fargs_size, unit_t>::type,
typename tl_zip< std::tuple
typename tl_zip<
padded_transformers,
partial_fun_signature,
if_not_left
>::type,
base_signature,
deduce_ref_type
>::type; >::type;
using type = static projection_funs pad(projection_funs res, std::false_type) {
advanced_match_case_impl< return std::move(res);
Expr, }
Pattern,
padded_transformers, template <class Guards>
projection_signature static projection_funs pad(Guards gs, std::true_type) {
>; return std::tuple_cat(std::move(gs), padding{});
}
using case_type = advanced_match_case_impl<F, tuple_type,
full_pattern, projection_funs>;
template <class Guards>
static case_type create(F f, Guards gs) {
std::integral_constant<bool, uses_arg_match> tk;
return {tl_exists<full_pattern, is_anything>::value,
make_type_token_from_list<full_pattern>(), std::move(f),
pad(std::move(gs), tk)};
}
}; };
template <class X, class Y> template <class X, class Y>
...@@ -190,40 +210,42 @@ struct pattern_projection_zipper<anything, Y> { ...@@ -190,40 +210,42 @@ struct pattern_projection_zipper<anything, Y> {
using type = none_t; using type = none_t;
}; };
template <class Projections, class Pattern, template <class Projections, class Pattern>
bool UsesArgMatch =
std::is_same<
arg_match_t,
typename tl_back<Pattern>::type
>::value>
class advanced_match_case_builder : public message_case_builder { class advanced_match_case_builder : public message_case_builder {
public: public:
using guards_tuple = using filtered_projections =
typename tl_apply<
// discard projection if at the same index in Pattern is a wildcard
typename tl_filter_not_type< typename tl_filter_not_type<
typename tl_zip<Pattern, Projections, pattern_projection_zipper>::type, typename tl_zip<
Pattern,
Projections,
pattern_projection_zipper
>::type,
none_t none_t
>::type;
using guards_tuple =
typename detail::tl_apply<
typename std::conditional<
std::is_same<
arg_match_t,
typename tl_back<Pattern>::type
>::value,
typename tl_pop_back<filtered_projections>::type,
filtered_projections
>::type, >::type,
std::tuple std::tuple
>::type; >::type;
advanced_match_case_builder() = default;
template <class... Fs> template <class... Fs>
advanced_match_case_builder(variadic_ctor, Fs... fs) advanced_match_case_builder(variadic_ctor, Fs... fs)
: m_guards(make_guards(Pattern{}, fs...)) { : m_g(make_guards(Pattern{}, fs...)) {
// nop
}
advanced_match_case_builder(guards_tuple arg1) : m_guards(std::move(arg1)) {
// nop // nop
} }
template <class F> template <class F>
typename get_advanced_match_case<F, Projections, Pattern>::type typename advanced_match_case_factory<F, Projections, Pattern>::case_type
operator>>(F f) const { operator>>(F f) const {
return {f, m_guards}; return advanced_match_case_factory<F, Projections, Pattern>::create(f, m_g);
} }
private: private:
...@@ -232,71 +254,6 @@ class advanced_match_case_builder : public message_case_builder { ...@@ -232,71 +254,6 @@ class advanced_match_case_builder : public message_case_builder {
return std::make_tuple(std::move(fs)...); return std::make_tuple(std::move(fs)...);
} }
template <class T, class F, class... Fs>
static guards_tuple make_guards(std::pair<wrapped<T>, F> x, Fs&&... fs) {
return make_guards(std::forward<Fs>(fs)..., x.second);
}
template <class F, class... Fs>
static guards_tuple make_guards(std::pair<wrapped<anything>, F>, Fs&&... fs) {
return make_guards(std::forward<Fs>(fs)...);
}
template <class... Ts, class... Fs>
static guards_tuple make_guards(type_list<Ts...>, Fs&... fs) {
tail_argument_token eoa;
return make_guards(std::make_pair(wrapped<Ts>(), std::ref(fs))..., eoa);
}
guards_tuple m_guards;
};
template <class Projections, class Pattern>
struct advanced_match_case_builder<Projections, Pattern, true>
: public message_case_builder {
public:
using guards_tuple =
typename detail::tl_apply<
typename tl_pop_back<Projections>::type,
std::tuple
>::type;
using pattern = typename tl_pop_back<Pattern>::type;
advanced_match_case_builder() = default;
template <class... Fs>
advanced_match_case_builder(variadic_ctor, Fs... fs)
: m_guards(make_guards(Pattern{}, fs...)) {
// nop
}
advanced_match_case_builder(guards_tuple arg1) : m_guards(std::move(arg1)) {
// nop
}
template <class F>
typename get_advanced_match_case<
F,
Projections,
typename tl_concat<
pattern,
typename tl_map<
typename get_callable_trait<F>::arg_types,
std::decay
>::type
>::type
>::type
operator>>(F f) const {
using padding =
typename tl_apply<
typename tl_replicate<get_callable_trait<F>::num_args, unit_t>::type,
std::tuple
>::type;
return {f, std::tuple_cat(m_guards, padding{})};
}
private:
static guards_tuple make_guards(tail_argument_token&) { static guards_tuple make_guards(tail_argument_token&) {
return {}; return {};
} }
...@@ -323,7 +280,7 @@ struct advanced_match_case_builder<Projections, Pattern, true> ...@@ -323,7 +280,7 @@ struct advanced_match_case_builder<Projections, Pattern, true>
return make_guards(std::make_pair(wrapped<Ts>(), std::ref(fs))..., eoa); return make_guards(std::make_pair(wrapped<Ts>(), std::ref(fs))..., eoa);
} }
guards_tuple m_guards; guards_tuple m_g;
}; };
template <class Left, class Right> template <class Left, class Right>
......
...@@ -317,28 +317,13 @@ struct projection_is_trivial { ...@@ -317,28 +317,13 @@ struct projection_is_trivial {
>::value == 0; >::value == 0;
}; };
/* /**
* A lifted functor consists of a set of projections, a plain-old * @tparam F Function or function object denoting the callback.
* functor and its signature. Note that the signature of the lifted * @tparam Tuple Type of the storage for intermediate results during matching.
* functor might differ from the underlying functor, because * @tparam Pattern Input types for this match case.
* of the projections.
*/ */
template <class F, class Pattern, class Projections, class Signature> template <class F, class Tuple, class Pattern, class Projections>
class advanced_match_case_impl : public class advanced_match_case_impl : public advanced_match_case<F, Tuple> {
advanced_match_case<
F,
typename detail::tl_apply<
typename detail::tl_zip_right<
typename detail::tl_map<
Projections,
projection_result
>::type,
typename detail::get_callable_trait<F>::arg_types,
detail::left_or_right,
detail::get_callable_trait<F>::num_args
>::type,
std::tuple
>::type> {
public: public:
using plain_result_type = typename detail::get_callable_trait<F>::result_type; using plain_result_type = typename detail::get_callable_trait<F>::result_type;
...@@ -349,22 +334,8 @@ class advanced_match_case_impl : public ...@@ -349,22 +334,8 @@ class advanced_match_case_impl : public
typename std::remove_const<plain_result_type>::type typename std::remove_const<plain_result_type>::type
>::type; >::type;
using pattern = Pattern;
using filtered_pattern =
typename detail::tl_filter_not_type<
Pattern,
anything
>::type;
using intermediate_tuple =
typename detail::tl_apply<
filtered_pattern,
detail::pseudo_tuple
>::type;
static constexpr uint32_t static_type_token = static constexpr uint32_t static_type_token =
detail::make_type_token_from_list<pattern>(); detail::make_type_token_from_list<Pattern>();
// Let F be "R (Ts...)" then match_case<F...> returns optional<R> // Let F be "R (Ts...)" then match_case<F...> returns optional<R>
// unless R is void in which case bool is returned // unless R is void in which case bool is returned
...@@ -375,73 +346,42 @@ class advanced_match_case_impl : public ...@@ -375,73 +346,42 @@ class advanced_match_case_impl : public
optional<result_type> optional<result_type>
>::type; >::type;
using projections_list = Projections; // Needed for static type checking when assigning to a typed behavior.
using arg_types = Pattern;
using projections =
typename detail::tl_apply<
projections_list,
std::tuple
>::type;
/* using fargs = typename detail::get_callable_trait<F>::arg_types;
* Needed for static type checking when assigning to a typed behavior.
*/
using arg_types = Signature;
using fun_args = typename detail::get_callable_trait<F>::arg_types; static constexpr size_t fargs_size = detail::tl_size<fargs>::value;
static constexpr size_t num_fun_args = detail::tl_size<fun_args>::value; using super = advanced_match_case<F, Tuple>;
static constexpr bool is_manipulator = advanced_match_case_impl(advanced_match_case_impl&&) = default;
detail::tl_exists<
fun_args,
detail::is_mutable_ref
>::value;
using tuple_type =
typename detail::tl_apply<
typename detail::tl_zip_right<
typename detail::tl_map<
projections_list,
projection_result
>::type,
fun_args,
detail::left_or_right,
num_fun_args
>::type,
std::tuple
>::type;
using super = advanced_match_case<F, tuple_type>;
advanced_match_case_impl() = default;
advanced_match_case_impl(const advanced_match_case_impl&) = default; advanced_match_case_impl(const advanced_match_case_impl&) = default;
advanced_match_case_impl& operator=(advanced_match_case_impl&&) = default; advanced_match_case_impl(bool has_wcard, uint32_t ttoken, F f, Projections ps)
: super(has_wcard, ttoken, std::move(f)),
advanced_match_case_impl& operator=(const advanced_match_case_impl&) = default;
advanced_match_case_impl(F f)
: super(pattern_has_wildcard<Pattern>::value, static_type_token,
std::move(f)) {
// nop
}
advanced_match_case_impl(F f, projections ps)
: super(pattern_has_wildcard<Pattern>::value, static_type_token,
std::move(f)),
m_ps(std::move(ps)) { m_ps(std::move(ps)) {
// nop // nop
} }
bool prepare_invoke(message& msg, tuple_type* out) { bool prepare_invoke(message& msg, Tuple* out) {
// detach msg before invoking m_fun if needed // detach msg before invoking m_fun if needed
if (is_manipulator) { if (detail::tl_exists<fargs, detail::is_mutable_ref>::value) {
msg.force_detach(); msg.force_detach();
} }
using filtered_pattern =
typename detail::tl_filter_not_type<
Pattern,
anything
>::type;
using intermediate_tuple =
typename detail::tl_apply<
filtered_pattern,
detail::pseudo_tuple
>::type;
intermediate_tuple it; intermediate_tuple it;
detail::meta_elements<pattern> ms; detail::meta_elements<Pattern> ms;
// check if try_match() reports success // check if try_match() reports success
if (!detail::try_match(msg, ms.arr.data(), ms.arr.size(), it.data)) { if (!detail::try_match(msg, ms.arr.data(), ms.arr.size(), it.data)) {
return false; return false;
...@@ -449,8 +389,8 @@ class advanced_match_case_impl : public ...@@ -449,8 +389,8 @@ class advanced_match_case_impl : public
match_case_zipper zip; match_case_zipper zip;
using indices_type = typename detail::il_indices<intermediate_tuple>::type; using indices_type = typename detail::il_indices<intermediate_tuple>::type;
//indices_type indices; //indices_type indices;
typename detail::il_take<indices_type, detail::tl_size<projections_list>::value - num_fun_args>::type lefts; typename detail::il_take<indices_type, std::tuple_size<Projections>::value - fargs_size>::type lefts;
typename detail::il_right<indices_type, num_fun_args>::type rights; typename detail::il_right<indices_type, fargs_size>::type rights;
has_none hn; has_none hn;
// check if guards of discarded arguments are fulfilled // check if guards of discarded arguments are fulfilled
auto lhs_tup = tuple_zip(zip, lefts, m_ps, it); auto lhs_tup = tuple_zip(zip, lefts, m_ps, it);
...@@ -458,18 +398,18 @@ class advanced_match_case_impl : public ...@@ -458,18 +398,18 @@ class advanced_match_case_impl : public
return false; return false;
} }
// zip remaining arguments into output tuple // zip remaining arguments into output tuple
new (out) tuple_type(tuple_zip(zip, rights, m_ps, it)); new (out) Tuple (tuple_zip(zip, rights, m_ps, it));
//tuple_type rhs_tup = tuple_zip(zip, rights, m_ps, it); //tuple_type rhs_tup = tuple_zip(zip, rights, m_ps, it);
// check if remaining guards are fulfilled // check if remaining guards are fulfilled
if (detail::apply_args(hn, detail::get_indices(*out), *out)) { if (detail::apply_args(hn, detail::get_indices(*out), *out)) {
out->~tuple_type(); out->~Tuple();
return false; return false;
} }
return true; return true;
} }
private: private:
projections m_ps; Projections m_ps;
}; };
struct match_case_info { struct match_case_info {
......
...@@ -39,9 +39,9 @@ ...@@ -39,9 +39,9 @@
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/arg_match_t.hpp" #include "caf/detail/arg_match_t.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/detail/match_case_builder.hpp"
#include "caf/detail/tail_argument_token.hpp" #include "caf/detail/tail_argument_token.hpp"
#include "caf/detail/implicit_conversions.hpp" #include "caf/detail/implicit_conversions.hpp"
#include "caf/detail/message_case_builder.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
......
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