#pragma once #include "vm.hpp" #include "string_bt.hpp" #include #include #include #include namespace wren { typedef std::tuple ModuleAndName; namespace detail { #if __cpp_concepts >= 201907 template concept ConstCharTuple = requires { std::same_as, Handle> or std::same_as, ModuleAndName>; }; #endif } //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); template R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args); template R call (VM& vm, const ModuleAndName& object, const char (&method)[N], const Args&... args); 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); std::string_view slot_string_view (VM& vm, int slot_num); template T get (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 { #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); } template <> inline void set_single_for_call (VM& vm, int slot_num, const Handle& handle) { vm.set_slot_handle(handle, slot_num); } template <> inline void set_single_for_call (VM& vm, int slot_num, const ModuleAndName& name) { variable(vm, name, slot_num); } template inline void set_for_call (std::integer_sequence, VM& vm, const Args&... args) { vm.ensure_slots(sizeof...(Args)); (set_single_for_call(vm, Indices + 1, args), ...); } } //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)); } 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...); vm.call(method); if constexpr (not std::is_same::value) { return get(vm, 0); } } template inline R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args) { vm.ensure_slots(sizeof...(args) + 1); variable(vm, object, 0); Handle obj_handle = vm.slot_handle(0); return call(vm, obj_handle, method, args...); } template inline R call (VM& vm, const ModuleAndName& object, const char (&method)[N], const Args&... args) { const constexpr char dummy_name_buff[N] = {0}; const constexpr auto params = dhandy::bt::string(dummy_name_buff) + dhandy::bt::make_string("(") + ((static_cast(args), dhandy::bt::make_string(",_")) + ...).template substr<1>() + dhandy::bt::make_string(")"); ; char cat_buff[params.size() + 1]; std::copy(method, method + N - 1, cat_buff); std::copy(params.data() + N - 1, params.data() + params.size() + 1, cat_buff + N - 1); return call(vm, object, vm.make_call_handle(cat_buff), args...); } } //namespace wren