diff --git a/include/wrenpp/class_manager.hpp b/include/wrenpp/class_manager.hpp index 457108b..e364b0a 100644 --- a/include/wrenpp/class_manager.hpp +++ b/include/wrenpp/class_manager.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace wren { namespace detail { @@ -73,7 +74,7 @@ namespace wren { } //namespace detail class ClassManager { - typedef foreign_class_t(*make_foreign_class_t)(); + typedef std::function make_foreign_class_t; typedef std::unordered_map ClassMap; public: ClassManager(); diff --git a/include/wrenpp/detail/construct_foreign_class.hpp b/include/wrenpp/detail/construct_foreign_class.hpp new file mode 100644 index 0000000..cffc504 --- /dev/null +++ b/include/wrenpp/detail/construct_foreign_class.hpp @@ -0,0 +1,124 @@ +/* Copyright 2020-2022, Michele Santullo + * This file is part of wrenpp. + * + * Wrenpp is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Wrenpp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with wrenpp. If not, see . + */ + +#pragma once + +#include "wrenpp/vm.hpp" +#include "seters_getters.hpp" +#include +#include +#include + +namespace wren { + namespace detail { + template + inline void construct_single ( + std::integer_sequence, + VM& vm, + void* memory + ) { + new(memory) T{get(vm, Indices + 1)...}; + } + + template + struct ForeignClassHelper; + + template class Pack, typename... PackArgs, typename... Args> + struct ForeignClassHelper, Args...> { + static bool construct (VM& vm, int cardinality, void* memory) { + using std::make_integer_sequence; + + //search by number of parameters. + //once we find a tuple-like parameter that contains the right + //number of types we invoke construct_single() with those types. + constexpr int pack_size = static_cast(sizeof...(PackArgs)); + if (pack_size == cardinality) { + construct_single(make_integer_sequence{}, vm, memory); + return true; + } + else { + return ForeignClassHelper::construct(vm, cardinality, memory); + } + } + }; + + template + struct ForeignClassHelper { + static bool construct (VM& vm, int cardinality, void* memory) { + using std::make_integer_sequence; + + if (1 == cardinality) { + construct_single(make_integer_sequence{}, vm, memory); + return true; + } + else { + return ForeignClassHelper::construct(vm, cardinality, memory); + } + } + }; + + template + struct ForeignClassHelper { + static bool construct (VM& vm, int cardinality, void* memory) { + using std::make_integer_sequence; + + assert(cardinality == 0); + construct_single(make_integer_sequence{}, vm, memory); + return true; + } + }; + + template + inline void find_params_and_construct_foreign_class ( + std::integer_sequence seq, + VM& vm, + void* memory + ) { + if constexpr (sizeof...(Args) == 0) { + construct_single(seq, vm, memory); + } + else { + ForeignClassHelper::construct(vm, vm.slot_count() - 1, memory); + } + } + } //namespace detail + + template + inline foreign_class_t make_overloaded_foreign_class() { + foreign_class_t ret; + ret.allocate = [](VM& vm) { + void* const mem = vm.set_slot_new_foreign(0, 0, sizeof(T)); + + detail::find_params_and_construct_foreign_class( + std::make_integer_sequence{}, + vm, + mem + ); + }; + ret.finalize = [](void* mem) { + const auto cale = static_cast(mem); + cale->~T(); + }; + + return ret; + } + + template + inline foreign_class_t make_foreign_class() { + return make_overloaded_foreign_class>(); + } +} //namespace wren diff --git a/include/wrenpp/detail/seters_getters.hpp b/include/wrenpp/detail/seters_getters.hpp new file mode 100644 index 0000000..bbe17ce --- /dev/null +++ b/include/wrenpp/detail/seters_getters.hpp @@ -0,0 +1,170 @@ +/* Copyright 2020-2022, Michele Santullo + * This file is part of wrenpp. + * + * Wrenpp is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Wrenpp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with wrenpp. If not, see . + */ + +#pragma once + +#include "wrenpp/vm.hpp" +#include +#include +#include + +namespace wren { + namespace detail { + template struct GetTypeToRetType; + template using GetTypeToRetType_t = typename GetTypeToRetType::type; + + template struct TType { typedef T type; }; + + templatestruct GetTypeToRetType{ + static_assert(not std::is_fundamental_v, "User type expected"); + static_assert(not std::is_pointer_v, "Unexpected pointer type"); + typedef std::remove_cv_t* type; + }; + 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{}; + template<>struct GetTypeToRetType : TType{}; + template<>struct GetTypeToRetType> : TType>{}; + +#if __cpp_concepts >= 201907 + template + concept ConstCharTuple = requires { + std::same_as, Handle> or + std::same_as, ModuleAndName>; + }; +#endif + +#if __cpp_concepts >= 201907 + template +#else + template +#endif + inline std::tuple...> variables_impl ( + VM& vm, + std::integer_sequence, + Params&&... modules_names + ) { + if constexpr (sizeof...(Outs) == 0) { + return {}; + } + else { + static_assert(sizeof...(Params) == sizeof...(Outs), "Expected a module/name pair per requested output"); + static_assert(sizeof...(Outs) == sizeof...(Indices), "Mismatching index count"); + + vm.ensure_slots(sizeof...(Params)); + (variable(vm, modules_names, Indices), ...); + return std::tuple...>(get(vm, Indices)...); + } + } + } //namespace detail + + void set (VM& vm, int slot_num, const char* value); + void set (VM& vm, int slot_num, double value); + void set (VM& vm, int slot_num, bool value); + void set (VM& vm, int slot_num, std::nullptr_t); + void set (VM& vm, int slot_num, const char* bytes, std::size_t length); + void set (VM& vm, int slot_num, const std::string& value); + void set (VM& vm, int slot_num, std::string_view value); + 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); + +#if __cpp_concepts >= 201907 + template +#else + template +#endif + std::tuple...> variables(VM& vm, Params&&... modules_names); + + inline void set (VM& vm, int slot_num, const char* value) { + vm.set_slot_string(slot_num, value); + } + + inline void set (VM& vm, int slot_num, double value) { + vm.set_slot_double(slot_num, value); + } + + inline void set (VM& vm, int slot_num, bool value) { + vm.set_slot_bool(slot_num, value); + } + + inline void set (VM& vm, int slot_num, std::nullptr_t) { + vm.set_slot_null(slot_num); + } + + inline void set (VM& vm, int slot_num, const char* bytes, std::size_t length) { + vm.set_slot_bytes(slot_num, bytes, length); + } + + inline void set (VM& vm, int slot_num, const std::string& value) { + vm.set_slot_string(slot_num, value.c_str()); + } + + inline void set (VM& vm, int slot_num, std::string_view value) { + vm.set_slot_bytes(slot_num, value.data(), value.size()); + } + + inline void set (VM& vm, int slot_num, const std::vector& value) { + vm.set_slot_bytes(slot_num, value.data(), value.size()); + } + + inline void set (VM& vm, int slot_num, int value) { + 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)); + return obj; + } + +#if __cpp_concepts >= 201907 + template +#else + template +#endif + inline std::tuple...> variables(VM& vm, Params&&... modules_names) { + return detail::variables_impl(vm, std::make_integer_sequence(), std::forward(modules_names)...); + } + + template + inline detail::GetTypeToRetType_t get (VM& vm, int slot_num) { + return foreign(vm, slot_num); + } + + template<> const char* get (VM& vm, int slot_num); + template <> double get (VM& vm, int slot_num); + 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); +} //namespace wren diff --git a/include/wrenpp/vm_fun.hpp b/include/wrenpp/vm_fun.hpp index 6d6815b..c6371d3 100644 --- a/include/wrenpp/vm_fun.hpp +++ b/include/wrenpp/vm_fun.hpp @@ -23,40 +23,18 @@ # include "guess_class_name.hpp" #endif #include "wren_types.hpp" +#include "detail/construct_foreign_class.hpp" +#include "detail/seters_getters.hpp" #include #include -#include #include #include #include namespace wren { namespace detail { - template struct GetTypeToRetType; - template using GetTypeToRetType_t = typename GetTypeToRetType::type; - -#if __cpp_concepts >= 201907 - template - concept ConstCharTuple = requires { - std::same_as, Handle> or - std::same_as, ModuleAndName>; - }; -#endif - - template - inline void construct_foreign_class ( - std::integer_sequence, - void* memory - ); } //namespace detail -#if __cpp_concepts >= 201907 - template -#else - template -#endif - std::tuple...> variables(VM& vm, Params&&... modules_names); - template R call (VM& vm, const Handle& object, const Handle& method, const Args&... args); @@ -69,9 +47,6 @@ namespace wren { template R call (VM& vm, const ModuleAndName& object, const char (&method)[N], const Args&... args); - template - foreign_class_t make_foreign_class(); - template T* make_foreign_object(VM& vm, const ModuleAndName& mn, Args&&... args); @@ -84,66 +59,12 @@ namespace wren { foreign_method_t make_method_bindable(); void interpret (VM& vm, const std::string& module_name, const std::string& script); - void set (VM& vm, int slot_num, const char* value); - void set (VM& vm, int slot_num, double value); - void set (VM& vm, int slot_num, bool value); - void set (VM& vm, int slot_num, std::nullptr_t); - void set (VM& vm, int slot_num, const char* bytes, std::size_t length); - void set (VM& vm, int slot_num, const std::string& value); - void set (VM& vm, int slot_num, std::string_view value); - 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); void variable(VM& vm, const ModuleAndName& mod_and_name, int slot); void variable(VM& vm, const Handle& handle, int slot); void variable_ensure_slot(VM& vm, const ModuleAndName& mod_and_name, int slot); void variable_ensure_slot(VM& vm, const Handle& handle, int slot); namespace detail { - template struct TType { typedef T type; }; - - templatestruct GetTypeToRetType{ - static_assert(not std::is_fundamental_v, "User type expected"); - static_assert(not std::is_pointer_v, "Unexpected pointer type"); - typedef std::remove_cv_t* type; - }; - 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{}; - template<>struct GetTypeToRetType : TType{}; - template<>struct GetTypeToRetType> : TType>{}; - -#if __cpp_concepts >= 201907 - template -#else - template -#endif - inline std::tuple...> variables_impl ( - VM& vm, - std::integer_sequence, - Params&&... modules_names - ) { - if constexpr (sizeof...(Outs) == 0) { - return {}; - } - else { - static_assert(sizeof...(Params) == sizeof...(Outs), "Expected a module/name pair per requested output"); - static_assert(sizeof...(Outs) == sizeof...(Indices), "Mismatching index count"); - - vm.ensure_slots(sizeof...(Params)); - (variable(vm, modules_names, Indices), ...); - return std::tuple...>(get(vm, Indices)...); - } - } - template inline void set_single_for_call (VM& vm, int slot, const T& value) { set(vm, slot, value); @@ -204,76 +125,12 @@ namespace wren { template struct MakeMethodBindable : MakeMethodBindableConstNonConst {}; template struct MakeMethodBindable : MakeMethodBindableConstNonConst {}; - - template - inline void construct_foreign_class ( - std::integer_sequence, - VM& vm, - void* memory - ) { - new(memory) T{get(vm, Indices + 1)...}; - } } //namespace detail -#if __cpp_concepts >= 201907 - template -#else - template -#endif - inline std::tuple...> variables(VM& vm, Params&&... modules_names) { - return detail::variables_impl(vm, std::make_integer_sequence(), std::forward(modules_names)...); - } - inline void interpret (VM& vm, const std::string& module_name, const std::string& script) { return vm.interpret(module_name.c_str(), script.c_str()); } - inline void set (VM& vm, int slot_num, const char* value) { - vm.set_slot_string(slot_num, value); - } - - inline void set (VM& vm, int slot_num, double value) { - vm.set_slot_double(slot_num, value); - } - - inline void set (VM& vm, int slot_num, bool value) { - vm.set_slot_bool(slot_num, value); - } - - inline void set (VM& vm, int slot_num, std::nullptr_t) { - vm.set_slot_null(slot_num); - } - - inline void set (VM& vm, int slot_num, const char* bytes, std::size_t length) { - vm.set_slot_bytes(slot_num, bytes, length); - } - - inline void set (VM& vm, int slot_num, const std::string& value) { - vm.set_slot_string(slot_num, value.c_str()); - } - - inline void set (VM& vm, int slot_num, std::string_view value) { - vm.set_slot_bytes(slot_num, value.data(), value.size()); - } - - inline void set (VM& vm, int slot_num, const std::vector& value) { - vm.set_slot_bytes(slot_num, value.data(), value.size()); - } - - inline void set (VM& vm, int slot_num, int value) { - 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)); - return obj; - } - template inline R call (VM& vm, const Handle& object, const Handle& method, const Args&... args) { detail::set_for_call(std::make_integer_sequence(), vm, args...); @@ -314,21 +171,6 @@ namespace wren { return call(vm, obj_handle, method, args...); } - template - inline foreign_class_t make_foreign_class() { - foreign_class_t ret; - ret.allocate = [](VM& vm) { - void* const mem = vm.set_slot_new_foreign(0, 0, sizeof(T)); - detail::construct_foreign_class(std::make_integer_sequence{}, vm, mem); - }; - ret.finalize = [](void* mem) { - const auto cale = static_cast(mem); - cale->~T(); - }; - - return ret; - } - template inline T* make_foreign_object(VM& vm, const ModuleAndName& mn, Args&&... args) { variable(vm, mn, 0); @@ -352,19 +194,4 @@ namespace wren { inline foreign_method_t make_method_bindable() { return detail::MakeMethodBindable::make(); } - - template - inline detail::GetTypeToRetType_t get (VM& vm, int slot_num) { - return foreign(vm, slot_num); - } - - template<> const char* get (VM& vm, int slot_num); - template <> double get (VM& vm, int slot_num); - 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); } //namespace wren diff --git a/src/class_manager.cpp b/src/class_manager.cpp index 859f6ef..2bf6fe0 100644 --- a/src/class_manager.cpp +++ b/src/class_manager.cpp @@ -92,7 +92,7 @@ namespace wren { auto it_found = m_classes.find(TempClassName{module_name, class_name}); if (m_classes.cend() != it_found) - return (*it_found->second)(); + return it_found->second(); else return {nullptr, nullptr}; }