#ifndef __dispatchkit_hpp__ #define __dispatchkit_hpp__ #include #include #include #include #include #include #include #include #include #include "boxed_value.hpp" #include "type_info.hpp" #include "proxy_functions.hpp" #include "proxy_constructors.hpp" namespace dispatchkit { class Dispatch_Function : public Proxy_Function { public: Dispatch_Function(const std::vector > > &t_funcs) : m_funcs(t_funcs) { } virtual bool operator==(const Proxy_Function &f) const { return false; } virtual ~Dispatch_Function() {} virtual Boxed_Value operator()(const std::vector ¶ms) { return dispatch(m_funcs, params); } 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; }; class Dispatch_Engine { public: typedef std::multimap > Function_Map; typedef std::map Type_Name_Map; typedef std::map Scope; typedef std::deque Stack; Dispatch_Engine() { m_scopes.push_back(Scope()); } bool register_function(const boost::shared_ptr &f, const std::string &name) { return add_function(f, name); } template bool register_function(const Function &func, const std::string &name) { return add_function(boost::shared_ptr(new Proxy_Function_Impl(func)), name); } template void set_object(const std::string &name, const Class &obj) { for (int i = m_scopes.size()-1; i >= 0; --i) { std::map::const_iterator itr = m_scopes[i].find(name); if (itr != m_scopes[i].end()) { m_scopes[i][name] = Boxed_Value(obj); return; } } add_object(name, obj); } template void add_object(const std::string &name, const Class &obj) { m_scopes.back()[name] = Boxed_Value(obj); } void new_scope() { m_scopes.push_back(Scope()); } void pop_scope() { if (m_scopes.size() > 1) { m_scopes.pop_back(); } else { throw std::range_error("Unable to pop global stack"); } } Stack get_stack() { return m_scopes; } Stack set_stack(Stack s) { swap(s, m_scopes); return s; } Boxed_Value get_object(const std::string &name) const { for (int i = m_scopes.size()-1; i >= 0; --i) { std::map::const_iterator itr = m_scopes[i].find(name); if (itr != m_scopes[i].end()) { return itr->second; } } std::vector > funcs = get_function_impl(name, false); if (funcs.empty()) { throw std::range_error("Object not known: " + name); } else { return Boxed_Value(boost::shared_ptr(new Dispatch_Function(funcs))); } } template void register_type(const std::string &name) { m_types.insert(std::make_pair(name, Get_Type_Info::get())); } std::vector get_types() const { return std::vector(m_types.begin(), m_types.end()); } std::vector > get_function_impl(const std::string &t_name, bool include_objects) const { std::vector > funcs; if (include_objects) { try { funcs.insert(funcs.end(), Function_Map::value_type( t_name, boxed_cast(get_object(t_name))) ); } catch (const bad_boxed_cast &) { } catch (const std::range_error &) { } } std::pair range = m_functions.equal_range(t_name); funcs.insert(funcs.end(), range.first, range.second); return funcs; } std::vector > get_function(const std::string &t_name) const { return get_function_impl(t_name, true); } std::vector get_functions() const { return std::vector(m_functions.begin(), m_functions.end()); } private: bool add_function(const boost::shared_ptr &f, const std::string &t_name) { std::pair range = m_functions.equal_range(t_name); while (range.first != range.second) { if ((*f) == *(range.first->second)) { return false; } ++range.first; } m_functions.insert(std::make_pair(t_name, f)); return true; } std::deque m_scopes; Function_Map m_functions; Type_Name_Map m_types; }; void dump_object(Boxed_Value o) { std::cout << o.get_type_info().m_type_info->name() << std::endl; } void dump_type(const Type_Info &type) { std::cout << type.m_bare_type_info->name(); } void dump_function(const Dispatch_Engine::Function_Map::value_type &f) { std::vector params = f.second->get_param_types(); dump_type(params.front()); std::cout << " " << f.first << "("; for (std::vector::const_iterator itr = params.begin() + 1; itr != params.end(); ++itr) { dump_type(*itr); std::cout << ", "; } std::cout << ")" << std::endl; } void dump_system(const Dispatch_Engine &s) { std::cout << "Registered Types: " << std::endl; std::vector types = s.get_types(); for (std::vector::const_iterator itr = types.begin(); itr != types.end(); ++itr) { std::cout << itr->first << ": "; dump_type(itr->second); std::cout << std::endl; } std::cout << std::endl; std::vector funcs = s.get_functions(); std::cout << "Functions: " << std::endl; for (std::vector::const_iterator itr = funcs.begin(); itr != funcs.end(); ++itr) { dump_function(*itr); } std::cout << std::endl; } } #endif