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.
This commit is contained in:
King_DuckZ 2020-05-03 12:23:06 +02:00
commit 6a30725a62
3 changed files with 49 additions and 2 deletions

View file

@ -23,6 +23,7 @@
#include <string_view>
#include <vector>
#include <type_traits>
#include <cstddef>
namespace wren {
typedef std::tuple<const char*, const char*> ModuleAndName;
@ -76,6 +77,7 @@ namespace wren {
void set (VM& vm, int slot_num, const std::vector<char>& 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 <typename T> detail::GetTypeToRetType_t<T> get (VM& vm, int slot_num);
template <typename T> T* foreign (VM& vm, int slot_num);
@ -95,6 +97,7 @@ namespace wren {
template<>struct GetTypeToRetType<bool> : TType<bool>{};
template<>struct GetTypeToRetType<std::pair<const char*,int>> : TType<std::pair<const char*,int>> {};
template<>struct GetTypeToRetType<int> : TType<int>{};
template<>struct GetTypeToRetType<std::size_t> : TType<std::size_t>{};
template<>struct GetTypeToRetType<std::string> : TType<std::string>{};
template<>struct GetTypeToRetType<std::string_view> : TType<std::string_view>{};
template<>struct GetTypeToRetType<std::vector<char>> : TType<std::vector<char>>{};
@ -143,6 +146,30 @@ namespace wren {
(set_single_for_call(vm, Indices + 1, args), ...);
}
template <typename T, typename R, auto Method, typename... Args> struct MakeMethodBindableConstNonConst {
private:
template <int... Indices>
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
T* obj = foreign<T>(vm, 0);
return (obj->*Method)(get<std::decay_t<Args>>(vm, Indices + 1)...);
}
public:
static foreign_method_t make() {
return [](VM& vm) {
if constexpr (std::is_same_v<R, void>) {
call_implem(std::make_integer_sequence<int, sizeof...(Args)>(), vm);
}
else {
auto ret = call_implem(std::make_integer_sequence<int, sizeof...(Args)>(), vm);
vm.ensure_slots(1);
set(vm, 0, ret);
}
};
}
};
template <auto V> struct MakeMethodBindable;
template <typename T, void(T::*Method)(VM&)> struct MakeMethodBindable<Method> {
static foreign_method_t make() {
@ -152,6 +179,9 @@ namespace wren {
};
}
};
template <typename T, typename R, typename... Args, R(T::*Method)(Args...)> struct MakeMethodBindable<Method> : MakeMethodBindableConstNonConst<T, R, Method, Args...> {};
template <typename T, typename R, typename... Args, R(T::*Method)(Args...)const> struct MakeMethodBindable<Method> : MakeMethodBindableConstNonConst<T, R, Method, Args...> {};
} //namespace detail
#if __cpp_concepts >= 201907
@ -203,6 +233,10 @@ namespace wren {
vm.set_slot_double(slot_num, static_cast<double>(value));
}
inline void set (VM& vm, int slot_num, std::size_t value) {
vm.set_slot_double(slot_num, static_cast<double>(value));
}
template <typename T>
inline T* foreign (VM& vm, int slot_num) {
T* obj = static_cast<T*>(vm.slot_foreign(slot_num));
@ -278,6 +312,7 @@ namespace wren {
template <> bool get<bool> (VM& vm, int slot_num);
template <> std::pair<const char*, int> get<std::pair<const char*,int>> (VM& vm, int slot_num);
template<> int get<int> (VM& vm, int slot_num);
template<> std::size_t get<std::size_t> (VM& vm, int slot_num);
template<> std::string get<std::string> (VM& vm, int slot_num);
template <> std::string_view get<std::string_view> (VM& vm, int slot_num);
template <> std::vector<char> get<std::vector<char>> (VM& vm, int slot_num);