From 8a721494b17786c8ad8ae87e7367548d5bf9daf7 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 19 May 2022 15:05:18 +0200 Subject: [PATCH] Refactor so that make_method_bindable also accepts free functions now This includes pointers to static member functions too of course. `make_method_bindable` got renamed into the more generic `make_function_bindable` because it deals with all functions now, not only member functions. --- examples/calendar/main.cpp | 8 ++--- examples/math_vector/main.cpp | 22 ++++++------ include/wrenpp/vm_fun.hpp | 65 +++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/examples/calendar/main.cpp b/examples/calendar/main.cpp index 3d5d680..b8f6ef1 100644 --- a/examples/calendar/main.cpp +++ b/examples/calendar/main.cpp @@ -121,17 +121,15 @@ int main() { MyConf conf; wren::VM vm(&conf, nullptr); vm.callback_manager() - //.add_callback(true, "calendar", "Calendar", "today()", [](){return &Calendar::today;}) - //.add_callback(false, "calendar", "Calendar", "add_appointment(_)", wren::make_method_bindable<&Calendar::add_appointment>) - .add_callback(false, "calendar", "Calendar", "appointment_count()", wren::make_method_bindable<&Calendar::appointment_count>); - //.add_callback(false, "calendar", "Calendar", "appointment_count()", wren::detail::MakeMethodBindable<&Calendar::appointment_count>()); + .add_callback(true, "calendar", "Calendar", "today()", [](){return &Calendar::today;}) + .add_callback(false, "calendar", "Calendar", "add_appointment(_)", wren::make_function_bindable<&Calendar::add_appointment>) + .add_callback(false, "calendar", "Calendar", "appointment_count()", wren::make_function_bindable<&Calendar::appointment_count>); vm.class_manager().add_class_maker("calendar", "Calendar", wren::make_foreign_class); vm.interpret("main", g_test_script); Calendar* const cale = std::get<0>(wren::variables(vm, MN<"main", "cale">)); cale->print_appointments(); - wren::make_wren_object(vm); return 0; } diff --git a/examples/math_vector/main.cpp b/examples/math_vector/main.cpp index 192208a..742f491 100644 --- a/examples/math_vector/main.cpp +++ b/examples/math_vector/main.cpp @@ -38,7 +38,7 @@ namespace { foreign y=(value) foreign z=(value) - foreign base_x() + foreign static base_x() } )script"}; @@ -56,7 +56,7 @@ vec3.y = vec2.x / vec2.z vec3.z = vec1.x + vec2.y / 4.0 System.print("vec3 modified by scripting: <%(vec3.x), %(vec3.y), %(vec3.z)>") -var vec_base_x = vec2.base_x() +var vec_base_x = MathVector.base_x() System.print("vec_base_x modified by scripting: <%(vec_base_x.x), %(vec_base_x.y), %(vec_base_x.z)>") )script"; @@ -80,7 +80,7 @@ System.print("vec_base_x modified by scripting: <%(vec_base_x.x), %(vec_base_x.y void set_y(T y) { m_y = y; } void set_z(T z) { m_z = z; } - Vector base_x() { return {1.0, 0.0, 0.0}; } + static Vector base_x() { return {1.0, 0.0, 0.0}; } private: T m_x{}, m_y{}, m_z{}; @@ -106,19 +106,19 @@ System.print("vec_base_x modified by scripting: <%(vec_base_x.x), %(vec_base_x.y } //unnamed namespace int main() { - using wren::make_method_bindable; + using wren::make_function_bindable; using wren::make_foreign_class; MyConf conf; wren::VM vm(&conf, nullptr); vm.callback_manager() - .add_callback(false, "math_vector", "MathVector", "x=(_)", make_method_bindable<&Vector::set_x>) - .add_callback(false, "math_vector", "MathVector", "y=(_)", make_method_bindable<&Vector::set_y>) - .add_callback(false, "math_vector", "MathVector", "z=(_)", make_method_bindable<&Vector::set_z>) - .add_callback(false, "math_vector", "MathVector", "x", make_method_bindable<&Vector::x>) - .add_callback(false, "math_vector", "MathVector", "y", make_method_bindable<&Vector::y>) - .add_callback(false, "math_vector", "MathVector", "z", make_method_bindable<&Vector::z>) - .add_callback(false, "math_vector", "MathVector", "base_x()", make_method_bindable<&Vector::base_x>); + .add_callback(false, "math_vector", "MathVector", "x=(_)", make_function_bindable<&Vector::set_x>) + .add_callback(false, "math_vector", "MathVector", "y=(_)", make_function_bindable<&Vector::set_y>) + .add_callback(false, "math_vector", "MathVector", "z=(_)", make_function_bindable<&Vector::set_z>) + .add_callback(false, "math_vector", "MathVector", "x", make_function_bindable<&Vector::x>) + .add_callback(false, "math_vector", "MathVector", "y", make_function_bindable<&Vector::y>) + .add_callback(false, "math_vector", "MathVector", "z", make_function_bindable<&Vector::z>) + .add_callback(true, "math_vector", "MathVector", "base_x()", make_function_bindable<&Vector::base_x>); vm.class_manager() .add_class_maker("math_vector", "MathVector", make_foreign_class, diff --git a/include/wrenpp/vm_fun.hpp b/include/wrenpp/vm_fun.hpp index 49e49ef..98768a6 100644 --- a/include/wrenpp/vm_fun.hpp +++ b/include/wrenpp/vm_fun.hpp @@ -84,25 +84,59 @@ namespace wren { (set_single_for_call(vm, Indices + 1, args), ...); } - template struct MakeMethodBindableConstNonConst { - private: + template + class CallImplemProvider; + template + class CallImplemProvider { + protected: + typedef R return_type; + static constexpr std::size_t argument_count = sizeof...(Args); + template static R call_implem (std::integer_sequence, VM& vm) { static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count"); T* obj = foreign(vm, 0); return (obj->*Method)(get>(vm, Indices + 1)...); } + }; + template + class CallImplemProvider { + protected: + typedef R return_type; + static constexpr std::size_t argument_count = sizeof...(Args); - public: + template + static R call_implem (std::integer_sequence, VM& vm) { + static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count"); + T* obj = foreign(vm, 0); + return (obj->*ConstMethod)(get>(vm, Indices + 1)...); + } + }; + template + class CallImplemProvider { + protected: + typedef R return_type; + static constexpr std::size_t argument_count = sizeof...(Args); + + template + static R call_implem (std::integer_sequence, VM& vm) { + static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count"); + return (*Function)(get>(vm, Indices + 1)...); + } + }; + + template + struct MakeFunctionBindable : private CallImplemProvider { foreign_method_t operator()() const { + using R = typename CallImplemProvider::return_type; + constexpr int argument_count = static_cast(CallImplemProvider::argument_count); + return [](VM& vm, ModuleAndName mn) { if constexpr (std::is_same_v) { - call_implem(std::make_integer_sequence(), vm); + CallImplemProvider::call_implem(std::make_integer_sequence(), vm); } else { - std::cout << "foreign_method make for " << mn.module_name() << - "::" << mn.class_name() << '\n'; - auto ret = call_implem(std::make_integer_sequence(), vm); + auto ret = CallImplemProvider::call_implem(std::make_integer_sequence(), vm); //TODO: check for errors vm.ensure_slots(1); if constexpr (std::is_fundamental::value) { @@ -118,8 +152,7 @@ namespace wren { } }; - template struct MakeMethodBindable; - template struct MakeMethodBindable { + template struct MakeFunctionBindable { foreign_method_t operator()() const { return [](VM& vm, ModuleAndName mn) { T* obj = foreign(vm, 0); @@ -128,8 +161,13 @@ namespace wren { } }; - template struct MakeMethodBindable : MakeMethodBindableConstNonConst {}; - template struct MakeMethodBindable : MakeMethodBindableConstNonConst {}; + template struct MakeFunctionBindable { + foreign_method_t operator()() const { + return [](VM& vm, ModuleAndName mn) { + (*Function)(vm, mn); + }; + } + }; } //namespace detail inline void interpret (VM& vm, const std::string& module_name, const std::string& script) { @@ -198,8 +236,5 @@ namespace wren { #endif template - inline constexpr detail::MakeMethodBindable make_method_bindable; - - //template - //inline detail::MakeFunctionBindable make_function_bindable; + constexpr detail::MakeFunctionBindable make_function_bindable; } //namespace wren