diff --git a/typelesscpp/scripting_constructors.hpp b/typelesscpp/scripting_constructors.hpp new file mode 100644 index 00000000..b850bf7e --- /dev/null +++ b/typelesscpp/scripting_constructors.hpp @@ -0,0 +1,50 @@ +#ifndef __scripting_constructors_hpp__ +#define __scripting_constrcutors_hpp__ + +#include +#include +#include + +//Constructors, to be made variadic +template +boost::shared_ptr constructor() +{ + return boost::shared_ptr(new Class()); +} + +template +boost::shared_ptr constructor(Param1 p1) +{ + return boost::shared_ptr(new Class(p1)); +} + +template +boost::shared_ptr constructor(Param1 p1, Param2 p2) +{ + return boost::shared_ptr(new Class(p1, p2)); +} + +template +boost::function ()> build_constructor() +{ + typedef boost::shared_ptr (*func)(); + return boost::function ()>(func(&(constructor))); +} + +template +boost::function (Param1)> build_constructor() +{ + typedef boost::shared_ptr (*func)(Param1); + return boost::function (Param1)>(func(&(constructor))); +} + +template +boost::function (Param1, Param2)> build_constructor() +{ + typedef boost::shared_ptr (*func)(Param1, Param2); + return boost::function (Param1, Param2)>(func(&(constructor))); +} + + +#endif + diff --git a/typelesscpp/scripting_functions.hpp b/typelesscpp/scripting_functions.hpp new file mode 100644 index 00000000..1c9e3785 --- /dev/null +++ b/typelesscpp/scripting_functions.hpp @@ -0,0 +1,131 @@ +#ifndef __scripting_function_hpp__ +#define __scripting_function_hpp__ + + +#include "scripting_object.hpp" + +#include +#include +#include +#include +#include + + +// handle_return implementations +template +struct Handle_Return +{ + Scripting_Object operator()(const boost::function &f) + { + return Scripting_Object(f()); + } +}; + +template +struct Handle_Return +{ + Scripting_Object operator()(const boost::function &f) + { + return Scripting_Object(boost::ref(f())); + } +}; + +template<> +struct Handle_Return +{ + Scripting_Object operator()(const boost::function &f) + { + f(); + return Scripting_Object(); + } +}; + + + +// call_func implementations todo: handle reference return types +// to be made variadic +template +Scripting_Object call_func(const boost::function &f, const std::vector ¶ms) +{ + if (params.size() != 2) + { + throw std::range_error("Incorrect number of parameters"); + } else { + return Handle_Return()(boost::bind(f, Cast_Helper()(params[0]), Cast_Helper()(params[1]))); + } +} + +template +Scripting_Object call_func(const boost::function &f, const std::vector ¶ms) +{ + if (params.size() != 1) + { + throw std::range_error("Incorrect number of parameters"); + } else { + return Handle_Return()(boost::bind(f, Cast_Helper()(params[0]))); + } +} + +template +Scripting_Object call_func(const boost::function &f, const std::vector ¶ms) +{ + if (params.size() != 0) + { + throw std::range_error("Incorrect number of parameters"); + } else { + return Handle_Return()(f); + } +} + + + +class Function_Handler +{ + public: + virtual Scripting_Object operator()(const std::vector ¶ms) = 0; +}; + +template +class Function_Handler_Impl : public Function_Handler +{ + public: + Function_Handler_Impl(const Func &f) + : m_f(f) + { + } + + virtual Scripting_Object operator()(const std::vector ¶ms) + { + return call_func(m_f, params); + } + + private: + Func m_f; +}; + +std::vector build_param_list(const Scripting_Object &so) +{ + std::vector sos; + sos.push_back(so); + return sos; +} +std::vector build_param_list(const Scripting_Object &so1, const Scripting_Object &so2) +{ + std::vector sos; + sos.push_back(so1); + sos.push_back(so2); + return sos; +} +std::vector build_param_list(const Scripting_Object &so1, const Scripting_Object &so2, const Scripting_Object &so3) +{ + std::vector sos; + sos.push_back(so1); + sos.push_back(so2); + sos.push_back(so3); + return sos; +} + + + +#endif + diff --git a/typelesscpp/scripting_object.hpp b/typelesscpp/scripting_object.hpp new file mode 100644 index 00000000..a8526772 --- /dev/null +++ b/typelesscpp/scripting_object.hpp @@ -0,0 +1,121 @@ +#ifndef __scripting_object_hpp__ +#define __scripting_object_hpp__ + +#include "scripting_type_info.hpp" +#include +#include + +#include + +class Scripting_Object +{ + public: + template + explicit Scripting_Object(boost::shared_ptr obj) + : m_type_info(Get_Type_Info()()), m_obj(obj), m_is_ref(false) + { + } + + template + explicit Scripting_Object(boost::reference_wrapper obj) + : m_type_info(Get_Type_Info()()), m_obj(obj), m_is_ref(true) + { + } + + template + explicit Scripting_Object(const T& t) + : m_type_info(Get_Type_Info()()), m_obj(boost::shared_ptr(new T(t))), m_is_ref(false) + { + } + + Scripting_Object(const Scripting_Object &t_so) + : m_type_info(t_so.m_type_info), m_obj(t_so.m_obj), m_is_ref(t_so.m_is_ref) + { + } + + Scripting_Object() + : m_type_info(Get_Type_Info()()), m_is_ref(false) + { + } + + const Type_Info &get_type_info() + { + return m_type_info; + } + + boost::any get() const + { + return m_obj; + } + + bool is_ref() const + { + return m_is_ref; + } + + private: + Type_Info m_type_info; + boost::any m_obj; + bool m_is_ref; +}; + + +//cast_help specializations +template +struct Cast_Helper +{ + typename boost::reference_wrapper::type > operator()(Scripting_Object ob) + { + if (ob.is_ref()) + { + return boost::cref((boost::any_cast >(ob.get())).get()); + } else { + return boost::cref(*(boost::any_cast >(ob.get()))); + } + } +}; + +template +struct Cast_Helper +{ + typename boost::reference_wrapper::type > operator()(Scripting_Object ob) + { + if (ob.is_ref()) + { + return boost::cref((boost::any_cast >(ob.get())).get()); + } else { + return boost::cref(*(boost::any_cast >(ob.get()))); + } + } +}; + +template +struct Cast_Helper +{ + Result *operator()(Scripting_Object ob) + { + if (ob.is_ref()) + { + return (boost::any_cast >(ob.get())).get_pointer(); + } else { + return (boost::any_cast >(ob.get())).get(); + } + } +}; + +template +struct Cast_Helper +{ + typename boost::reference_wrapper operator()(Scripting_Object ob) + { + if (ob.is_ref()) + { + return boost::any_cast >(ob.get()); + } else { + return boost::ref(*(boost::any_cast >(ob.get()))); + } + } +}; + +#endif + diff --git a/typelesscpp/scripting_system.hpp b/typelesscpp/scripting_system.hpp new file mode 100644 index 00000000..05301054 --- /dev/null +++ b/typelesscpp/scripting_system.hpp @@ -0,0 +1,64 @@ +#ifndef __scripting_system_hpp__ +#define __scripting_system_hpp__ + +#include +#include +#include +#include +#include +#include + +#include "scripting_object.hpp" +#include "scripting_functions.hpp" +#include "scripting_constructors.hpp" + +class Scripting_System +{ + public: + template + void register_function(const Function &func, const std::string &name) + { + m_functions.insert(std::make_pair(name, boost::shared_ptr(new Function_Handler_Impl(func)))); + } + + template + void add_object(const std::string &name, const Class &obj) + { + m_objects.insert(std::make_pair(name, Scripting_Object(obj))); + } + + Scripting_Object get_object(const std::string &name) const + { + std::map::const_iterator itr = m_objects.find(name); + if (itr != m_objects.end()) + { + return itr->second; + } else { + throw std::range_error("Object not known: " + name); + } + } + + template + void register_type(const std::string &name) + { + m_types.insert(std::make_pair(name, &typeid(Type))); + } + + boost::shared_ptr get_function(const std::string &t_name) + { + std::map >::const_iterator itr = m_functions.find(t_name); + if (itr != m_functions.end()) + { + return itr->second; + } else { + throw std::range_error("Function not known: " + t_name); + } + } + + private: + std::map m_objects; + std::map m_types; + std::map > m_functions; +}; + +#endif diff --git a/typelesscpp/scripting_type_info.hpp b/typelesscpp/scripting_type_info.hpp new file mode 100644 index 00000000..a8e65ce0 --- /dev/null +++ b/typelesscpp/scripting_type_info.hpp @@ -0,0 +1,36 @@ +#ifndef __scripting_type_info_hpp__ +#define __scripting_type_info_hpp__ + +#include + +struct Type_Info +{ + Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + const std::type_info *t_ti, const std::type_info *t_bareti) + : m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), + m_type_info(t_ti), m_bare_type_info(t_bareti) + { + } + + bool m_is_const; + bool m_is_reference; + bool m_is_pointer; + bool m_is_void; + const std::type_info *m_type_info; + const std::type_info *m_bare_type_info; +}; + +template +struct Get_Type_Info +{ + Type_Info operator()() + { + return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, + boost::is_void::value, + &typeid(T), + &typeid(typename boost::remove_const::type>::type>::type)); + + } +}; + +#endif diff --git a/typelesscpp/test.cpp b/typelesscpp/test.cpp new file mode 100644 index 00000000..fbcd0417 --- /dev/null +++ b/typelesscpp/test.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +#include "scripting_system.hpp" + +struct Test +{ + Test() + : md(0) + { + } + + Test(const std::string &s) + : message(s), md(0) + { + std::cout << "Test class constructed with value: " << s << std::endl; + } + + void show_message() + { + std::cout << "Constructed Message: " << message << std::endl; + } + + std::string &get_message() + { + return message; + } + + int method(double d) + { + md += d; + std::cout << "Method called " << md << std::endl; + return int(md); + } + + std::string message; + double md; +}; + +std::string testprint(const std::string &p) +{ + std::cout << p << std::endl; + return p; +} + +void print() +{ + std::cout << "Test void function succeeded" << std::endl; +} + + +//Test main +int main() +{ + Scripting_System ss; + ss.register_type("Test"); + ss.register_function(boost::function(&Test::method), "method"); + ss.register_function(boost::function(&testprint), "print"); + ss.register_function(boost::function(&print), "voidfunc"); + ss.register_function(build_constructor(), "Test"); + ss.register_function(boost::function(&Test::show_message), "show_message"); + ss.register_function(boost::function(&Test::get_message), "get_message"); + + + ss.add_object("testobj", boost::shared_ptr(new Test())); + ss.add_object("d", boost::shared_ptr(new double(10.2))); + ss.add_object("str", std::string("Hello World")); + + std::vector sos; + sos.push_back(ss.get_object("testobj")); + sos.push_back(ss.get_object("d")); + + boost::shared_ptr method1(ss.get_function("method")); + (*method1)(sos); + (*method1)(sos); + Scripting_Object o = (*method1)(sos); + + (*ss.get_function("print"))(build_param_list(ss.get_object("str"))); + + //Add new dynamically created object from registered "Test" constructor + ss.add_object("testobj2", (*ss.get_function("Test"))(build_param_list(Scripting_Object(std::string("Yo"))))); + + std::cout << Cast_Helper()(o) << std::endl; + + (*ss.get_function("voidfunc"))(std::vector()); + + std::vector sos3; + sos3.push_back(ss.get_object("testobj2")); + (*ss.get_function("show_message"))(sos3); + + Scripting_Object stringref = (*ss.get_function("get_message"))(sos3); + + std::string &sr = Cast_Helper()(stringref); + sr = "Bob Updated The message"; + + (*ss.get_function("show_message"))(sos3); +} +