From 6a30725a62aed18d0dd4c0dec4b2df83b95dc01a Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 3 May 2020 12:23:06 +0200 Subject: [PATCH] Add arbitrary method to foreign_method_t conversion helper It might not work in every case, you still are restricted to types that set() and get() understand. --- examples/calendar/main.cpp | 12 ++++++++++-- include/wrenpp/vm_fun.hpp | 35 +++++++++++++++++++++++++++++++++++ src/vm_fun.cpp | 4 ++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/examples/calendar/main.cpp b/examples/calendar/main.cpp index 7bc650a..f20fa87 100644 --- a/examples/calendar/main.cpp +++ b/examples/calendar/main.cpp @@ -31,6 +31,7 @@ namespace { construct new() {} foreign static today() foreign add_appointment(desc) + foreign appointment_count() } )script"; @@ -39,6 +40,7 @@ R"script(import "calendar" for Calendar var cale = Calendar.new() System.print("Today is %(Calendar.today())") cale.add_appointment("go get a haircut") +System.print("You have %(cale.appointment_count()) appointment(s)") )script"; auto today_unique_str() { @@ -69,8 +71,8 @@ cale.add_appointment("go get a haircut") vm.set_slot_string(0, today_unique_str().get()); } - void add_appointment (wren::VM& vm) { - m_appointments.push_back(wren::get(vm, 1)); + void add_appointment (std::string&& appointment) { + m_appointments.push_back(std::move(appointment)); } void print_appointments() const { @@ -85,6 +87,10 @@ cale.add_appointment("go get a haircut") } } + std::size_t appointment_count() const { + return m_appointments.size(); + } + private: std::vector m_appointments; }; @@ -111,6 +117,8 @@ cale.add_appointment("go get a haircut") return &Calendar::today; else if (not is_static and signature == "add_appointment(_)") return wren::make_method_bindable<&Calendar::add_appointment>(); + else if (not is_static and signature == "appointment_count()") + return wren::make_method_bindable<&Calendar::appointment_count>(); } return nullptr; } diff --git a/include/wrenpp/vm_fun.hpp b/include/wrenpp/vm_fun.hpp index 7d4d5c4..a2b3ee2 100644 --- a/include/wrenpp/vm_fun.hpp +++ b/include/wrenpp/vm_fun.hpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace wren { typedef std::tuple ModuleAndName; @@ -76,6 +77,7 @@ namespace wren { void set (VM& vm, int slot_num, const std::vector& value); void set (VM& vm, int slot_num, const char* beg, const char* end); void set (VM& vm, int slot_num, int value); + void set (VM& vm, int slot_num, std::size_t value); std::string_view slot_string_view (VM& vm, int slot_num); template detail::GetTypeToRetType_t get (VM& vm, int slot_num); template T* foreign (VM& vm, int slot_num); @@ -95,6 +97,7 @@ namespace wren { template<>struct GetTypeToRetType : TType{}; template<>struct GetTypeToRetType> : TType> {}; template<>struct GetTypeToRetType : TType{}; + template<>struct GetTypeToRetType : TType{}; template<>struct GetTypeToRetType : TType{}; template<>struct GetTypeToRetType : TType{}; template<>struct GetTypeToRetType> : TType>{}; @@ -143,6 +146,30 @@ namespace wren { (set_single_for_call(vm, Indices + 1, args), ...); } + template struct MakeMethodBindableConstNonConst { + private: + 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)...); + } + + public: + static foreign_method_t make() { + return [](VM& vm) { + if constexpr (std::is_same_v) { + call_implem(std::make_integer_sequence(), vm); + } + else { + auto ret = call_implem(std::make_integer_sequence(), vm); + vm.ensure_slots(1); + set(vm, 0, ret); + } + }; + } + }; + template struct MakeMethodBindable; template struct MakeMethodBindable { static foreign_method_t make() { @@ -152,6 +179,9 @@ namespace wren { }; } }; + + template struct MakeMethodBindable : MakeMethodBindableConstNonConst {}; + template struct MakeMethodBindable : MakeMethodBindableConstNonConst {}; } //namespace detail #if __cpp_concepts >= 201907 @@ -203,6 +233,10 @@ namespace wren { vm.set_slot_double(slot_num, static_cast(value)); } + inline void set (VM& vm, int slot_num, std::size_t value) { + vm.set_slot_double(slot_num, static_cast(value)); + } + template inline T* foreign (VM& vm, int slot_num) { T* obj = static_cast(vm.slot_foreign(slot_num)); @@ -278,6 +312,7 @@ namespace wren { template <> bool get (VM& vm, int slot_num); template <> std::pair get> (VM& vm, int slot_num); template<> int get (VM& vm, int slot_num); + template<> std::size_t get (VM& vm, int slot_num); template<> std::string get (VM& vm, int slot_num); template <> std::string_view get (VM& vm, int slot_num); template <> std::vector get> (VM& vm, int slot_num); diff --git a/src/vm_fun.cpp b/src/vm_fun.cpp index d1fc137..bd2855b 100644 --- a/src/vm_fun.cpp +++ b/src/vm_fun.cpp @@ -54,6 +54,10 @@ namespace wren { return static_cast(vm.slot_double(slot_num)); } + template<> std::size_t get (VM& vm, int slot_num) { + return static_cast(vm.slot_double(slot_num)); + } + template<> std::string get (VM& vm, int slot_num) { return {vm.slot_string(slot_num)}; }