diff --git a/dispatchkit/bootstrap.hpp b/dispatchkit/bootstrap.hpp index 27e6c55..2ab934c 100644 --- a/dispatchkit/bootstrap.hpp +++ b/dispatchkit/bootstrap.hpp @@ -449,6 +449,18 @@ namespace dispatchkit std::vector(params.begin() + 1, params.end())))); } + static Boxed_Value call_exists(const std::vector ¶ms) + { + if (params.size() < 1) + { + throw arity_error(params.size(), 1); + } + + boost::shared_ptr f = boxed_cast >(params[0]); + + return Boxed_Value(f->types_match(std::vector(params.begin() + 1, params.end()))); + } + static void bootstrap(Dispatch_Engine &s) { s.register_type("void"); @@ -488,6 +500,9 @@ namespace dispatchkit s.register_function(boost::shared_ptr(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))), "bind"); + s.register_function(boost::shared_ptr(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))), + "call_exists"); + register_function(s, &type_match, "type_match"); register_function(s, &bool_and, "&&"); register_function(s, &bool_or, "||"); diff --git a/dispatchkit/dispatchkit.hpp b/dispatchkit/dispatchkit.hpp index 735e23e..c428f6f 100644 --- a/dispatchkit/dispatchkit.hpp +++ b/dispatchkit/dispatchkit.hpp @@ -26,7 +26,7 @@ namespace dispatchkit { } - bool operator==(const Proxy_Function &f) const + virtual bool operator==(const Proxy_Function &f) const { return false; } @@ -38,11 +38,31 @@ namespace dispatchkit return dispatch(m_funcs, params); } - virtual std::vector get_param_types() + virtual std::vector get_param_types() const { return std::vector(); } + virtual bool types_match(const std::vector &types) const + { + typedef std::vector > > function_vec; + + function_vec::const_iterator begin = m_funcs.begin(); + function_vec::const_iterator end = m_funcs.end(); + + while (begin != end) + { + if (begin->second->types_match(types)) + { + return true; + } else { + ++begin; + } + } + + return false; + } + private: std::vector > > m_funcs; }; diff --git a/dispatchkit/proxy_functions.hpp b/dispatchkit/proxy_functions.hpp index 4e75185..d5bdfb8 100644 --- a/dispatchkit/proxy_functions.hpp +++ b/dispatchkit/proxy_functions.hpp @@ -2,6 +2,8 @@ #define gettypeinfo(z,n,text) ti.push_back(Get_Type_Info::get()); #define casthelper(z,n,text) ,dispatchkit::boxed_cast< Param ## n >(params[n]) +#define comparetype(z,n,text) && ((Get_Type_Info::get() == params[n].get_type_info())) +#define trycast(z,n,text) dispatchkit::boxed_cast(params[n]); #ifndef BOOST_PP_IS_ITERATING @@ -119,8 +121,9 @@ namespace dispatchkit public: virtual ~Proxy_Function() {} virtual Boxed_Value operator()(const std::vector ¶ms) = 0; - virtual std::vector get_param_types() = 0; + virtual std::vector get_param_types() const = 0; virtual bool operator==(const Proxy_Function &) const = 0; + virtual bool types_match(const std::vector &types) const = 0; }; class Dynamic_Proxy_Function : public Proxy_Function @@ -131,11 +134,16 @@ namespace dispatchkit { } - bool operator==(const Proxy_Function &f) const + virtual bool operator==(const Proxy_Function &f) const { return false; } + virtual bool types_match(const std::vector &types) const + { + return (m_arity < 0 || types.size() == size_t(m_arity)); + } + virtual ~Dynamic_Proxy_Function() {} virtual Boxed_Value operator()(const std::vector ¶ms) @@ -148,7 +156,7 @@ namespace dispatchkit } } - virtual std::vector get_param_types() + virtual std::vector get_param_types() const { return build_param_type_list(m_f); } @@ -167,14 +175,25 @@ namespace dispatchkit { } - bool operator==(const Proxy_Function &f) const + virtual bool operator==(const Proxy_Function &f) const { return false; } virtual ~Bound_Function() {} + virtual bool types_match(const std::vector &types) const + { + std::vector params = build_param_list(types); + return m_f->types_match(params); + } + virtual Boxed_Value operator()(const std::vector ¶ms) + { + return (*m_f)(build_param_list(params)); + } + + std::vector build_param_list(const std::vector ¶ms) const { typedef std::vector::const_iterator pitr; @@ -208,10 +227,10 @@ namespace dispatchkit } } - return (*m_f)(args); + return args; } - virtual std::vector get_param_types() + virtual std::vector get_param_types() const { return std::vector(); } @@ -247,11 +266,16 @@ namespace dispatchkit return call_func(m_f, params); } - virtual std::vector get_param_types() + virtual std::vector get_param_types() const { return build_param_type_list(m_f); } + virtual bool types_match(const std::vector &types) const + { + return compare_types(m_f, types); + } + private: Func m_f; }; @@ -315,6 +339,28 @@ namespace dispatchkit return Handle_Return()(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~))); } } + + template + bool compare_types(const boost::function &, + const std::vector ¶ms) + { + if (params.size() != n) + { + return false; + } else { + bool val = true BOOST_PP_REPEAT(n, comparetype, ~); + if (val) return true; + + try { + BOOST_PP_REPEAT(n, trycast, ~); + } catch (const bad_boxed_cast &) { + return false; + } + + return true; + } + } + } #endif