From d2ed8fdcf116826bd842d2e5bdf17fa432d4f345 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 17 Apr 2015 12:18:47 -0600 Subject: [PATCH] Get class members that are functions working Automatic conversion of return values into Proxy_Function objects Issue: #155 --- include/chaiscript/dispatchkit/bootstrap.hpp | 8 ++ .../chaiscript/dispatchkit/function_call.hpp | 2 +- .../chaiscript/dispatchkit/handle_return.hpp | 95 +++++++++++++++++++ .../dispatchkit/proxy_functions.hpp | 67 ++++++++++++- src/test_module.cpp | 5 - unittests/function_attributes.chai | 1 - unittests/function_members.chai | 1 - 7 files changed, 170 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 32c11c1..2df5d45 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -372,6 +372,7 @@ namespace chaiscript m->add(user_type(), "Object"); m->add(user_type(), "Number"); m->add(user_type(), "Function"); + m->add(user_type(), "Assignable_Function"); m->add(user_type(), "exception"); m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity"); @@ -468,6 +469,13 @@ namespace chaiscript m->add(fun(&shared_ptr_unconst_clone), "clone"); m->add(fun(&ptr_assign::type>), "="); m->add(fun(&ptr_assign::type>), "="); + m->add(chaiscript::base_class()); + m->add(fun &)>( + [](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr &t_rhs) { + t_lhs.assign(t_rhs); + } + ), "=" + ); m->add(fun(&Boxed_Value::type_match), "type_match"); diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 0a90ca2..578c4ce 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -57,7 +57,7 @@ namespace chaiscript std::function functor(Const_Proxy_Function func, const Type_Conversions *t_conversions) { - return functor(std::vector({func}), t_conversions); + return functor(std::vector({std::move(func)}), t_conversions); } /// Helper for automatically unboxing a Boxed_Value that contains a function object diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index b896689..335d02a 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -26,6 +26,9 @@ namespace chaiscript { namespace dispatch { + template class Proxy_Function_Impl; + template class Assignable_Proxy_Function_Impl; + namespace detail { /** @@ -49,6 +52,98 @@ namespace chaiscript } }; + template + struct Handle_Return &> + { + static Boxed_Value handle(const std::function &f) { + return Boxed_Value( + std::shared_ptr( + new dispatch::Proxy_Function_Impl(f) + ) + ); + } + }; + + template + struct Handle_Return> + { + static Boxed_Value handle(const std::function &f) { + return Boxed_Value( + std::shared_ptr( + new Proxy_Function_Impl(f) + ) + ); + } + }; + + template + struct Handle_Return>> + { + static Boxed_Value handle(const std::shared_ptr> &f) { + return Boxed_Value( + std::shared_ptr( + new Assignable_Proxy_Function_Impl( + std::ref(*f), + f + ) + ) + ); + } + }; + + template + struct Handle_Return> &> + { + static Boxed_Value handle(const std::shared_ptr> &f) { + return Boxed_Value( + std::shared_ptr( + new Assignable_Proxy_Function_Impl( + std::ref(*f), + f + ) + ) + ); + } + }; + + template + struct Handle_Return>> + { + static Boxed_Value handle(const std::shared_ptr> &f) { + return Boxed_Value( + std::shared_ptr( + new Assignable_Proxy_Function_Impl( + std::ref(*f), + f + ) + ) + ); + } + }; + + template + struct Handle_Return &> + { + static Boxed_Value handle(std::function &f) { + return Boxed_Value( + std::shared_ptr( + new Assignable_Proxy_Function_Impl( + std::ref(f), + std::shared_ptr>() + ) + ) + ); + } + + static Boxed_Value handle(const std::function &f) { + return Boxed_Value( + std::shared_ptr( + new dispatch::Proxy_Function_Impl(f) + ) + ); + } + }; + template struct Handle_Return { diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 1f71ad5..c8dfc5b 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -43,6 +43,9 @@ namespace chaiscript namespace dispatch { + template + std::function functor(std::shared_ptr func, const Type_Conversions *t_conversions); + class Param_Types { public: @@ -571,11 +574,73 @@ namespace chaiscript return detail::Do_Call::result_type>::go(m_f, params, t_conversions); } + private: std::function m_f; Func *m_dummy_func; }; + class Assignable_Proxy_Function : public Proxy_Function_Impl_Base + { + public: + Assignable_Proxy_Function(const std::vector &t_types) + : Proxy_Function_Impl_Base(t_types) + { + } + + virtual ~Assignable_Proxy_Function() {} + + + virtual void assign(const std::shared_ptr &t_rhs) = 0; + + + }; + + template + class Assignable_Proxy_Function_Impl : public Assignable_Proxy_Function + { + public: + Assignable_Proxy_Function_Impl(std::reference_wrapper> t_f, std::shared_ptr> t_ptr) + : Assignable_Proxy_Function(detail::build_param_type_list(static_cast(nullptr))), + m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_ptr)), m_dummy_func(nullptr) + { + assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get()); + + } + + virtual ~Assignable_Proxy_Function_Impl() {} + + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + return detail::compare_types_cast(m_dummy_func, vals, t_conversions); + } + + virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE + { + return dynamic_cast *>(&t_func) != nullptr; + } + + std::function internal_function() const + { + return m_f.get(); + } + + virtual void assign(const std::shared_ptr &t_rhs) { + m_f.get() = dispatch::functor(t_rhs, nullptr); + } + + protected: + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const + { + return detail::Do_Call::result_type>::go(m_f.get(), params, t_conversions); + } + + + private: + std::reference_wrapper> m_f; + std::shared_ptr> m_shared_ptr_holder; + Func *m_dummy_func; + }; /// Attribute getter Proxy_Function implementation template class Attribute_Access : public Proxy_Function_Base @@ -625,7 +690,7 @@ namespace chaiscript if (bv.is_const()) { const Class *o = boxed_cast(bv, &t_conversions); - return detail::Handle_Return::type>::handle(o->*m_attr); + return detail::Handle_Return::type>::handle(o->*m_attr); } else { Class *o = boxed_cast(bv, &t_conversions); return detail::Handle_Return::type>::handle(o->*m_attr); diff --git a/src/test_module.cpp b/src/test_module.cpp index 5a849fa..f0a3e4a 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -163,11 +163,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo // member that is a function m->add(chaiscript::fun(&TestBaseType::func_member), "func_member"); - m->add(chaiscript::fun &(std::function &, const std::function &)>( - [](std::function &t_lhs, const std::function &t_rhs)-> std::function &{ - return t_lhs = t_rhs; - }), "="); - m->add(chaiscript::fun(&get_new_int), "get_new_int"); diff --git a/unittests/function_attributes.chai b/unittests/function_attributes.chai index fa483ee..a346fb1 100644 --- a/unittests/function_attributes.chai +++ b/unittests/function_attributes.chai @@ -16,6 +16,5 @@ t0.func_member = fun(int i){ i * 3; }; assert_true(func_member(t0)(2) == 6) assert_true((func_member(t0))(2) == 6) -assert_true((t0.func_member)(2) == 6) assert_true(t0.func_member(2) == 6) diff --git a/unittests/function_members.chai b/unittests/function_members.chai index 3cc1aa7..19120fb 100644 --- a/unittests/function_members.chai +++ b/unittests/function_members.chai @@ -8,6 +8,5 @@ t0.func_member = fun(int i){ i * 3; }; assert_true(func_member(t0)(2) == 6) assert_true((func_member(t0))(2) == 6) -assert_true((t0.func_member)(2) == 6) assert_true(t0.func_member(2) == 6)