Commit ada8fbb3 authored by neverlord's avatar neverlord

pattern matching improvements

parent e41694da
......@@ -198,6 +198,7 @@ nobase_library_include_HEADERS = \
cppa/util/is_legal_tuple_type.hpp \
cppa/util/is_one_of.hpp \
cppa/util/is_primitive.hpp \
cppa/util/option.hpp \
cppa/util/producer_consumer_list.hpp \
cppa/util/pt_dispatch.hpp \
cppa/util/pt_token.hpp \
......
......@@ -250,3 +250,4 @@ cppa/detail/types_array.hpp
cppa/util/is_builtin.hpp
cppa/util/type_pair.hpp
cppa/util/tbind.hpp
cppa/util/option.hpp
......@@ -39,8 +39,8 @@
namespace cppa {
template<typename... Types>
tuple_view<Types...> tuple_cast(any_tuple&& tup);
//template<typename... Types>
//tuple_view<Types...> tuple_cast(any_tuple&& tup);
/**
* @brief Describes a fixed-length tuple with elements of any type.
......@@ -48,8 +48,8 @@ tuple_view<Types...> tuple_cast(any_tuple&& tup);
class any_tuple
{
template<typename... Types>
friend tuple_view<Types...> tuple_cast(any_tuple&& tup);
//template<typename... Types>
//friend tuple_view<Types...> tuple_cast(any_tuple&& tup);
cow_ptr<detail::abstract_tuple> m_vals;
......@@ -57,8 +57,6 @@ class any_tuple
public:
//typedef cow_ptr<detail::abstract_tuple> vals_ptr;
any_tuple();
template<typename... Args>
......@@ -102,6 +100,8 @@ class any_tuple
template<typename T>
inline T& get_mutable_as(size_t p);
};
inline bool operator==(any_tuple const& lhs, any_tuple const& rhs)
......@@ -126,6 +126,7 @@ inline T& any_tuple::get_mutable_as(size_t p)
return *reinterpret_cast<T*>(mutable_at(p));
}
/*
template<typename... Types>
tuple_view<Types...> tuple_cast(any_tuple const& tup)
{
......@@ -137,6 +138,7 @@ tuple_view<Types...> tuple_cast(any_tuple&& tup)
{
return tuple_view<Types...>::from(std::move(tup.m_vals));
}
*/
} // namespace cppa
......
......@@ -101,6 +101,8 @@ class cow_ptr
cow_ptr(T* raw_ptr) : m_ptr(raw_ptr) { }
cow_ptr(cow_ptr&& other) : m_ptr(std::move(other.m_ptr)) { }
cow_ptr(cow_ptr const& other) : m_ptr(other.m_ptr) { }
template<typename Y>
......@@ -111,6 +113,12 @@ class cow_ptr
m_ptr.swap(other.m_ptr);
}
cow_ptr& operator=(cow_ptr&& other)
{
swap(other);
return *this;
}
cow_ptr& operator=(cow_ptr const& other)
{
cow_ptr tmp(other);
......
......@@ -35,7 +35,6 @@
#include "cppa/tuple.hpp"
#include "cppa/channel.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp"
......
......@@ -45,18 +45,21 @@
namespace cppa { namespace detail {
template<typename... ElementTypes>
template<size_t VectorSize>
class decorated_tuple : public abstract_tuple
{
public:
typedef util::fixed_vector<size_t, sizeof...(ElementTypes)> vector_type;
typedef util::type_list<ElementTypes...> element_types;
typedef util::fixed_vector<size_t, VectorSize> vector_type;
typedef cow_ptr<abstract_tuple> ptr_type;
decorated_tuple(ptr_type&& d, vector_type const& v)
: m_decorated(std::move(d)), m_mappings(v)
{
}
decorated_tuple(ptr_type const& d, vector_type const& v)
: m_decorated(d), m_mappings(v)
{
......
......@@ -43,79 +43,6 @@
namespace cppa { namespace detail {
template<typename OutputIterator, typename T0>
void fill_uti_vec(OutputIterator& ii)
{
typedef typename unboxed<T0>::type real_type;
*ii = std::is_same<real_type,anything>::value ? nullptr
: uniform_typeid<real_type>();
}
template<typename OutputIterator, typename T0, typename T1, typename... Tn>
void fill_uti_vec(OutputIterator& ii)
{
fill_uti_vec<OutputIterator, T0>(ii);
fill_uti_vec<OutputIterator, T1, Tn...>(++ii);
}
template<typename T0>
struct fill_vecs_util
{
template<typename DataTuple>
inline static void _(size_t pos,
size_t dt_size,
bool* dt_is_invalid,
DataTuple const& dt,
cppa::uniform_type_info const* * utis,
void const* * data_ptrs)
{
utis[pos] = uniform_typeid<T0>();
data_ptrs[pos] = (pos < dt_size && !(dt_is_invalid[pos])) ? dt.at(pos)
: nullptr;
}
};
template<>
struct fill_vecs_util<anything>
{
template<typename DataTuple>
inline static void _(size_t pos,
size_t,
bool*,
DataTuple const&,
cppa::uniform_type_info const* * utis,
void const* * data_ptrs)
{
utis[pos] = nullptr;
data_ptrs[pos] = nullptr;
}
};
template<typename DataTuple, typename T0>
void fill_vecs(size_t pos,
size_t dt_size,
bool* dt_invalids,
DataTuple const& dt,
cppa::uniform_type_info const* * utis,
void const* * data_ptrs)
{
fill_vecs_util<T0>::_(pos, dt_size, dt_invalids, dt, utis, data_ptrs);
}
template<typename DataTuple, typename T0, typename T1, typename... Tn>
void fill_vecs(size_t pos,
size_t dt_size,
bool* dt_invalids,
DataTuple const& dt,
cppa::uniform_type_info const* * utis,
void const* * data_ptrs)
{
fill_vecs_util<T0>::_(pos, dt_size, dt_invalids,
dt, utis, data_ptrs);
fill_vecs<DataTuple, T1, Tn...>(pos + 1, dt_size, dt_invalids,
dt, utis, data_ptrs);
}
template<class TypesArray>
class pattern_iterator
{
......
......@@ -99,7 +99,7 @@ class invoke_rule_builder
detail::implicit_conversions>::type
converted_types;
typedef typename pattern_type_from_type_list<converted_types>::type
typedef typename pattern_from_type_list<converted_types>::type
pattern_type;
std::unique_ptr<pattern_type> m_ptr;
......@@ -122,7 +122,7 @@ class invoke_rule_builder
static_assert(raw_types::size > 0, "functor has no arguments");
typedef typename tl_apply<raw_types,rm_ref>::type new_types;
typedef typename concat_type_lists<converted_types,new_types>::type types;
typedef typename pattern_type_from_type_list<types>::type epattern;
typedef typename pattern_from_type_list<types>::type epattern;
typedef typename epattern::tuple_view_type tuple_view_type;
typedef invokable_impl<tuple_view_type, epattern, F> impl;
std::unique_ptr<epattern> pptr(extend_pattern<epattern>(m_ptr.get()));
......@@ -164,7 +164,7 @@ class on_the_fly_invoke_rule_builder
typedef typename ctrait::arg_types raw_types;
static_assert(raw_types::size > 0, "functor has no arguments");
typedef typename tl_apply<raw_types,rm_ref>::type types;
typedef typename pattern_type_from_type_list<types>::type pattern_type;
typedef typename pattern_from_type_list<types>::type pattern_type;
typedef typename pattern_type::tuple_view_type tuple_view_type;
typedef invokable_impl<tuple_view_type, pattern_type, F> impl;
std::unique_ptr<pattern_type> pptr(new pattern_type);
......
......@@ -51,12 +51,11 @@ namespace cppa {
struct dont_initialize_pattern { };
template<typename... Types>
class pattern;
template<typename T0, typename... Tn>
class pattern<T0, Tn...>
class pattern
{
static_assert(sizeof...(Types) > 0, "empty pattern");
pattern(pattern const&) = delete;
pattern& operator=(pattern const&) = delete;
......@@ -64,14 +63,14 @@ class pattern<T0, Tn...>
pattern(dont_initialize_pattern const&) { }
static constexpr size_t size = sizeof...(Tn) + 1;
static constexpr size_t size = sizeof...(Types);
typedef util::type_list<T0, Tn...> tpl_args;
typedef util::type_list<Types...> types;
typedef typename util::lt_filter_not<tpl_args, util::tbind<std::is_same, anything>::type>::type
filtered_tpl_args;
typedef typename util::lt_filter_not<types, util::tbind<std::is_same, anything>::type>::type
filtered_types;
typedef typename tuple_view_type_from_type_list<filtered_tpl_args>::type
typedef typename tuple_view_type_from_type_list<filtered_types>::type
tuple_view_type;
typedef typename tuple_view_type::mapping_vector mapping_vector;
......@@ -109,15 +108,15 @@ class pattern<T0, Tn...>
// private:
detail::tdata<T0, Tn...> m_data;
detail::tdata<Types...> m_data;
//cppa::uniform_type_info const* m_utis[size];
static detail::types_array<T0, Tn...> m_utis;
static detail::types_array<Types...> m_utis;
void const* m_data_ptr[size];
};
template<typename T0, typename... Tn>
detail::types_array<T0, Tn...> pattern<T0, Tn...>::m_utis;
template<typename... Types>
detail::types_array<Types...> pattern<Types...>::m_utis;
template<class ExtendedType, class BasicType>
ExtendedType* extend_pattern(BasicType* p)
......@@ -126,23 +125,21 @@ ExtendedType* extend_pattern(BasicType* p)
et->m_data = p->m_data;
for (size_t i = 0; i < BasicType::size; ++i)
{
//et->m_utis[i] = p->m_utis[i];
et->m_data_ptr[i] = (p->m_data_ptr[i]) ? et->m_data.at(i)
: nullptr;
}
for (size_t i = BasicType::size; i < ExtendedType::size; ++i)
{
et->m_data_ptr[i] = nullptr;
//et->m_utis[i] = et->m_data.type_at(i);
}
return et;
}
template<typename TypeList>
struct pattern_type_from_type_list;
struct pattern_from_type_list;
template<typename... Types>
struct pattern_type_from_type_list<util::type_list<Types...>>
struct pattern_from_type_list<util::type_list<Types...>>
{
typedef pattern<Types...> type;
};
......
......@@ -64,34 +64,38 @@ template<typename... ElementTypes>
class tuple
{
template<size_t N, typename... Types>
friend typename util::at<N, Types...>::type& get_ref(tuple<Types...>&);
public:
typedef util::type_list<ElementTypes...> element_types;
private:
static_assert(sizeof...(ElementTypes) > 0, "tuple is empty");
static_assert(util::tl_forall<element_types, util::is_legal_tuple_type>::value,
static_assert(util::tl_forall<util::type_list<ElementTypes...>,
util::is_legal_tuple_type>::value,
"illegal types in tuple definition: "
"pointers and references are prohibited");
typedef detail::tuple_vals<ElementTypes...> tuple_vals_type;
typedef detail::tuple_vals<ElementTypes...> data_type;
//typedef detail::tuple_vals<ElementTypes...> vals_t;
typedef detail::abstract_tuple vals_t;
cow_ptr<detail::abstract_tuple> m_vals;
cow_ptr<vals_t> m_vals;
struct ptr_ctor { };
template<typename CowPtr>
tuple(ptr_ctor const&, CowPtr&& ptr) : m_vals(std::forward<CowPtr>(ptr))
{
}
public:
/**
* @brief Initializes each element with its default constructor.
*/
tuple() : m_vals(new tuple_vals_type)
tuple() : m_vals(new data_type)
{
}
/**
* @brief Initializes the tuple with @p args.
* @param args Initialization values.
*/
tuple(ElementTypes const&... args) : m_vals(new data_type(args...))
{
}
......@@ -99,8 +103,23 @@ class tuple
* @brief Initializes the tuple with @p args.
* @param args Initialization values.
*/
tuple(ElementTypes const&... args) : m_vals(new tuple_vals_type(args...))
tuple(ElementTypes&&... args) : m_vals(new data_type(std::move(args)...))
{
}
tuple(tuple&&) = default;
tuple(tuple const&) = default;
tuple& operator=(tuple&&) = default;
tuple& operator=(tuple const&) = default;
static tuple from(cow_ptr<detail::abstract_tuple>&& ptr)
{
return tuple(ptr_ctor(), std::move(ptr));
}
static tuple from(cow_ptr<detail::abstract_tuple> const& ptr)
{
return tuple(ptr_ctor(), ptr);
}
/**
......@@ -143,7 +162,7 @@ class tuple
*/
cow_ptr<InternalData> vals() const;
# else
inline cow_ptr<vals_t> const& vals() const
inline cow_ptr<detail::abstract_tuple> const& vals() const
{
return m_vals;
}
......@@ -152,10 +171,10 @@ class tuple
};
template<typename TypeList>
struct tuple_type_from_type_list;
struct tuple_from_type_list;
template<typename... Types>
struct tuple_type_from_type_list<util::type_list<Types...>>
struct tuple_from_type_list< util::type_list<Types...> >
{
typedef tuple<Types...> type;
};
......@@ -202,7 +221,6 @@ const typename util::at<N, Types...>::type& get(tuple<Types...> const& tup)
{
typedef typename util::at<N, Types...>::type result_type;
return *reinterpret_cast<result_type const*>(tup.at(N));
//return get<N>(tup.vals()->data());
}
template<size_t N, typename... Types>
......@@ -210,11 +228,10 @@ typename util::at<N, Types...>::type& get_ref(tuple<Types...>& tup)
{
typedef typename util::at<N, Types...>::type result_type;
return *reinterpret_cast<result_type*>(tup.mutable_at(N));
//return get_ref<N>(tup.m_vals->data_ref());
}
template<typename... Types>
typename tuple_type_from_type_list<
typename tuple_from_type_list<
typename util::tl_apply<util::type_list<Types...>,
detail::implicit_conversions>::type>::type
make_tuple(Types const&... args)
......
......@@ -82,7 +82,7 @@ class tuple_view
}
tuple_view(vals_t const& vals, mapping_vector& mapping)
: m_vals(new detail::decorated_tuple<ElementTypes...>(vals, mapping))
: m_vals(new detail::decorated_tuple<num_elements>(vals, mapping))
{
}
......
#ifndef OPTION_HPP
#define OPTION_HPP
namespace cppa { namespace util {
template<typename What>
class option
{
union
{
What m_value;
};
bool m_valid;
void destroy()
{
if (m_valid) m_value.~What();
}
template<typename V>
void cr(V&& value)
{
m_valid = true;
new (&m_value) What (std::forward<V>(value));
}
public:
option() : m_valid(false) { }
template<typename V>
option(V&& value)
{
cr(std::forward<V>(value));
}
option(option const& other) : m_valid(other.m_valid)
{
if (other.m_valid) cr(other.m_value);
}
option(option&& other) : m_valid(other.m_valid)
{
if (other.m_valid) cr(std::move(other.m_value));
}
~option()
{
destroy();
}
option& operator=(option const& other)
{
if (m_valid)
{
if (other.m_valid)
{
m_value = other.m_value;
}
else
{
destroy();
m_valid = false;
}
}
else
{
if (other.m_valid)
{
cr(other.m_value);
}
}
return *this;
}
option& operator=(option&& other)
{
if (m_valid)
{
if (other.m_valid)
{
m_value = std::move(other.m_value);
}
else
{
destroy();
m_valid = false;
}
}
else
{
if (other.m_valid)
{
cr(std::move(other.m_value));
}
}
return *this;
}
option& operator=(What const& value)
{
if (m_valid) m_value = value;
else cr(value);
return *this;
}
option& operator=(What& value)
{
if (m_valid) m_value = std::move(value);
else cr(std::move(value));
return *this;
}
inline bool valid() const { return m_valid; }
inline What& operator*() { return m_value; }
inline What const& operator*() const { return m_value; }
inline What& get() { return m_value; }
inline What const& get() const { return m_value; }
};
} } // namespace cppa::util
#endif // OPTION_HPP
......@@ -8,12 +8,14 @@
#include "cppa/pattern.hpp"
#include "cppa/announce.hpp"
#include "cppa/util/option.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/conjunction.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/decorated_tuple.hpp"
using namespace cppa;
......@@ -34,26 +36,63 @@ typedef std::pair<int,int> foobar;
static detail::types_array<int,anything,float> arr1;
static detail::types_array<int,anything,foobar> arr2;
//template<template <typename, typename> class Tpl, typename Arg1>
//struct tbind
//{
// template<typename Arg2>
// struct type
// {
// static constexpr bool value = Tpl<Arg1, Arg2>::value;
// };
//};
//template<template<typename> class Predicate, class Value>
//struct foobaz
//{
// static constexpr bool value = Predicate<Value>::value;
//};
template<typename... P>
auto tuple_cast(any_tuple const& tup, pattern<P...> const& p) -> util::option<typename tuple_from_type_list<typename pattern<P...>::filtered_types>::type>
{
typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type;
util::option<tuple_type> result;
typename pattern<P...>::mapping_vector mv;
if (p(tup, &mv))
{
if (mv.size() == tup.size()) // perfect match
{
result = tuple_type::from(tup.vals());
}
else
{
result = tuple_type::from(new detail::decorated_tuple<filtered_types::size>(tup.vals(), mv));
}
}
return std::move(result);
}
struct match_helper
{
any_tuple const& what;
match_helper(any_tuple const& w) : what(w) { }
void operator()(invoke_rules&& rules)
{
rules(what);
}
};
match_helper match(any_tuple const& x)
{
return { x };
}
size_t test__pattern()
{
//cout << "foobaz: " << foobaz<tbind<std::is_same, void>::type, void>::value << endl;
//std::vector<int> ivec = {1, 2, 3};
match(make_tuple(1,2,3))
(
on_arg_match >> [](int a, int b, int c)
{
cout << "MATCH: " << a << ", " << b << ", " << c << endl;
}
);
pattern<int, anything, int> i3;
any_tuple i3_any_tup = make_tuple(1, 2, 3);
auto opt = tuple_cast(i3_any_tup, i3);
if (opt.valid())
{
cout << "x = ( " << get<0>(*opt) << ", " << get<1>(*opt) << " )" << endl;
}
announce<foobar>(&foobar::first, &foobar::second);
......
......@@ -28,6 +28,8 @@ using std::endl;
using namespace cppa;
size_t test__tuple()
{
CPPA_TEST(test__tuple);
......
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