diff --git a/examples/calendar/main.cpp b/examples/calendar/main.cpp index 331682f..7bc650a 100644 --- a/examples/calendar/main.cpp +++ b/examples/calendar/main.cpp @@ -130,13 +130,13 @@ cale.add_appointment("go get a haircut") } //unnamed namespace int main() { + typedef wren::ModuleAndName MN; + MyConf conf; wren::VM vm(&conf, nullptr); vm.interpret("main", g_test_script); - vm.ensure_slots(1); - wren::variable(vm, {"main", "cale"}, 0); - const auto cale = wren::foreign(vm, 0); + Calendar* const cale = std::get<0>(wren::variables(vm, MN{"main", "cale"})); cale->print_appointments(); return 0; diff --git a/include/wrenpp/vm_fun.hpp b/include/wrenpp/vm_fun.hpp index 7df58d0..7d4d5c4 100644 --- a/include/wrenpp/vm_fun.hpp +++ b/include/wrenpp/vm_fun.hpp @@ -28,6 +28,9 @@ namespace wren { typedef std::tuple ModuleAndName; namespace detail { + template struct GetTypeToRetType; + template using GetTypeToRetType_t = typename GetTypeToRetType::type; + #if __cpp_concepts >= 201907 template concept ConstCharTuple = requires { @@ -42,7 +45,7 @@ namespace wren { #else template #endif - std::tuple variables(VM& vm, Params&&... modules_names); + std::tuple...> variables(VM& vm, Params&&... modules_names); template R call (VM& vm, const Handle& object, const Handle& method, const Args&... args); @@ -74,18 +77,34 @@ namespace wren { void set (VM& vm, int slot_num, const char* beg, const char* end); void set (VM& vm, int slot_num, int value); std::string_view slot_string_view (VM& vm, int slot_num); - template T get (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); 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>{}; + #if __cpp_concepts >= 201907 template #else template #endif - inline std::tuple variables_impl ( + inline std::tuple...> variables_impl ( VM& vm, std::integer_sequence, Params&&... modules_names @@ -99,7 +118,7 @@ namespace wren { vm.ensure_slots(sizeof...(Params)); (variable(vm, modules_names, Indices), ...); - return std::tuple(get(vm, Indices)...); + return std::tuple...>(get(vm, Indices)...); } } @@ -140,7 +159,7 @@ namespace wren { #else template #endif - inline std::tuple variables(VM& vm, Params&&... modules_names) { + inline std::tuple...> variables(VM& vm, Params&&... modules_names) { return detail::variables_impl(vm, std::make_integer_sequence(), std::forward(modules_names)...); } @@ -248,4 +267,18 @@ 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::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/vm_fun.cpp b/src/vm_fun.cpp index f5f77cd..d1fc137 100644 --- a/src/vm_fun.cpp +++ b/src/vm_fun.cpp @@ -34,36 +34,36 @@ namespace wren { return {ptr.first, static_cast(ptr.second)}; } - template<> const char* get (VM& vm, int slot_num) { + template<> const char* get (VM& vm, int slot_num) { return vm.slot_string(slot_num); } - template <> double get (VM& vm, int slot_num) { + template <> double get (VM& vm, int slot_num) { return vm.slot_double(slot_num); } - template <> bool get (VM& vm, int slot_num) { + template <> bool get (VM& vm, int slot_num) { return vm.slot_bool(slot_num); } - template <> std::pair get (VM& vm, int slot_num) { + template <> std::pair get> (VM& vm, int slot_num) { return vm.slot_bytes(slot_num); } - template<> int get (VM& vm, int slot_num) { + template<> int get (VM& vm, int slot_num) { return static_cast(vm.slot_double(slot_num)); } - template<> std::string get (VM& vm, int slot_num) { + template<> std::string get (VM& vm, int slot_num) { return {vm.slot_string(slot_num)}; } - template <> std::string_view get (VM& vm, int slot_num) { + template <> std::string_view get (VM& vm, int slot_num) { auto arr = get>(vm, slot_num); return std::string_view{arr.first, static_cast(arr.second)}; } - template <> std::vector get (VM& vm, int slot_num) { + template <> std::vector get> (VM& vm, int slot_num) { auto arr = get>(vm, slot_num); return std::vector{arr.first, arr.first + arr.second}; }