Add support for object parameters to Wren calls
This commit is contained in:
parent
b00bd59027
commit
05298b6111
9 changed files with 282 additions and 37 deletions
63
include/wrenpp/detail/foreign_object.hpp
Normal file
63
include/wrenpp/detail/foreign_object.hpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* Copyright 2020-2024, 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wrenpp/handle.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace wren {
|
||||
|
||||
template <typename T>
|
||||
class ForeignObject {
|
||||
public:
|
||||
ForeignObject() = default;
|
||||
ForeignObject (std::nullptr_t) : ForeignObject() {}
|
||||
ForeignObject (T* obj, Handle&& handle);
|
||||
~ForeignObject() noexcept = default;
|
||||
|
||||
void set_to_slot (int num);
|
||||
T& object() { return *m_object; }
|
||||
const T& object() const { return *m_object; }
|
||||
Handle& handle() { return m_handle; }
|
||||
const Handle& handle() const { return m_handle; }
|
||||
bool is_valid() const { return nullptr != m_object; }
|
||||
|
||||
operator T&() { return object(); }
|
||||
operator const T&() const { return object(); }
|
||||
operator Handle&() { return handle(); }
|
||||
operator const Handle&() const { return handle(); }
|
||||
bool operator!= (std::nullptr_t) const { return nullptr != m_object; }
|
||||
bool operator== (std::nullptr_t) const { return nullptr == m_object; }
|
||||
|
||||
private:
|
||||
Handle m_handle;
|
||||
T* m_object{nullptr};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline ForeignObject<T>::ForeignObject (T* obj, Handle&& handle) :
|
||||
m_handle(std::move(handle)),
|
||||
m_object(obj)
|
||||
{ }
|
||||
|
||||
template <typename T>
|
||||
inline void ForeignObject<T>::set_to_slot (int num) {
|
||||
m_handle.set_to_slot(num);
|
||||
}
|
||||
|
||||
} //namespace wren
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -18,6 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../vm.hpp"
|
||||
#include "../handle.hpp"
|
||||
#include "module_and_name.hpp"
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
@ -87,6 +88,8 @@ namespace wren {
|
|||
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);
|
||||
void set (VM& vm, int slot_num, const Handle& handle);
|
||||
void set (VM& vm, int slot_num, const ModuleAndName& name);
|
||||
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);
|
||||
|
@ -138,6 +141,14 @@ namespace wren {
|
|||
vm.set_slot_double(slot_num, static_cast<double>(value));
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const Handle& handle) {
|
||||
vm.set_slot_handle(handle, slot_num);
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const ModuleAndName& name) {
|
||||
vm.variable_or_throw(name.module_name_char(), name.class_name_char(), slot_num);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* foreign (VM& vm, int slot_num) {
|
||||
T* obj = static_cast<T*>(vm.slot_foreign(slot_num));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -42,6 +42,8 @@ namespace wren {
|
|||
operator WrenHandle*() const { return m_handle; }
|
||||
operator bool() const { return nullptr != m_handle; }
|
||||
|
||||
void set_to_slot (int num);
|
||||
|
||||
private:
|
||||
WrenHandle* m_handle;
|
||||
VM* m_vm;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include "detail/construct_foreign_class.hpp"
|
||||
#include "detail/setters_getters.hpp"
|
||||
#include "detail/wren_class_name_from_type.hpp"
|
||||
#include "detail/foreign_object.hpp"
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
@ -46,11 +47,11 @@ namespace wren {
|
|||
R call (VM& vm, ModuleAndName object, const char (&method)[N], const Args&... args);
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T* make_wren_object(VM& vm, ModuleAndName mn, Args&&... args);
|
||||
ForeignObject<T> make_wren_object(VM& vm, ModuleAndName mn, Args&&... args);
|
||||
|
||||
#if defined(WRENPP_WITH_NAME_GUESSING)
|
||||
template <typename T, dhandy::bt::string Mod, typename... Args>
|
||||
T* make_wren_object(VM& vm, Args&&... args);
|
||||
ForeignObject<T> make_wren_object(VM& vm, Args&&... args);
|
||||
#endif
|
||||
|
||||
void interpret (VM& vm, const std::string& module_name, const std::string& script);
|
||||
|
@ -61,28 +62,13 @@ namespace wren {
|
|||
void abort_fiber_with_error (VM& vm, int slot, std::string_view message);
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
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);
|
||||
}
|
||||
|
||||
//Sets arguments so wren is ready to perform a function call. It doesn't
|
||||
//touch at slot 0, so eventual objects for method calls must be set
|
||||
//manually
|
||||
template <typename... Args, int... Indices>
|
||||
inline void set_for_call (std::integer_sequence<int, Indices...>, VM& vm, const Args&... args) {
|
||||
vm.ensure_slots(sizeof...(Args));
|
||||
(set_single_for_call(vm, Indices + 1, args), ...);
|
||||
(set(vm, Indices + 1, args), ...);
|
||||
}
|
||||
|
||||
template <auto V>
|
||||
|
@ -145,7 +131,7 @@ namespace wren {
|
|||
}
|
||||
else {
|
||||
ModuleAndName wren_name = wren_class_name_from_type<R>(vm);
|
||||
R* const new_object = make_wren_object<R>(vm, wren_name, std::move(ret));
|
||||
ForeignObject<R> new_object = make_wren_object<R>(vm, wren_name, std::move(ret));
|
||||
static_cast<void>(new_object);
|
||||
}
|
||||
}
|
||||
|
@ -197,15 +183,13 @@ namespace wren {
|
|||
inline R call (VM& vm, const Handle& object, const char (&method)[N], const Args&... args) {
|
||||
using dhandy::bt::string;
|
||||
|
||||
const constexpr char dummy_name_buff[N] = {0};
|
||||
const constexpr auto params = string<N, char>(dummy_name_buff) +
|
||||
string("(") +
|
||||
const constexpr auto params = string("(") +
|
||||
((static_cast<void>(args), string(",_")) + ... + string("")).template substr<1>() +
|
||||
string(")");
|
||||
;
|
||||
char cat_buff[params.size() + 1];
|
||||
char cat_buff[params.size() + 1 + N - 1];
|
||||
std::copy(method, method + N - 1, cat_buff);
|
||||
std::copy(params.data() + N - 1, params.data() + params.size() + 1, cat_buff + N - 1);
|
||||
std::copy(params.data(), params.data() + params.size() + 1, cat_buff + N - 1);
|
||||
return call<R, Args...>(vm, object, vm.make_call_handle(cat_buff), args...);
|
||||
}
|
||||
|
||||
|
@ -218,12 +202,12 @@ namespace wren {
|
|||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline T* make_wren_object(VM& vm, ModuleAndName mn, Args&&... args) {
|
||||
variable(vm, mn, 0);
|
||||
inline ForeignObject<T> make_wren_object(VM& vm, ModuleAndName mn, Args&&... args) {
|
||||
variable_ensure_slot(vm, mn, 0);
|
||||
void* const mem = vm.set_slot_new_foreign(0, 0, sizeof(T));
|
||||
try {
|
||||
T* const obj = new(mem) T{std::forward<Args>(args)...};
|
||||
return obj;
|
||||
return {obj, vm.slot_handle(0)};
|
||||
}
|
||||
catch (const std::runtime_error& err) {
|
||||
abort_fiber_with_error(vm, 1, err.what());
|
||||
|
@ -233,7 +217,7 @@ namespace wren {
|
|||
|
||||
#if defined(WRENPP_WITH_NAME_GUESSING)
|
||||
template <typename T, dhandy::bt::string Mod, typename... Args>
|
||||
inline T* make_wren_object(VM& vm, Args&&... args) {
|
||||
inline ForeignObject<T> make_wren_object(VM& vm, Args&&... args) {
|
||||
return make_wren_object<T>(
|
||||
vm,
|
||||
MN<Mod, g_guessed_class_name<T>>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue