diff --git a/src/wren/vm.cpp b/src/wren/vm.cpp index 4ddc27a..595e360 100644 --- a/src/wren/vm.cpp +++ b/src/wren/vm.cpp @@ -68,6 +68,17 @@ namespace wren { retval.finalize = funcs.finalize; return retval; } + + template T slot_specialized (WrenVM* vm, int slot_num); + template <> bool slot_specialized (WrenVM* vm, int slot_num) { + return wrenGetSlotBool(vm, slot_num); + } + template <> std::string slot_specialized (WrenVM* vm, int slot_num) { + return wrenGetSlotString(vm, slot_num); + } + template <> double slot_specialized (WrenVM* vm, int slot_num) { + return wrenGetSlotDouble(vm, slot_num); + } } //unnamed namespace struct VM::LocalData { @@ -152,4 +163,27 @@ namespace wren { void VM::interpret (const std::string& module_name, const std::string& script) { return interpret(module_name.c_str(), script.c_str()); } + + template + T VM::slot (int slot_num) { + return slot_specialized(m_local->wvm, slot_num); + } + + template <> + int VM::slot (int slot_num) { + return static_cast(slot(slot_num)); + } + + void VM::ensure_slots (int num_slots) { + wrenEnsureSlots(m_local->wvm, num_slots); + } + + void VM::variable(const char* module, const char* name, int slot) { + wrenGetVariable(m_local->wvm, module, name, slot); + } + + template bool VM::slot(int); + template std::string VM::slot(int); + template double VM::slot(int); + template int VM::slot(int); } //namespace wren diff --git a/src/wren/vm.hpp b/src/wren/vm.hpp index b208aca..b0dee6e 100644 --- a/src/wren/vm.hpp +++ b/src/wren/vm.hpp @@ -4,6 +4,11 @@ #include "error_type.hpp" #include #include +#include +#include +#if __cpp_concepts >= 201907 +# include +#endif namespace wren { class Configuration; @@ -12,6 +17,7 @@ namespace wren { typedef void(*foreign_method_t)(VM*); typedef void(*finalizer_t)(void*); + typedef std::tuple ModuleAndName; struct foreign_class_t { foreign_method_t allocate; @@ -32,6 +38,10 @@ namespace wren { VM* owner {nullptr}; DynafuncMaker* dynafunc {nullptr}; }; + +#if __cpp_concepts >= 201907 + template concept ConstCharTuple = std::same_as, ModuleAndName>; +#endif } //namespace detail class VM { @@ -45,6 +55,18 @@ namespace wren { void interpret (const char* module_name, const char* script); void interpret (const std::string& module_name, const std::string& script); + template T slot (int slot_num); +#if __cpp_concepts >= 201907 + template +#else + template +#endif + std::tuple variables(Params&&... modules_names); + //template std::tuple variables(const Handle& handle); + + void ensure_slots(int num_slots); + void variable(const char* module, const char* name, int slot); + private: struct LocalData; @@ -54,6 +76,13 @@ namespace wren { template detail::Callbacks to_callbacks (T& conf); +#if __cpp_concepts >= 201907 + template +#else + template +#endif + std::tuple get_variables_impl (std::integer_sequence, Params&&... modules_names); + std::unique_ptr m_local; }; @@ -122,4 +151,44 @@ namespace wren { VM(static_cast(conf), to_callbacks(*conf)) { } + +#if __cpp_concepts >= 201907 + template +#else + template +#endif + std::tuple VM::variables(Params&&... modules_names) { + return get_variables_impl(std::make_integer_sequence(), std::forward(modules_names)...); + } + +#if __cpp_concepts >= 201907 + template +#else + template +#endif + inline std::tuple VM::get_variables_impl ( + std::integer_sequence, + Params&&... modules_names + ) { + if constexpr (sizeof...(Outs) == 0) { + return {}; + } + else { + using std::get; + using std::tuple; + + static_assert(sizeof...(Params) == sizeof...(Outs), "Expected a module/name pair per requested output"); + static_assert(sizeof...(Outs) == sizeof...(Indices), "Mismatching index count"); + + ensure_slots(sizeof...(Outs)); + (this->variable(get<0>(modules_names), get<1>(modules_names), Indices), ...); + return tuple(this->slot(Indices)...); + } + } + + //template + //inline std::tuple VM::variables(const Handle& handle) { + // if constexpr (sizeof...(Args) == 0) + // return {}; + //} } //namespace wren