mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
cull a good chunk of SFINAE, see what results...
This commit is contained in:
parent
ad494bd063
commit
e1f3e5f009
@ -1,4 +1,4 @@
|
|||||||
// sol3
|
// sol3
|
||||||
|
|
||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
|
|
||||||
@ -35,51 +35,101 @@
|
|||||||
namespace sol {
|
namespace sol {
|
||||||
namespace function_detail {
|
namespace function_detail {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct class_indicator {};
|
struct class_indicator {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
struct call_indicator {};
|
struct call_indicator {};
|
||||||
} // namespace function_detail
|
|
||||||
|
|
||||||
namespace stack {
|
template <bool yielding>
|
||||||
template <typename... Sigs>
|
inline int lua_c_wrapper(lua_State* L) {
|
||||||
struct unqualified_pusher<function_sig<Sigs...>> {
|
lua_CFunction cf = lua_tocfunction(L, lua_upvalueindex(2));
|
||||||
template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
|
int nr = cf(L);
|
||||||
static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
|
if constexpr (yielding) {
|
||||||
typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t;
|
return lua_yield(L, nr);
|
||||||
typedef R (*fx_ptr_t)(A...);
|
}
|
||||||
constexpr bool is_convertible = std::is_convertible_v<raw_fx_t, fx_ptr_t>;
|
else {
|
||||||
if constexpr (is_convertible) {
|
return nr;
|
||||||
using fx_ptr_t = R (*)(A...);
|
}
|
||||||
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
}
|
||||||
select_function<is_yielding>(std::true_type(), L, fxptr, std::forward<Args>(args)...);
|
|
||||||
|
template <bool yielding>
|
||||||
|
inline int lua_c_noexcept_wrapper(lua_State* L) noexcept {
|
||||||
|
detail::lua_CFunction_noexcept cf = reinterpret_cast<detail::lua_CFunction_noexcept>(lua_tocfunction(L, lua_upvalueindex(2)));
|
||||||
|
int nr = cf(L);
|
||||||
|
if constexpr (yielding) {
|
||||||
|
return lua_yield(L, nr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct c_function_invocation {};
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select(lua_State* L, Fx&& fx, Args&&... args);
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select_set_fx(lua_State* L, Args&&... args) {
|
||||||
|
lua_CFunction freefunc = detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
|
||||||
|
|
||||||
|
int upvalues = 0;
|
||||||
|
upvalues += stack::push(L, nullptr);
|
||||||
|
upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
||||||
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
|
||||||
|
inline void select_convertible(types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
using dFx = std::decay_t<meta::unwrap_unqualified_t<Fx>>;
|
||||||
|
using fx_ptr_t = R (*)(A...);
|
||||||
|
constexpr bool is_convertible = std::is_convertible_v<dFx, fx_ptr_t>;
|
||||||
|
if constexpr (is_convertible) {
|
||||||
|
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
||||||
|
select<is_yielding>(L, std::move(fxptr), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
using F = function_detail::functor_function<dFx, is_yielding, true>;
|
||||||
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
|
||||||
|
select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select_member_variable(lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
using uFx = meta::unqualified_t<Fx>;
|
||||||
|
if constexpr (sizeof...(Args) < 1) {
|
||||||
|
using C = typename meta::bind_traits<uFx>::object_type;
|
||||||
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call;
|
||||||
|
|
||||||
|
int upvalues = 0;
|
||||||
|
upvalues += stack::push(L, nullptr);
|
||||||
|
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||||
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
|
}
|
||||||
|
else if constexpr (sizeof...(Args) < 2) {
|
||||||
|
using Tu = typename meta::unqualified<Args...>::type;
|
||||||
|
constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
|
||||||
|
if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
|
||||||
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<typename Tu::type, Fx, is_yielding>::call;
|
||||||
|
|
||||||
|
int upvalues = 0;
|
||||||
|
upvalues += stack::push(L, nullptr);
|
||||||
|
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||||
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
else {
|
else if constexpr (is_reference) {
|
||||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
|
||||||
typedef function_detail::functor_function<clean_fx, is_yielding, true> F;
|
|
||||||
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
|
||||||
static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
|
|
||||||
select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
|
||||||
static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_convertible<is_yielding>(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler>
|
|
||||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
|
||||||
constexpr bool is_reference = meta::is_specialization_of_v<meta::unqualified_t<T>, std::reference_wrapper> || std::is_pointer_v<T>;
|
|
||||||
if constexpr(is_reference) {
|
|
||||||
typedef std::decay_t<Fx> dFx;
|
typedef std::decay_t<Fx> dFx;
|
||||||
dFx memfxptr(std::forward<Fx>(fx));
|
dFx memfxptr(std::forward<Fx>(fx));
|
||||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
auto userptr = detail::ptr(std::forward<Args>(args)...);
|
||||||
lua_CFunction freefunc
|
lua_CFunction freefunc
|
||||||
= &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
|
= &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
|
||||||
|
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
@ -89,94 +139,93 @@ namespace sol {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
|
using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
|
||||||
using F = function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding>;
|
using F = function_detail::member_variable<Tu, clean_fx, is_yielding>;
|
||||||
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <bool is_yielding, typename Fx, typename C>
|
using C = typename meta::bind_traits<uFx>::object_type;
|
||||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call;
|
using F = function_detail::member_variable<C, clean_fx, is_yielding>;
|
||||||
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
int upvalues = 0;
|
|
||||||
upvalues += stack::push(L, nullptr);
|
|
||||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx>
|
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
||||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
inline void select_member_function_with(lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
using dFx = std::decay_t<Fx>;
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call;
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
|
||||||
int upvalues = 0;
|
using C = typename Tu::type;
|
||||||
upvalues += stack::push(L, nullptr);
|
|
||||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
|
||||||
static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
|
||||||
typedef std::decay_t<Fx> clean_fx;
|
|
||||||
typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding> F;
|
|
||||||
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
|
||||||
static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
|
||||||
using dFx = std::decay_t<Fx>;
|
|
||||||
dFx memfxptr(std::forward<Fx>(fx));
|
|
||||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
|
|
||||||
|
|
||||||
int upvalues = 0;
|
|
||||||
upvalues += stack::push(L, nullptr);
|
|
||||||
upvalues += stack::push<user<dFx>>(L, memfxptr);
|
|
||||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
|
||||||
static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_member_variable<is_yielding>(meta::is_member_object<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler>
|
|
||||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
|
||||||
typedef meta::boolean<meta::is_specialization_of<meta::unqualified_t<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
|
|
||||||
select_reference_member_function<is_yielding>(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename C>
|
|
||||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
|
||||||
using dFx = std::decay_t<Fx>;
|
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
||||||
|
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
upvalues += stack::push<user<dFx>>(L, fx);
|
upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
|
||||||
|
if constexpr (is_reference) {
|
||||||
|
auto userptr = detail::ptr(std::forward<T>(obj));
|
||||||
|
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, dFx, is_yielding>::call;
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx>
|
int upvalues = 0;
|
||||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
upvalues += stack::push(L, nullptr);
|
||||||
using dFx = std::decay_t<Fx>;
|
upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||||
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
using F = function_detail::member_function<Tu, dFx, is_yielding>;
|
||||||
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select_member_function(lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
using dFx = std::decay_t<Fx>;
|
||||||
|
if constexpr (sizeof...(Args) < 1) {
|
||||||
|
using C = typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type;
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
||||||
|
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
upvalues += stack::push<user<dFx>>(L, fx);
|
upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx));
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
select_member_function_with<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_member_function<is_yielding>(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
|
inline void select(lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
using uFx = meta::unqualified_t<Fx>;
|
||||||
|
if constexpr (is_lua_reference_v<uFx>) {
|
||||||
|
// TODO: hoist into lambda in this case for yielding???
|
||||||
|
stack::push(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else if constexpr (is_lua_c_function_v<uFx>) {
|
||||||
|
int upvalues = 0;
|
||||||
|
upvalues += stack::push(L, nullptr);
|
||||||
|
upvalues += stack::push(L, std::forward<Fx>(fx));
|
||||||
|
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
||||||
|
if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
|
||||||
|
detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>;
|
||||||
|
lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_CFunction cf = &lua_c_wrapper<is_yielding>;
|
||||||
|
lua_pushcclosure(L, cf, 2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>;
|
||||||
|
lua_pushcclosure(L, cf, 2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_function_v<std::remove_pointer_t<uFx>>) {
|
||||||
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx, is_yielding>::call;
|
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx, is_yielding>::call;
|
||||||
|
|
||||||
@ -185,74 +234,45 @@ namespace sol {
|
|||||||
upvalues += stack::stack_detail::push_as_upvalues(L, target);
|
upvalues += stack::stack_detail::push_as_upvalues(L, target);
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_member_function_pointer_v<uFx>) {
|
||||||
template <bool is_yielding>
|
select_member_function<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
|
|
||||||
// TODO: support yielding
|
|
||||||
stack::push(L, f);
|
|
||||||
}
|
}
|
||||||
|
else if constexpr (meta::is_member_object_v<uFx>) {
|
||||||
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
select_member_variable<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
template <bool is_yielding>
|
|
||||||
static void select_function(std::true_type, lua_State* L, detail::lua_CFunction_noexcept f) {
|
|
||||||
// TODO: support yielding
|
|
||||||
stack::push(L, f);
|
|
||||||
}
|
}
|
||||||
#endif // noexcept function type
|
else {
|
||||||
|
select_convertible<is_yielding>(types<>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
template <bool is_yielding, typename Fx, typename... Args, meta::disable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler>
|
|
||||||
static void select(lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_function<is_yielding>(std::is_function<std::remove_pointer_t<meta::unqualified_t<Fx>>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, meta::enable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler>
|
|
||||||
static void select(lua_State* L, Fx&& fx) {
|
|
||||||
// TODO: hoist into lambda in this case??
|
|
||||||
stack::push(L, std::forward<Fx>(fx));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
|
||||||
static void set_fx(lua_State* L, Args&&... args) {
|
|
||||||
lua_CFunction freefunc = detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
|
|
||||||
|
|
||||||
int upvalues = 0;
|
|
||||||
upvalues += stack::push(L, nullptr);
|
|
||||||
upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} // namespace function_detail
|
||||||
|
|
||||||
|
namespace stack {
|
||||||
|
template <typename... Sigs>
|
||||||
|
struct unqualified_pusher<function_sig<Sigs...>> {
|
||||||
template <typename Arg0, typename... Args>
|
template <typename Arg0, typename... Args>
|
||||||
static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
|
static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
|
||||||
if constexpr(std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) {
|
if constexpr (std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) {
|
||||||
select<true>(L, std::forward<Args>(args)...);
|
function_detail::select<true>(L, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
select<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
|
function_detail::select<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
static int push(lua_State* L, detail::yield_tag_t, Args&&... args) {
|
|
||||||
// Set will always place one thing (function) on the stack
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<yielding_t<T>> {
|
struct unqualified_pusher<yielding_t<T>> {
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) {
|
static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) {
|
||||||
unqualified_pusher<function_sig<>> p{};
|
function_detail::select<true>(L, f.func, std::forward<Args>(args)...);
|
||||||
(void)p;
|
return 1;
|
||||||
return p.push(L, detail::yield_tag, f.func, std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) {
|
static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) {
|
||||||
unqualified_pusher<function_sig<>> p{};
|
function_detail::select<true>(L, std::move(f.func), std::forward<Args>(args)...);
|
||||||
(void)p;
|
return 1;
|
||||||
return p.push(L, detail::yield_tag, std::move(f.func), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -275,50 +295,53 @@ namespace sol {
|
|||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
struct unqualified_pusher<std::function<Signature>> {
|
struct unqualified_pusher<std::function<Signature>> {
|
||||||
static int push(lua_State* L, const std::function<Signature>& fx) {
|
static int push(lua_State* L, const std::function<Signature>& fx) {
|
||||||
return unqualified_pusher<function_sig<Signature>>{}.push(L, fx);
|
function_detail::select<false>(L, fx);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, std::function<Signature>&& fx) {
|
static int push(lua_State* L, std::function<Signature>&& fx) {
|
||||||
return unqualified_pusher<function_sig<Signature>>{}.push(L, std::move(fx));
|
function_detail::select<false>(L, std::move(fx));
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
struct unqualified_pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
struct unqualified_pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
||||||
template <typename F, typename... Args>
|
template <typename... Args>
|
||||||
static int push(lua_State* L, F&& f, Args&&... args) {
|
static int push(lua_State* L, Args&&... args) {
|
||||||
unqualified_pusher<function_sig<>> p{};
|
function_detail::select<false>(L, std::forward<Args>(args)...);
|
||||||
(void)p;
|
return 1;
|
||||||
return p.push(L, std::forward<F>(f), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
struct unqualified_pusher<Signature, std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
|
struct unqualified_pusher<Signature,
|
||||||
|
std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>,
|
||||||
|
meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
|
||||||
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
||||||
,
|
,
|
||||||
meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
|
meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>,
|
||||||
|
meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
|
||||||
#endif // noexcept function types
|
#endif // noexcept function types
|
||||||
>::value>> {
|
>::value>> {
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static int push(lua_State* L, F&& f) {
|
static int push(lua_State* L, F&& f) {
|
||||||
return unqualified_pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
function_detail::select<false>(L, std::forward<F>(f));
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Functions>
|
template <typename... Functions>
|
||||||
struct unqualified_pusher<overload_set<Functions...>> {
|
struct unqualified_pusher<overload_set<Functions...>> {
|
||||||
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
||||||
// TODO: yielding
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
function_detail::select_set_fx<false, F>(L, std::move(set.functions));
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(set.functions));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
||||||
// TODO: yielding
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
function_detail::select_set_fx<false, F>(L, set.functions);
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, set.functions);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -343,32 +366,29 @@ namespace sol {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename F, typename G>
|
template <typename F, typename G>
|
||||||
struct unqualified_pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
|
struct unqualified_pusher<property_wrapper<F, G>> {
|
||||||
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
|
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
|
||||||
return stack::push(L, overload(std::move(pw.read), std::move(pw.write)));
|
if constexpr (std::is_void_v<F>) {
|
||||||
|
return stack::push(L, std::move(pw.write));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_void_v<G>) {
|
||||||
|
return stack::push(L, std::move(pw.read));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return stack::push(L, overload(std::move(pw.read), std::move(pw.write)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
|
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
|
||||||
return stack::push(L, overload(pw.read, pw.write));
|
if constexpr (std::is_void_v<F>) {
|
||||||
}
|
return stack::push(L, pw.write);
|
||||||
};
|
}
|
||||||
|
else if constexpr (std::is_void_v<G>) {
|
||||||
template <typename F>
|
return stack::push(L, pw.read);
|
||||||
struct unqualified_pusher<property_wrapper<F, void>> {
|
}
|
||||||
static int push(lua_State* L, property_wrapper<F, void>&& pw) {
|
else {
|
||||||
return stack::push(L, std::move(pw.read));
|
return stack::push(L, overload(pw.read, pw.write));
|
||||||
}
|
}
|
||||||
static int push(lua_State* L, const property_wrapper<F, void>& pw) {
|
|
||||||
return stack::push(L, pw.read);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
struct unqualified_pusher<property_wrapper<void, F>> {
|
|
||||||
static int push(lua_State* L, property_wrapper<void, F>&& pw) {
|
|
||||||
return stack::push(L, std::move(pw.write));
|
|
||||||
}
|
|
||||||
static int push(lua_State* L, const property_wrapper<void, F>& pw) {
|
|
||||||
return stack::push(L, pw.write);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -385,26 +405,26 @@ namespace sol {
|
|||||||
template <typename... Functions>
|
template <typename... Functions>
|
||||||
struct unqualified_pusher<factory_wrapper<Functions...>> {
|
struct unqualified_pusher<factory_wrapper<Functions...>> {
|
||||||
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, fw.functions);
|
function_detail::select_set_fx<false, F>(L, fw.functions);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(fw.functions));
|
function_detail::select_set_fx<false, F>(L, std::move(fw.functions));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const factory_wrapper<Functions...>& set, function_detail::call_indicator) {
|
static int push(lua_State* L, const factory_wrapper<Functions...>& fw, function_detail::call_indicator) {
|
||||||
typedef function_detail::overloaded_function<1, Functions...> F;
|
using F = function_detail::overloaded_function<1, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, set.functions);
|
function_detail::select_set_fx<false, F>(L, fw.functions);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, factory_wrapper<Functions...>&& set, function_detail::call_indicator) {
|
static int push(lua_State* L, factory_wrapper<Functions...>&& fw, function_detail::call_indicator) {
|
||||||
typedef function_detail::overloaded_function<1, Functions...> F;
|
using F = function_detail::overloaded_function<1, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(set.functions));
|
function_detail::select_set_fx<false, F>(L, std::move(fw.functions));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace function_detail {
|
namespace function_detail {
|
||||||
template <int start_skew = 0, typename... Functions>
|
template <int start_skew, typename... Functions>
|
||||||
struct overloaded_function {
|
struct overloaded_function {
|
||||||
typedef std::tuple<Functions...> overload_list;
|
typedef std::tuple<Functions...> overload_list;
|
||||||
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
||||||
@ -47,7 +47,8 @@ namespace function_detail {
|
|||||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||||
static int call(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, overload_list& ol) {
|
static int call(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, overload_list& ol) {
|
||||||
auto& func = std::get<I>(ol);
|
auto& func = std::get<I>(ol);
|
||||||
return call_detail::call_wrapped<void, true, false, start_skew>(L, func);
|
int nr = call_detail::call_wrapped<void, true, false, start_skew>(L, func);
|
||||||
|
return nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int operator()(lua_State* L) {
|
int operator()(lua_State* L) {
|
||||||
|
@ -136,6 +136,9 @@ namespace sol {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_member_object<readonly_wrapper<T>> : std::true_type {};
|
struct is_member_object<readonly_wrapper<T>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_member_object_v = is_member_object<T>::value;
|
||||||
} // namespace meta
|
} // namespace meta
|
||||||
|
|
||||||
} // namespace sol
|
} // namespace sol
|
||||||
|
@ -523,13 +523,27 @@ namespace sol {
|
|||||||
struct supports_op_less<T, void> : std::false_type {};
|
struct supports_op_less<T, void> : std::false_type {};
|
||||||
template <typename T, typename U = T>
|
template <typename T, typename U = T>
|
||||||
struct supports_op_equal : decltype(meta_detail::supports_op_equal_test(std::declval<T&>(), std::declval<U&>())) {};
|
struct supports_op_equal : decltype(meta_detail::supports_op_equal_test(std::declval<T&>(), std::declval<U&>())) {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_equal<void, T> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_equal<T, void> : std::false_type {};
|
||||||
template <typename T, typename U = T>
|
template <typename T, typename U = T>
|
||||||
struct supports_op_less_equal : decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>(), std::declval<U&>())) {};
|
struct supports_op_less_equal : decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>(), std::declval<U&>())) {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_less_equal<void, T> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_less_equal<T, void> : std::false_type {};
|
||||||
template <typename T, typename U = std::ostream>
|
template <typename T, typename U = std::ostream>
|
||||||
struct supports_ostream_op : decltype(meta_detail::supports_ostream_op(std::declval<T&>(), std::declval<U&>())) {};
|
struct supports_ostream_op : decltype(meta_detail::supports_ostream_op(std::declval<T&>(), std::declval<U&>())) {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
struct supports_ostream_op<void, T> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_ostream_op<T, void> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
struct supports_adl_to_string : decltype(meta_detail::supports_adl_to_string(std::declval<T&>())) {};
|
struct supports_adl_to_string : decltype(meta_detail::supports_adl_to_string(std::declval<T&>())) {};
|
||||||
|
template <>
|
||||||
|
struct supports_adl_to_string<void> : std::false_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<T>::value>;
|
using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<T>::value>;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ namespace sol {
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
|
struct unqualified : std::remove_cv<std::remove_reference_t<T>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using unqualified_t = typename unqualified<T>::type;
|
using unqualified_t = typename unqualified<T>::type;
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2019-01-17 06:28:58.332972 UTC
|
// Generated 2019-01-28 16:32:19.530572 UTC
|
||||||
// This header was generated with sol v2.20.6 (revision 88a089c)
|
// This header was generated with sol v2.20.6 (revision ad494bd)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2019-01-17 06:28:58.073560 UTC
|
// Generated 2019-01-28 16:32:19.243332 UTC
|
||||||
// This header was generated with sol v2.20.6 (revision 88a089c)
|
// This header was generated with sol v2.20.6 (revision ad494bd)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||||
@ -510,7 +510,7 @@ namespace sol {
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
|
struct unqualified : std::remove_cv<std::remove_reference_t<T>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using unqualified_t = typename unqualified<T>::type;
|
using unqualified_t = typename unqualified<T>::type;
|
||||||
@ -1332,11 +1332,8 @@ namespace sol {
|
|||||||
template <bool B>
|
template <bool B>
|
||||||
using boolean = std::integral_constant<bool, B>;
|
using boolean = std::integral_constant<bool, B>;
|
||||||
|
|
||||||
template <typename T>
|
template <bool B>
|
||||||
using invoke_t = typename T::type;
|
constexpr inline bool boolean_v = boolean<B>::value;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using invoke_v = boolean<T::value>;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using neg = boolean<!T::value>;
|
using neg = boolean<!T::value>;
|
||||||
@ -1710,29 +1707,35 @@ namespace sol {
|
|||||||
struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> {};
|
struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> {};
|
||||||
} // namespace meta_detail
|
} // namespace meta_detail
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1910
|
|
||||||
template <typename T, typename U = T>
|
template <typename T, typename U = T>
|
||||||
using supports_op_less = decltype(meta_detail::supports_op_less_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>())));
|
struct supports_op_less : decltype(meta_detail::supports_op_less_test(std::declval<T&>(), std::declval<U&>())) {};
|
||||||
template <typename T, typename U = T>
|
|
||||||
using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>())));
|
|
||||||
template <typename T, typename U = T>
|
|
||||||
using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>())));
|
|
||||||
template <typename T, typename U = std::ostream>
|
|
||||||
using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::ref(std::declval<T&>()), std::ref(std::declval<U&>())));
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::ref(std::declval<T&>())));
|
struct supports_op_less<void, T> : std::false_type {};
|
||||||
#else
|
|
||||||
template <typename T, typename U = T>
|
|
||||||
using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>(), std::declval<U&>()));
|
|
||||||
template <typename T, typename U = T>
|
|
||||||
using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>(), std::declval<U&>()));
|
|
||||||
template <typename T, typename U = T>
|
|
||||||
using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>(), std::declval<U&>()));
|
|
||||||
template <typename T, typename U = std::ostream>
|
|
||||||
using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::declval<T&>(), std::declval<U&>()));
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::declval<T&>()));
|
struct supports_op_less<T, void> : std::false_type {};
|
||||||
#endif
|
template <typename T, typename U = T>
|
||||||
|
struct supports_op_equal : decltype(meta_detail::supports_op_equal_test(std::declval<T&>(), std::declval<U&>())) {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_equal<void, T> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_equal<T, void> : std::false_type {};
|
||||||
|
template <typename T, typename U = T>
|
||||||
|
struct supports_op_less_equal : decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>(), std::declval<U&>())) {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_less_equal<void, T> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_op_less_equal<T, void> : std::false_type {};
|
||||||
|
template <typename T, typename U = std::ostream>
|
||||||
|
struct supports_ostream_op : decltype(meta_detail::supports_ostream_op(std::declval<T&>(), std::declval<U&>())) {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_ostream_op<void, T> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_ostream_op<T, void> : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct supports_adl_to_string : decltype(meta_detail::supports_adl_to_string(std::declval<T&>())) {};
|
||||||
|
template <>
|
||||||
|
struct supports_adl_to_string<void> : std::false_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<T>::value>;
|
using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<T>::value>;
|
||||||
|
|
||||||
@ -15360,6 +15363,9 @@ namespace sol {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_member_object<readonly_wrapper<T>> : std::true_type {};
|
struct is_member_object<readonly_wrapper<T>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_member_object_v = is_member_object<T>::value;
|
||||||
} // namespace meta
|
} // namespace meta
|
||||||
|
|
||||||
} // namespace sol
|
} // namespace sol
|
||||||
@ -16071,17 +16077,35 @@ namespace sol {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Y, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
||||||
|
struct lua_call_wrapper<T, yielding_t<Y>, is_index, is_variable, checked, boost, clean_stack, C> {
|
||||||
|
template <typename F>
|
||||||
|
static int call(lua_State* L, F&& f) {
|
||||||
|
return lua_call_wrapper<T, meta::unqualified_t<Y>, is_index, is_variable, checked, boost, clean_stack>{}.call(L, f.func);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
||||||
struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> {
|
struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> {
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static int call(lua_State* L, F&& f) {
|
static int call(lua_State* L, F&& f) {
|
||||||
return lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> {}.call(L, std::get<0>(f.arguments));
|
return lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack>{}.call(L, std::get<0>(f.arguments));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... Args>
|
template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... Args>
|
||||||
inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) {
|
inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, checked, boost, clean_stack> {}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
using uFx = meta::unqualified_t<Fx>;
|
||||||
|
if constexpr(meta::is_specialization_of_v<uFx, yielding_t>) {
|
||||||
|
using real_fx = meta::unqualified_t<decltype(std::forward<Fx>(fx).func)>;
|
||||||
|
int nr = lua_call_wrapper<T, real_fx, is_index, is_variable, checked, boost, clean_stack>{}.call(
|
||||||
|
L, std::forward<Fx>(fx).func, std::forward<Args>(args)...);
|
||||||
|
return lua_yield(L, nr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack>{}.call(
|
||||||
|
L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, bool clean_stack = true>
|
template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, bool clean_stack = true>
|
||||||
@ -16607,7 +16631,7 @@ namespace function_detail {
|
|||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace function_detail {
|
namespace function_detail {
|
||||||
template <int start_skew = 0, typename... Functions>
|
template <int start_skew, typename... Functions>
|
||||||
struct overloaded_function {
|
struct overloaded_function {
|
||||||
typedef std::tuple<Functions...> overload_list;
|
typedef std::tuple<Functions...> overload_list;
|
||||||
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
||||||
@ -16624,7 +16648,8 @@ namespace function_detail {
|
|||||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||||
static int call(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, overload_list& ol) {
|
static int call(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, overload_list& ol) {
|
||||||
auto& func = std::get<I>(ol);
|
auto& func = std::get<I>(ol);
|
||||||
return call_detail::call_wrapped<void, true, false, start_skew>(L, func);
|
int nr = call_detail::call_wrapped<void, true, false, start_skew>(L, func);
|
||||||
|
return nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int operator()(lua_State* L) {
|
int operator()(lua_State* L) {
|
||||||
@ -16789,157 +16814,197 @@ namespace sol {
|
|||||||
namespace sol {
|
namespace sol {
|
||||||
namespace function_detail {
|
namespace function_detail {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct class_indicator {};
|
struct class_indicator {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
struct call_indicator {};
|
struct call_indicator {};
|
||||||
} // namespace function_detail
|
|
||||||
|
|
||||||
namespace stack {
|
template <bool yielding>
|
||||||
template <typename... Sigs>
|
inline int lua_c_wrapper(lua_State* L) {
|
||||||
struct unqualified_pusher<function_sig<Sigs...>> {
|
lua_CFunction cf = lua_tocfunction(L, lua_upvalueindex(2));
|
||||||
template <bool is_yielding, typename... Sig, typename Fx, typename... Args>
|
int nr = cf(L);
|
||||||
static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
|
if constexpr (yielding) {
|
||||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
return lua_yield(L, nr);
|
||||||
typedef function_detail::functor_function<clean_fx, is_yielding, true> F;
|
|
||||||
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
|
template <bool yielding>
|
||||||
static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
|
inline int lua_c_noexcept_wrapper(lua_State* L) noexcept {
|
||||||
using fx_ptr_t = R (*)(A...);
|
detail::lua_CFunction_noexcept cf = reinterpret_cast<detail::lua_CFunction_noexcept>(lua_tocfunction(L, lua_upvalueindex(2)));
|
||||||
|
int nr = cf(L);
|
||||||
|
if constexpr (yielding) {
|
||||||
|
return lua_yield(L, nr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct c_function_invocation {};
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select(lua_State* L, Fx&& fx, Args&&... args);
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select_set_fx(lua_State* L, Args&&... args) {
|
||||||
|
lua_CFunction freefunc = detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
|
||||||
|
|
||||||
|
int upvalues = 0;
|
||||||
|
upvalues += stack::push(L, nullptr);
|
||||||
|
upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
||||||
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
|
||||||
|
inline void select_convertible(types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
using dFx = std::decay_t<meta::unwrap_unqualified_t<Fx>>;
|
||||||
|
using fx_ptr_t = R (*)(A...);
|
||||||
|
constexpr bool is_convertible = std::is_convertible_v<dFx, fx_ptr_t>;
|
||||||
|
if constexpr (is_convertible) {
|
||||||
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
||||||
select_function<is_yielding>(std::true_type(), L, fxptr, std::forward<Args>(args)...);
|
select<is_yielding>(L, std::move(fxptr), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
|
using F = function_detail::functor_function<dFx, is_yielding, true>;
|
||||||
static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t;
|
|
||||||
typedef R (*fx_ptr_t)(A...);
|
|
||||||
typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
|
|
||||||
select_convertible<is_yielding>(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
inline void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
|
typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
|
||||||
select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
inline void select_member_variable(lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
using uFx = meta::unqualified_t<Fx>;
|
||||||
typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding> F;
|
if constexpr (sizeof...(Args) < 1) {
|
||||||
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
using C = typename meta::bind_traits<uFx>::object_type;
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
|
||||||
static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
|
||||||
typedef std::decay_t<Fx> dFx;
|
|
||||||
dFx memfxptr(std::forward<Fx>(fx));
|
|
||||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
|
|
||||||
|
|
||||||
int upvalues = 0;
|
|
||||||
upvalues += stack::push(L, nullptr);
|
|
||||||
upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
|
|
||||||
upvalues += stack::push(L, static_cast<void const*>(userptr));
|
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
|
||||||
static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_convertible<is_yielding>(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler>
|
|
||||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
|
||||||
typedef meta::boolean<meta::is_specialization_of<meta::unqualified_t<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
|
|
||||||
select_reference_member_variable<is_yielding>(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename C>
|
|
||||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call;
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call;
|
||||||
|
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
|
else if constexpr (sizeof...(Args) < 2) {
|
||||||
|
using Tu = typename meta::unqualified<Args...>::type;
|
||||||
|
constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
|
||||||
|
if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
|
||||||
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<typename Tu::type, Fx, is_yielding>::call;
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx>
|
int upvalues = 0;
|
||||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
upvalues += stack::push(L, nullptr);
|
||||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call;
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
|
}
|
||||||
int upvalues = 0;
|
else if constexpr (is_reference) {
|
||||||
upvalues += stack::push(L, nullptr);
|
typedef std::decay_t<Fx> dFx;
|
||||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
dFx memfxptr(std::forward<Fx>(fx));
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
auto userptr = detail::ptr(std::forward<Args>(args)...);
|
||||||
|
lua_CFunction freefunc
|
||||||
|
= &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
|
||||||
|
|
||||||
|
int upvalues = 0;
|
||||||
|
upvalues += stack::push(L, nullptr);
|
||||||
|
upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||||
|
upvalues += stack::push(L, static_cast<void const*>(userptr));
|
||||||
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
|
||||||
|
using F = function_detail::member_variable<Tu, clean_fx, is_yielding>;
|
||||||
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
using C = typename meta::bind_traits<uFx>::object_type;
|
||||||
static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
|
||||||
typedef std::decay_t<Fx> clean_fx;
|
using F = function_detail::member_variable<C, clean_fx, is_yielding>;
|
||||||
typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding> F;
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
template <bool is_yielding, typename Fx, typename T, typename... Args>
|
||||||
static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
inline void select_member_function_with(lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||||
using dFx = std::decay_t<Fx>;
|
using dFx = std::decay_t<Fx>;
|
||||||
dFx memfxptr(std::forward<Fx>(fx));
|
using Tu = meta::unqualified_t<T>;
|
||||||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
|
using C = typename Tu::type;
|
||||||
|
|
||||||
int upvalues = 0;
|
|
||||||
upvalues += stack::push(L, nullptr);
|
|
||||||
upvalues += stack::push<user<dFx>>(L, memfxptr);
|
|
||||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
|
||||||
static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_member_variable<is_yielding>(meta::is_member_object<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler>
|
|
||||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
|
||||||
typedef meta::boolean<meta::is_specialization_of<meta::unqualified_t<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
|
|
||||||
select_reference_member_function<is_yielding>(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename C>
|
|
||||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
|
||||||
using dFx = std::decay_t<Fx>;
|
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
||||||
|
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
upvalues += stack::push<user<dFx>>(L, fx);
|
upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
|
||||||
|
if constexpr (is_reference) {
|
||||||
|
auto userptr = detail::ptr(std::forward<T>(obj));
|
||||||
|
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, dFx, is_yielding>::call;
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx>
|
int upvalues = 0;
|
||||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
upvalues += stack::push(L, nullptr);
|
||||||
using dFx = std::decay_t<Fx>;
|
upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||||
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
using F = function_detail::member_function<Tu, dFx, is_yielding>;
|
||||||
|
select_set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
|
inline void select_member_function(lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
using dFx = std::decay_t<Fx>;
|
||||||
|
if constexpr (sizeof...(Args) < 1) {
|
||||||
|
using C = typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type;
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
|
||||||
|
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
upvalues += stack::push<user<dFx>>(L, fx);
|
upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx));
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
select_member_function_with<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_member_function<is_yielding>(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
template <bool is_yielding, typename Fx, typename... Args>
|
||||||
static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
|
inline void select(lua_State* L, Fx&& fx, Args&&... args) {
|
||||||
|
using uFx = meta::unqualified_t<Fx>;
|
||||||
|
if constexpr (is_lua_reference_v<uFx>) {
|
||||||
|
// TODO: hoist into lambda in this case for yielding???
|
||||||
|
stack::push(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else if constexpr (is_lua_c_function_v<uFx>) {
|
||||||
|
int upvalues = 0;
|
||||||
|
upvalues += stack::push(L, nullptr);
|
||||||
|
upvalues += stack::push(L, std::forward<Fx>(fx));
|
||||||
|
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
||||||
|
if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
|
||||||
|
detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>;
|
||||||
|
lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_CFunction cf = &lua_c_wrapper<is_yielding>;
|
||||||
|
lua_pushcclosure(L, cf, 2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>;
|
||||||
|
lua_pushcclosure(L, cf, 2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_function_v<std::remove_pointer_t<uFx>>) {
|
||||||
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx, is_yielding>::call;
|
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx, is_yielding>::call;
|
||||||
|
|
||||||
@ -16948,53 +17013,29 @@ namespace sol {
|
|||||||
upvalues += stack::stack_detail::push_as_upvalues(L, target);
|
upvalues += stack::stack_detail::push_as_upvalues(L, target);
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
stack::push(L, c_closure(freefunc, upvalues));
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_member_function_pointer_v<uFx>) {
|
||||||
template <bool is_yielding>
|
select_member_function<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
|
|
||||||
// TODO: support yielding
|
|
||||||
stack::push(L, f);
|
|
||||||
}
|
}
|
||||||
|
else if constexpr (meta::is_member_object_v<uFx>) {
|
||||||
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
select_member_variable<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
template <bool is_yielding>
|
|
||||||
static void select_function(std::true_type, lua_State* L, detail::lua_CFunction_noexcept f) {
|
|
||||||
// TODO: support yielding
|
|
||||||
stack::push(L, f);
|
|
||||||
}
|
}
|
||||||
#endif // noexcept function type
|
else {
|
||||||
|
select_convertible<is_yielding>(types<>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
template <bool is_yielding, typename Fx, typename... Args, meta::disable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler>
|
|
||||||
static void select(lua_State* L, Fx&& fx, Args&&... args) {
|
|
||||||
select_function<is_yielding>(std::is_function<std::remove_pointer_t<meta::unqualified_t<Fx>>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} // namespace function_detail
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, meta::enable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler>
|
namespace stack {
|
||||||
static void select(lua_State* L, Fx&& fx) {
|
template <typename... Sigs>
|
||||||
// TODO: hoist into lambda in this case??
|
struct unqualified_pusher<function_sig<Sigs...>> {
|
||||||
stack::push(L, std::forward<Fx>(fx));
|
template <typename Arg0, typename... Args>
|
||||||
}
|
|
||||||
|
|
||||||
template <bool is_yielding, typename Fx, typename... Args>
|
|
||||||
static void set_fx(lua_State* L, Args&&... args) {
|
|
||||||
lua_CFunction freefunc = detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
|
|
||||||
|
|
||||||
int upvalues = 0;
|
|
||||||
upvalues += stack::push(L, nullptr);
|
|
||||||
upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
|
||||||
stack::push(L, c_closure(freefunc, upvalues));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Arg0, typename... Args, meta::disable<std::is_same<detail::yield_tag_t, meta::unqualified_t<Arg0>>> = meta::enabler>
|
|
||||||
static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
|
static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
|
||||||
// Set will always place one thing (function) on the stack
|
if constexpr (std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) {
|
||||||
select<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
|
function_detail::select<true>(L, std::forward<Args>(args)...);
|
||||||
return 1;
|
}
|
||||||
}
|
else {
|
||||||
|
function_detail::select<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
|
||||||
template <typename... Args>
|
}
|
||||||
static int push(lua_State* L, detail::yield_tag_t, Args&&... args) {
|
|
||||||
// Set will always place one thing (function) on the stack
|
|
||||||
select<true>(L, std::forward<Args>(args)...);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -17003,16 +17044,14 @@ namespace sol {
|
|||||||
struct unqualified_pusher<yielding_t<T>> {
|
struct unqualified_pusher<yielding_t<T>> {
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) {
|
static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) {
|
||||||
unqualified_pusher<function_sig<>> p{};
|
function_detail::select<true>(L, f.func, std::forward<Args>(args)...);
|
||||||
(void)p;
|
return 1;
|
||||||
return p.push(L, detail::yield_tag, f.func, std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) {
|
static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) {
|
||||||
unqualified_pusher<function_sig<>> p{};
|
function_detail::select<true>(L, std::move(f.func), std::forward<Args>(args)...);
|
||||||
(void)p;
|
return 1;
|
||||||
return p.push(L, detail::yield_tag, f.func, std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17035,50 +17074,53 @@ namespace sol {
|
|||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
struct unqualified_pusher<std::function<Signature>> {
|
struct unqualified_pusher<std::function<Signature>> {
|
||||||
static int push(lua_State* L, const std::function<Signature>& fx) {
|
static int push(lua_State* L, const std::function<Signature>& fx) {
|
||||||
return unqualified_pusher<function_sig<Signature>>{}.push(L, fx);
|
function_detail::select<false>(L, fx);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, std::function<Signature>&& fx) {
|
static int push(lua_State* L, std::function<Signature>&& fx) {
|
||||||
return unqualified_pusher<function_sig<Signature>>{}.push(L, std::move(fx));
|
function_detail::select<false>(L, std::move(fx));
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
struct unqualified_pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
struct unqualified_pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
||||||
template <typename F, typename... Args>
|
template <typename... Args>
|
||||||
static int push(lua_State* L, F&& f, Args&&... args) {
|
static int push(lua_State* L, Args&&... args) {
|
||||||
unqualified_pusher<function_sig<>> p{};
|
function_detail::select<false>(L, std::forward<Args>(args)...);
|
||||||
(void)p;
|
return 1;
|
||||||
return p.push(L, std::forward<F>(f), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
struct unqualified_pusher<Signature, std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
|
struct unqualified_pusher<Signature,
|
||||||
|
std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>,
|
||||||
|
meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
|
||||||
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE
|
||||||
,
|
,
|
||||||
meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
|
meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>,
|
||||||
|
meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
|
||||||
#endif // noexcept function types
|
#endif // noexcept function types
|
||||||
>::value>> {
|
>::value>> {
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static int push(lua_State* L, F&& f) {
|
static int push(lua_State* L, F&& f) {
|
||||||
return unqualified_pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
function_detail::select<false>(L, std::forward<F>(f));
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Functions>
|
template <typename... Functions>
|
||||||
struct unqualified_pusher<overload_set<Functions...>> {
|
struct unqualified_pusher<overload_set<Functions...>> {
|
||||||
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
||||||
// TODO: yielding
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
function_detail::select_set_fx<false, F>(L, std::move(set.functions));
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(set.functions));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
||||||
// TODO: yielding
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
function_detail::select_set_fx<false, F>(L, set.functions);
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, set.functions);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -17103,32 +17145,29 @@ namespace sol {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename F, typename G>
|
template <typename F, typename G>
|
||||||
struct unqualified_pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
|
struct unqualified_pusher<property_wrapper<F, G>> {
|
||||||
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
|
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
|
||||||
return stack::push(L, overload(std::move(pw.read), std::move(pw.write)));
|
if constexpr (std::is_void_v<F>) {
|
||||||
|
return stack::push(L, std::move(pw.write));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_void_v<G>) {
|
||||||
|
return stack::push(L, std::move(pw.read));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return stack::push(L, overload(std::move(pw.read), std::move(pw.write)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
|
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
|
||||||
return stack::push(L, overload(pw.read, pw.write));
|
if constexpr (std::is_void_v<F>) {
|
||||||
}
|
return stack::push(L, pw.write);
|
||||||
};
|
}
|
||||||
|
else if constexpr (std::is_void_v<G>) {
|
||||||
template <typename F>
|
return stack::push(L, pw.read);
|
||||||
struct unqualified_pusher<property_wrapper<F, void>> {
|
}
|
||||||
static int push(lua_State* L, property_wrapper<F, void>&& pw) {
|
else {
|
||||||
return stack::push(L, std::move(pw.read));
|
return stack::push(L, overload(pw.read, pw.write));
|
||||||
}
|
}
|
||||||
static int push(lua_State* L, const property_wrapper<F, void>& pw) {
|
|
||||||
return stack::push(L, pw.read);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
struct unqualified_pusher<property_wrapper<void, F>> {
|
|
||||||
static int push(lua_State* L, property_wrapper<void, F>&& pw) {
|
|
||||||
return stack::push(L, std::move(pw.write));
|
|
||||||
}
|
|
||||||
static int push(lua_State* L, const property_wrapper<void, F>& pw) {
|
|
||||||
return stack::push(L, pw.write);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17145,26 +17184,26 @@ namespace sol {
|
|||||||
template <typename... Functions>
|
template <typename... Functions>
|
||||||
struct unqualified_pusher<factory_wrapper<Functions...>> {
|
struct unqualified_pusher<factory_wrapper<Functions...>> {
|
||||||
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, fw.functions);
|
function_detail::select_set_fx<false, F>(L, fw.functions);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
|
||||||
typedef function_detail::overloaded_function<0, Functions...> F;
|
using F = function_detail::overloaded_function<0, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(fw.functions));
|
function_detail::select_set_fx<false, F>(L, std::move(fw.functions));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const factory_wrapper<Functions...>& set, function_detail::call_indicator) {
|
static int push(lua_State* L, const factory_wrapper<Functions...>& fw, function_detail::call_indicator) {
|
||||||
typedef function_detail::overloaded_function<1, Functions...> F;
|
using F = function_detail::overloaded_function<1, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, set.functions);
|
function_detail::select_set_fx<false, F>(L, fw.functions);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, factory_wrapper<Functions...>&& set, function_detail::call_indicator) {
|
static int push(lua_State* L, factory_wrapper<Functions...>&& fw, function_detail::call_indicator) {
|
||||||
typedef function_detail::overloaded_function<1, Functions...> F;
|
using F = function_detail::overloaded_function<1, Functions...>;
|
||||||
unqualified_pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(set.functions));
|
function_detail::select_set_fx<false, F>(L, std::move(fw.functions));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,9 +25,70 @@
|
|||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
struct coro_h {
|
||||||
|
int x = 500;
|
||||||
|
int func() {
|
||||||
|
x += 1;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct coro_test {
|
||||||
|
std::string identifier;
|
||||||
|
sol::reference obj;
|
||||||
|
|
||||||
|
coro_test(sol::this_state L, std::string id) : identifier(id), obj(L, sol::lua_nil) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void store(sol::table ref) {
|
||||||
|
// must be explicit
|
||||||
|
obj = sol::reference(obj.lua_state(), ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_store(sol::table ref) {
|
||||||
|
// must be explicit
|
||||||
|
obj = sol::reference(obj.lua_state(), ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::reference get() {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
~coro_test() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct coro_test_implicit {
|
||||||
|
std::string identifier;
|
||||||
|
sol::main_reference obj;
|
||||||
|
|
||||||
|
coro_test_implicit(sol::this_state L, std::string id) : identifier(id), obj(L, sol::lua_nil) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void store(sol::table ref) {
|
||||||
|
// main_reference does the state shift implicitly
|
||||||
|
obj = std::move(ref);
|
||||||
|
lua_State* Lmain = sol::main_thread(ref.lua_state());
|
||||||
|
REQUIRE(obj.lua_state() == Lmain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_store(sol::table ref) {
|
||||||
|
// main_reference does the state shift implicitly
|
||||||
|
obj = ref;
|
||||||
|
lua_State* Lmain = sol::main_thread(ref.lua_state());
|
||||||
|
REQUIRE(obj.lua_state() == Lmain);
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::reference get() {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
~coro_test_implicit() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("coroutines/coroutine.yield", "ensure calling a coroutine works") {
|
TEST_CASE("coroutines/coroutine.yield", "ensure calling a coroutine works") {
|
||||||
const auto& script = R"(counter = 20
|
const auto& script = R"(counter = 20
|
||||||
|
|
||||||
function loop()
|
function loop()
|
||||||
while counter ~= 30
|
while counter ~= 30
|
||||||
do
|
do
|
||||||
@ -55,7 +116,6 @@ end
|
|||||||
|
|
||||||
TEST_CASE("coroutines/new thread coroutines", "ensure calling a coroutine works when the work is put on a different thread") {
|
TEST_CASE("coroutines/new thread coroutines", "ensure calling a coroutine works when the work is put on a different thread") {
|
||||||
const auto& code = R"(counter = 20
|
const auto& code = R"(counter = 20
|
||||||
|
|
||||||
function loop()
|
function loop()
|
||||||
while counter ~= 30
|
while counter ~= 30
|
||||||
do
|
do
|
||||||
@ -145,10 +205,10 @@ TEST_CASE("coroutines/explicit transfer", "check that the xmove constructors shi
|
|||||||
-- co - L2
|
-- co - L2
|
||||||
-- co2 - L3
|
-- co2 - L3
|
||||||
|
|
||||||
x = co_test.new("x")
|
x = coro_test.new("x")
|
||||||
local co = coroutine.wrap(
|
local co = coroutine.wrap(
|
||||||
function()
|
function()
|
||||||
local t = co_test.new("t")
|
local t = coro_test.new("t")
|
||||||
local co2 = coroutine.wrap(
|
local co2 = coroutine.wrap(
|
||||||
function()
|
function()
|
||||||
local t2 = { "SOME_TABLE" }
|
local t2 = { "SOME_TABLE" }
|
||||||
@ -171,45 +231,19 @@ collectgarbage()
|
|||||||
co = nil
|
co = nil
|
||||||
)";
|
)";
|
||||||
|
|
||||||
struct co_test {
|
|
||||||
std::string identifier;
|
|
||||||
sol::reference obj;
|
|
||||||
|
|
||||||
co_test(sol::this_state L, std::string id)
|
|
||||||
: identifier(id), obj(L, sol::lua_nil) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void store(sol::table ref) {
|
|
||||||
// must be explicit
|
|
||||||
obj = sol::reference(obj.lua_state(), ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_store(sol::table ref) {
|
|
||||||
// must be explicit
|
|
||||||
obj = sol::reference(obj.lua_state(), ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
sol::reference get() {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
~co_test() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::coroutine, sol::lib::base);
|
lua.open_libraries(sol::lib::coroutine, sol::lib::base);
|
||||||
|
|
||||||
lua.new_usertype<co_test>("co_test",
|
lua.new_usertype<coro_test>("coro_test",
|
||||||
sol::constructors<co_test(sol::this_state, std::string)>(),
|
sol::constructors<coro_test(sol::this_state, std::string)>(),
|
||||||
"store", &co_test::store,
|
"store", &coro_test::store,
|
||||||
"copy_store", &co_test::copy_store,
|
"copy_store", &coro_test::copy_store,
|
||||||
"get", &co_test::get);
|
"get", &coro_test::get);
|
||||||
|
|
||||||
auto r = lua.safe_script(code, sol::script_pass_on_error);
|
auto r = lua.safe_script(code, sol::script_pass_on_error);
|
||||||
REQUIRE(r.valid());
|
REQUIRE(r.valid());
|
||||||
|
|
||||||
co_test& ct = lua["x"];
|
coro_test& ct = lua["x"];
|
||||||
|
|
||||||
lua_State* Lmain1 = lua.lua_state();
|
lua_State* Lmain1 = lua.lua_state();
|
||||||
lua_State* Lmain2 = sol::main_thread(lua);
|
lua_State* Lmain2 = sol::main_thread(lua);
|
||||||
@ -229,10 +263,10 @@ TEST_CASE("coroutines/implicit transfer", "check that copy and move assignment c
|
|||||||
-- co - L2
|
-- co - L2
|
||||||
-- co2 - L3
|
-- co2 - L3
|
||||||
|
|
||||||
x = co_test.new("x")
|
x = coro_test.new("x")
|
||||||
local co = coroutine.wrap(
|
local co = coroutine.wrap(
|
||||||
function()
|
function()
|
||||||
local t = co_test.new("t")
|
local t = coro_test.new("t")
|
||||||
local co2 = coroutine.wrap(
|
local co2 = coroutine.wrap(
|
||||||
function()
|
function()
|
||||||
local t2 = { "SOME_TABLE" }
|
local t2 = { "SOME_TABLE" }
|
||||||
@ -255,11 +289,11 @@ collectgarbage()
|
|||||||
co = nil
|
co = nil
|
||||||
)";
|
)";
|
||||||
|
|
||||||
struct co_test_implicit {
|
struct coro_test_implicit {
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
sol::reference obj;
|
sol::reference obj;
|
||||||
|
|
||||||
co_test_implicit(sol::this_state L, std::string id)
|
coro_test_implicit(sol::this_state L, std::string id)
|
||||||
: identifier(id), obj(L, sol::lua_nil) {
|
: identifier(id), obj(L, sol::lua_nil) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,23 +311,23 @@ co = nil
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
~co_test_implicit() {
|
~coro_test_implicit() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::coroutine, sol::lib::base);
|
lua.open_libraries(sol::lib::coroutine, sol::lib::base);
|
||||||
|
|
||||||
lua.new_usertype<co_test_implicit>("co_test",
|
lua.new_usertype<coro_test_implicit>("coro_test",
|
||||||
sol::constructors<co_test_implicit(sol::this_state, std::string)>(),
|
sol::constructors<coro_test_implicit(sol::this_state, std::string)>(),
|
||||||
"store", &co_test_implicit::store,
|
"store", &coro_test_implicit::store,
|
||||||
"copy_store", &co_test_implicit::copy_store,
|
"copy_store", &coro_test_implicit::copy_store,
|
||||||
"get", &co_test_implicit::get);
|
"get", &coro_test_implicit::get);
|
||||||
|
|
||||||
auto r = lua.safe_script(code, sol::script_pass_on_error);
|
auto r = lua.safe_script(code, sol::script_pass_on_error);
|
||||||
REQUIRE(r.valid());
|
REQUIRE(r.valid());
|
||||||
|
|
||||||
co_test_implicit& ct = lua["x"];
|
coro_test_implicit& ct = lua["x"];
|
||||||
|
|
||||||
lua_State* Lmain1 = lua.lua_state();
|
lua_State* Lmain1 = lua.lua_state();
|
||||||
lua_State* Lmain2 = sol::main_thread(lua);
|
lua_State* Lmain2 = sol::main_thread(lua);
|
||||||
@ -313,10 +347,10 @@ TEST_CASE("coroutines/main transfer", "check that copy and move assignment const
|
|||||||
-- co - L2
|
-- co - L2
|
||||||
-- co2 - L3
|
-- co2 - L3
|
||||||
|
|
||||||
x = co_test.new("x")
|
x = coro_test.new("x")
|
||||||
local co = coroutine.wrap(
|
local co = coroutine.wrap(
|
||||||
function()
|
function()
|
||||||
local t = co_test.new("t")
|
local t = coro_test.new("t")
|
||||||
local co2 = coroutine.wrap(
|
local co2 = coroutine.wrap(
|
||||||
function()
|
function()
|
||||||
local t2 = { "SOME_TABLE" }
|
local t2 = { "SOME_TABLE" }
|
||||||
@ -338,49 +372,19 @@ co = nil
|
|||||||
collectgarbage()
|
collectgarbage()
|
||||||
)";
|
)";
|
||||||
|
|
||||||
struct co_test_implicit {
|
|
||||||
std::string identifier;
|
|
||||||
sol::main_reference obj;
|
|
||||||
|
|
||||||
co_test_implicit(sol::this_state L, std::string id)
|
|
||||||
: identifier(id), obj(L, sol::lua_nil) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void store(sol::table ref) {
|
|
||||||
// main_reference does the state shift implicitly
|
|
||||||
obj = std::move(ref);
|
|
||||||
lua_State* Lmain = sol::main_thread(ref.lua_state());
|
|
||||||
REQUIRE(obj.lua_state() == Lmain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_store(sol::table ref) {
|
|
||||||
// main_reference does the state shift implicitly
|
|
||||||
obj = ref;
|
|
||||||
lua_State* Lmain = sol::main_thread(ref.lua_state());
|
|
||||||
REQUIRE(obj.lua_state() == Lmain);
|
|
||||||
}
|
|
||||||
|
|
||||||
sol::reference get() {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
~co_test_implicit() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::coroutine, sol::lib::base);
|
lua.open_libraries(sol::lib::coroutine, sol::lib::base);
|
||||||
|
|
||||||
lua.new_usertype<co_test_implicit>("co_test",
|
lua.new_usertype<coro_test_implicit>("coro_test",
|
||||||
sol::constructors<co_test_implicit(sol::this_state, std::string)>(),
|
sol::constructors<coro_test_implicit(sol::this_state, std::string)>(),
|
||||||
"store", &co_test_implicit::store,
|
"store", &coro_test_implicit::store,
|
||||||
"copy_store", &co_test_implicit::copy_store,
|
"copy_store", &coro_test_implicit::copy_store,
|
||||||
"get", &co_test_implicit::get);
|
"get", &coro_test_implicit::get);
|
||||||
|
|
||||||
auto r = lua.safe_script(code, sol::script_pass_on_error);
|
auto r = lua.safe_script(code, sol::script_pass_on_error);
|
||||||
REQUIRE(r.valid());
|
REQUIRE(r.valid());
|
||||||
|
|
||||||
co_test_implicit& ct = lua["x"];
|
coro_test_implicit& ct = lua["x"];
|
||||||
|
|
||||||
lua_State* Lmain1 = lua.lua_state();
|
lua_State* Lmain1 = lua.lua_state();
|
||||||
lua_State* Lmain2 = sol::main_thread(lua);
|
lua_State* Lmain2 = sol::main_thread(lua);
|
||||||
@ -532,53 +536,95 @@ end
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("coroutines/yielding", "test that a sol2 bound function can yield when marked yieldable") {
|
TEST_CASE("coroutines/yielding", "test that a sol2 bound function can yield when marked yieldable") {
|
||||||
sol::state lua;
|
SECTION("regular functions") {
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
auto func = [&i]() {
|
auto func = [&i]() {
|
||||||
++i;
|
++i;
|
||||||
return i;
|
return i;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct h {
|
coro_h hobj{};
|
||||||
int x = 500;
|
|
||||||
int func() const {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
} hobj{};
|
|
||||||
|
|
||||||
lua["f"] = sol::yielding(func);
|
lua["f"] = sol::yielding(func);
|
||||||
lua["g"] = sol::yielding([]() { return 300; });
|
lua["g"] = sol::yielding([]() { return 300; });
|
||||||
lua["h"] = sol::yielding(&h::func);
|
lua["h"] = sol::yielding(&coro_h::func);
|
||||||
lua["hobj"] = &hobj;
|
lua["hobj"] = &hobj;
|
||||||
|
|
||||||
sol::string_view code = R"(
|
sol::string_view code = R"(
|
||||||
co1 = coroutine.create(function () return f() end)
|
co1 = coroutine.create(function () return f() end)
|
||||||
success1, value1 = coroutine.resume(co1)
|
success1, value1 = coroutine.resume(co1)
|
||||||
co2 = coroutine.create(function () return g() end)
|
co2 = coroutine.create(function () return g() end)
|
||||||
success2, value2 = coroutine.resume(co2)
|
success2, value2 = coroutine.resume(co2)
|
||||||
co3 = coroutine.create(function()
|
co3 = coroutine.create(function()
|
||||||
h(hobj)
|
h(hobj)
|
||||||
end)
|
end)
|
||||||
success3, value3 = coroutine.resume(co3)
|
success3, value3 = coroutine.resume(co3)
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto result = lua.safe_script(code);
|
auto result = lua.safe_script(code, sol::script_pass_on_error);
|
||||||
REQUIRE(result.valid());
|
REQUIRE(result.valid());
|
||||||
|
|
||||||
bool success1 = lua["success1"];
|
bool success1 = lua["success1"];
|
||||||
int value1 = lua["value1"];
|
int value1 = lua["value1"];
|
||||||
REQUIRE(success1);
|
REQUIRE(success1);
|
||||||
REQUIRE(value1 == 1);
|
REQUIRE(value1 == 1);
|
||||||
|
|
||||||
bool success2 = lua["success2"];
|
bool success2 = lua["success2"];
|
||||||
int value2 = lua["value2"];
|
int value2 = lua["value2"];
|
||||||
REQUIRE(success2);
|
REQUIRE(success2);
|
||||||
REQUIRE(value2 == 300);
|
REQUIRE(value2 == 300);
|
||||||
|
|
||||||
bool success3 = lua["success3"];
|
bool success3 = lua["success3"];
|
||||||
int value3 = lua["value3"];
|
int value3 = lua["value3"];
|
||||||
REQUIRE(success3);
|
REQUIRE(success3);
|
||||||
REQUIRE(value3 == 500);
|
REQUIRE(value3 == 501);
|
||||||
|
|
||||||
|
REQUIRE(hobj.x == 501);
|
||||||
|
}
|
||||||
|
SECTION("usertypes") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
|
||||||
|
|
||||||
|
coro_h hobj;
|
||||||
|
|
||||||
|
lua["hobj"] = &hobj;
|
||||||
|
|
||||||
|
lua.new_usertype<coro_h>("coro_h",
|
||||||
|
"h", sol::yielding(&coro_h::func)
|
||||||
|
);
|
||||||
|
|
||||||
|
sol::string_view code = R"(
|
||||||
|
co4 = coroutine.create(function()
|
||||||
|
hobj:h()
|
||||||
|
hobj.h(hobj)
|
||||||
|
coro_h.h(hobj)
|
||||||
|
end)
|
||||||
|
success4, value4 = coroutine.resume(co4)
|
||||||
|
success5, value5 = coroutine.resume(co4)
|
||||||
|
success6, value6 = coroutine.resume(co4)
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto result = lua.safe_script(code, sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
|
||||||
|
bool success4 = lua["success4"];
|
||||||
|
int value4 = lua["value4"];
|
||||||
|
REQUIRE(success4);
|
||||||
|
REQUIRE(value4 == 501);
|
||||||
|
|
||||||
|
bool success5 = lua["success5"];
|
||||||
|
int value5 = lua["value5"];
|
||||||
|
REQUIRE(success5);
|
||||||
|
REQUIRE(value5 == 502);
|
||||||
|
|
||||||
|
bool success6 = lua["success6"];
|
||||||
|
int value6 = lua["value6"];
|
||||||
|
REQUIRE(success6);
|
||||||
|
REQUIRE(value6 == 503);
|
||||||
|
|
||||||
|
REQUIRE(hobj.x == 503);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user