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