Commit 2ced36ba authored by Dominik Charousset's avatar Dominik Charousset

Simplify pattern matching implementation

Remove template-based pattern matching implementation.  The removed code is too
complex and as a result too hard to maintain in the long run. Also, the main
use case for wildcards is `others()`. Other use cases seem rare (and often
unlikely) and thus do not justify the optimizations in the first place..
parent 9abec963
...@@ -26,166 +26,38 @@ ...@@ -26,166 +26,38 @@
#include "caf/wildcard_position.hpp" #include "caf/wildcard_position.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/pseudo_tuple.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
template <wildcard_position, class Tuple, class...> template <class Pattern, class FilteredPattern>
struct matcher; struct matcher;
template <class Tuple, class... T> template <class... Ts, class... Us>
struct matcher<wildcard_position::nil, Tuple, T...> { struct matcher<type_list<Ts...>, type_list<Us...>> {
bool operator()(const Tuple& tup) const {
if (not tup.dynamically_typed()) {
// statically typed tuples return &typeid(type_list<T...>)
// as type token
return typeid(detail::type_list<T...>)== *(tup.type_token());
}
// always use a full dynamic match for dynamic typed tuples
else if (tup.size() == sizeof...(T)) {
auto& tarr = static_types_array<T...>::arr;
return std::equal(tup.begin(), tup.end(), tarr.begin(),
types_only_eq);
}
return false;
}
bool operator()(const Tuple& tup, std::vector<size_t>& mv) const {
if ((*this)(tup)) {
mv.resize(sizeof...(T));
std::iota(mv.begin(), mv.end(), 0);
return true;
}
return false;
}
};
template <class Tuple, class... T>
struct matcher<wildcard_position::trailing, Tuple, T...> {
static constexpr size_t size = sizeof...(T) - 1;
bool operator()(const Tuple& tup) const {
if (tup.size() >= size) {
auto& tarr = static_types_array<T...>::arr;
auto begin = tup.begin();
return std::equal(begin, begin + size, tarr.begin(), types_only_eq);
}
return false;
}
bool operator()(const Tuple& tup, std::vector<size_t>& mv) const {
if ((*this)(tup)) {
mv.resize(size);
std::iota(mv.begin(), mv.end(), 0);
return true;
}
return false;
}
};
template <class Tuple>
struct matcher<wildcard_position::leading, Tuple, anything> {
bool operator()(const Tuple&) const { return true; }
bool operator()(const Tuple&, std::vector<size_t>&) const { return true; }
};
template <class Tuple, class... T>
struct matcher<wildcard_position::leading, Tuple, T...> {
static constexpr size_t size = sizeof...(T) - 1;
bool operator()(const Tuple& tup) const {
auto tup_size = tup.size();
if (tup_size >= size) {
auto& tarr = static_types_array<T...>::arr;
auto begin = tup.begin();
begin += (tup_size - size);
return std::equal(begin, tup.end(),
(tarr.begin() + 1), // skip 'anything'
types_only_eq);
}
return false;
}
bool operator()(const Tuple& tup, std::vector<size_t>& mv) const {
if ((*this)(tup)) {
mv.resize(size);
std::iota(mv.begin(), mv.end(), tup.size() - size);
return true;
}
return false;
}
};
template <class Tuple, class... T>
struct matcher<wildcard_position::in_between, Tuple, T...> {
static constexpr int signed_wc_pos =
detail::tl_find<detail::type_list<T...>, anything>::value;
static constexpr size_t size = sizeof...(T);
static constexpr size_t wc_pos = static_cast<size_t>(signed_wc_pos);
static_assert(signed_wc_pos > 0 && wc_pos < (sizeof...(T) - 1),
"illegal wildcard position");
bool operator()(const Tuple& tup) const {
auto tup_size = tup.size();
if (tup_size >= (size - 1)) {
auto& tarr = static_types_array<T...>::arr;
// first range [0, X1)
auto begin = tup.begin();
auto end = begin + wc_pos;
if (std::equal(begin, end, tarr.begin(), types_only_eq)) {
// second range [X2, N)
begin = end = tup.end();
begin -= (size - (wc_pos + 1));
auto arr_begin = tarr.begin() + (wc_pos + 1);
return std::equal(begin, end, arr_begin, types_only_eq);
}
}
return false;
}
bool operator()(const Tuple& tup, std::vector<size_t>& mv) const {
if ((*this)(tup)) {
// first range
mv.resize(size - 1);
auto begin = mv.begin();
std::iota(begin, begin + wc_pos, 0);
// second range
begin = mv.begin() + wc_pos;
std::iota(begin, mv.end(), tup.size() - (size - (wc_pos + 1)));
return true;
}
return false;
}
};
template <class Tuple, class... T>
struct matcher<wildcard_position::multiple, Tuple, T...> {
static constexpr size_t wc_count =
detail::tl_count<detail::type_list<T...>, is_anything>::value;
static_assert(sizeof...(T) > wc_count, "only wildcards given");
template <class TupleIter, class PatternIter, class Push, class Commit, template <class TupleIter, class PatternIter, class Push, class Commit,
class Rollback> class Rollback>
bool operator()(TupleIter tbegin, TupleIter tend, PatternIter pbegin, bool operator()(TupleIter tbegin, TupleIter tend, PatternIter pbegin,
PatternIter pend, Push& push, Commit& commit, PatternIter pend, Push& push, Commit& commit,
Rollback& rollback) const { Rollback& rollback) const {
while (!(pbegin == pend && tbegin == tend)) { while (!(pbegin == pend && tbegin == tend)) {
if (pbegin == pend) { if (pbegin == pend) {
// reached end of pattern while some values remain unmatched // reached end of pattern while some values remain unmatched
return false; return false;
} else if (*pbegin == nullptr) { // nullptr == wildcard (anything) }
if (*pbegin == nullptr) { // nullptr == wildcard (anything)
// perform submatching // perform submatching
++pbegin; ++pbegin;
// always true at the end of the pattern // always true at the end of the pattern
if (pbegin == pend) return true; if (pbegin == pend) {
return true;
}
// safe current mapping as fallback // safe current mapping as fallback
commit(); commit();
// iterate over tuple values until we found a match // iterate over tuple values until we found a match
for (; tbegin != tend; ++tbegin) { for (; tbegin != tend; ++tbegin) {
if (match(tbegin, tend, pbegin, pend, push, commit, if ((*this)(tbegin, tend, pbegin, pend, push, commit, rollback)) {
rollback)) {
return true; return true;
} }
// restore mapping to fallback (delete invalid mappings) // restore mapping to fallback (delete invalid mappings)
...@@ -194,56 +66,43 @@ struct matcher<wildcard_position::multiple, Tuple, T...> { ...@@ -194,56 +66,43 @@ struct matcher<wildcard_position::multiple, Tuple, T...> {
return false; // no submatch found return false; // no submatch found
} }
// compare types // compare types
else if (tbegin.type() == *pbegin) if (tbegin.type() != *pbegin) {
push(tbegin); // type mismatch
// no match
else
return false; return false;
}
// next iteration // next iteration
push(tbegin);
++tbegin; ++tbegin;
++pbegin; ++pbegin;
} }
return true; // pbegin == pend && tbegin == tend return true; // pbegin == pend && tbegin == tend
} }
bool operator()(const Tuple& tup) const { bool operator()(const message& tup, pseudo_tuple<Us...>* out) const {
auto& tarr = static_types_array<T...>::arr; auto& tarr = static_types_array<Ts...>::arr;
if (tup.size() >= (sizeof...(T) - wc_count)) { if (sizeof...(Us) == 0) {
auto fpush = [](const typename Tuple::const_iterator&) {}; // this pattern only has wildcards and thus always matches
auto fcommit = [] {}; return true;
auto frollback = [] {};
return match(tup.begin(), tup.end(), tarr.begin(), tarr.end(),
fpush, fcommit, frollback);
} }
return false; if (tup.size() < sizeof...(Us)) {
} return false;
}
template <class MappingVector> if (out) {
bool operator()(const Tuple& tup, MappingVector& mv) const { size_t pos = 0;
auto& tarr = static_types_array<T...>::arr; size_t fallback_pos = 0;
if (tup.size() >= (sizeof...(T) - wc_count)) { auto fpush = [&](const typename message::const_iterator& iter) {
size_t commited_size = 0; (*out)[pos++] = const_cast<void*>(iter.value());
auto fpush = [&](const typename Tuple::const_iterator& iter) {
mv.push_back(iter.position());
}; };
auto fcommit = [&] { commited_size = mv.size(); }; auto fcommit = [&] { fallback_pos = pos; };
auto frollback = [&] { mv.resize(commited_size); }; auto frollback = [&] { pos = fallback_pos; };
return match(tup.begin(), tup.end(), tarr.begin(), tarr.end(), return (*this)(tup.begin(), tup.end(), tarr.begin(), tarr.end(), fpush,
fpush, fcommit, frollback); fcommit, frollback);
} }
return false; auto no_push = [](const typename message::const_iterator&) { };
auto nop = [] { };
return (*this)(tup.begin(), tup.end(), tarr.begin(), tarr.end(), no_push,
nop, nop);
} }
};
template <class Tuple, class List>
struct select_matcher;
template <class Tuple, class... Ts>
struct select_matcher<Tuple, detail::type_list<Ts...>> {
using type = matcher<get_wildcard_position<detail::type_list<Ts...>>(),
Tuple, Ts...>;
}; };
} // namespace detail } // namespace detail
......
This diff is collapsed.
...@@ -20,6 +20,7 @@ add_unit_test(variant) ...@@ -20,6 +20,7 @@ add_unit_test(variant)
add_unit_test(atom) add_unit_test(atom)
add_unit_test(metaprogramming) add_unit_test(metaprogramming)
add_unit_test(intrusive_containers) add_unit_test(intrusive_containers)
add_unit_test(match)
add_unit_test(serialization) add_unit_test(serialization)
add_unit_test(uniform_type) add_unit_test(uniform_type)
add_unit_test(fixed_vector) add_unit_test(fixed_vector)
......
This diff is collapsed.
...@@ -301,7 +301,11 @@ void test_sync_send() { ...@@ -301,7 +301,11 @@ void test_sync_send() {
}); });
self->on_sync_failure(CAF_UNEXPECTED_MSG_CB_REF(self)); self->on_sync_failure(CAF_UNEXPECTED_MSG_CB_REF(self));
self->timed_sync_send(c, std::chrono::milliseconds(500), atom("HiThere")) self->timed_sync_send(c, std::chrono::milliseconds(500), atom("HiThere"))
.await(CAF_FAILURE_CB("C replied to 'HiThere'!")); .await(
on(val<atom_value>) >> [&] {
cout << "C did reply to 'HiThere'" << endl;
}
);
CAF_CHECK_EQUAL(timeout_occured, true); CAF_CHECK_EQUAL(timeout_occured, true);
self->on_sync_failure(CAF_UNEXPECTED_MSG_CB_REF(self)); self->on_sync_failure(CAF_UNEXPECTED_MSG_CB_REF(self));
self->sync_send(c, atom("gogo")).await(CAF_CHECKPOINT_CB()); self->sync_send(c, atom("gogo")).await(CAF_CHECKPOINT_CB());
......
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