mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Herpin' that derp.
SOL_NO_COMPAT is now in the proper place and documented in the compatibility part of the API. Basic test for `table::add`
This commit is contained in:
parent
556be8da98
commit
b6928b4b4e
|
@ -7,6 +7,8 @@ This is a detail header used to maintain compatability with the 5.2 and 5.3 APIs
|
|||
|
||||
It is not fully documented as this header's only purpose is for internal use to make sure Sol compiles across all platforms / distributions with no errors or missing Lua functionality. If you think there's some compatibility features we are missing or if you are running into redefinition errors, please make an `issue in the issue tracker`_.
|
||||
|
||||
If you have this already in your project or you have your own compatibility layer, then please ``#define SOL_NO_COMPAT 1`` before including ``sol.hpp`` or pass this flag on the command line to turn off the compatibility wrapper.
|
||||
|
||||
For the licenses, see :doc:`here<../licenses>`
|
||||
|
||||
.. _issue in the issue tracker: https://github.com/ThePhD/sol2/issues/
|
||||
|
|
|
@ -1,218 +1,242 @@
|
|||
#pragma once
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013-2016 Rappt1101010z, ThePhD and contributors
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef SOL_BIND_TRAITS_HPP
|
||||
#define SOL_BIND_TRAITS_HPP
|
||||
|
||||
#include "tuple.hpp"
|
||||
|
||||
namespace sol {
|
||||
namespace meta {
|
||||
namespace meta_detail {
|
||||
namespace meta {
|
||||
namespace meta_detail {
|
||||
|
||||
template<class F>
|
||||
struct check_deducible_signature {
|
||||
struct nat {};
|
||||
template<class G>
|
||||
static auto test(int) -> decltype(&G::operator(), void());
|
||||
template<class>
|
||||
static auto test(...) -> nat;
|
||||
template<class F>
|
||||
struct check_deducible_signature {
|
||||
struct nat {};
|
||||
template<class G>
|
||||
static auto test(int) -> decltype(&G::operator(), void());
|
||||
template<class>
|
||||
static auto test(...)->nat;
|
||||
|
||||
using type = std::is_void<decltype(test<F>(0))>;
|
||||
};
|
||||
} // meta_detail
|
||||
using type = std::is_void<decltype(test<F>(0))>;
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template<class F>
|
||||
struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { };
|
||||
template<class F>
|
||||
struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { };
|
||||
|
||||
namespace meta_detail {
|
||||
namespace meta_detail {
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
struct void_tuple_element : meta::tuple_element<I, T> {};
|
||||
template <std::size_t I, typename T>
|
||||
struct void_tuple_element : meta::tuple_element<I, T> {};
|
||||
|
||||
template <std::size_t I>
|
||||
struct void_tuple_element<I, std::tuple<>> { typedef void type; };
|
||||
template <std::size_t I>
|
||||
struct void_tuple_element<I, std::tuple<>> { typedef void type; };
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
using void_tuple_element_t = typename void_tuple_element<I, T>::type;
|
||||
template <std::size_t I, typename T>
|
||||
using void_tuple_element_t = typename void_tuple_element<I, T>::type;
|
||||
|
||||
template <bool has_c_variadic, typename T, typename R, typename... Args>
|
||||
struct basic_traits {
|
||||
private:
|
||||
typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type;
|
||||
template <bool has_c_variadic, typename T, typename R, typename... Args>
|
||||
struct basic_traits {
|
||||
private:
|
||||
typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type;
|
||||
|
||||
public:
|
||||
static const bool is_member_function = std::is_void<T>::value;
|
||||
static const bool has_c_var_arg = has_c_variadic;
|
||||
static const std::size_t arity = sizeof...(Args);
|
||||
static const std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value);
|
||||
typedef types<Args...> args_list;
|
||||
typedef std::tuple<Args...> args_tuple;
|
||||
typedef T object_type;
|
||||
typedef R return_type;
|
||||
typedef tuple_types<R> returns_list;
|
||||
typedef R(function_type)(Args...);
|
||||
typedef std::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list;
|
||||
typedef std::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type;
|
||||
typedef std::conditional_t<std::is_void<T>::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type;
|
||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||
};
|
||||
public:
|
||||
static const bool is_member_function = std::is_void<T>::value;
|
||||
static const bool has_c_var_arg = has_c_variadic;
|
||||
static const std::size_t arity = sizeof...(Args);
|
||||
static const std::size_t free_arity = sizeof...(Args)+static_cast<std::size_t>(!std::is_void<T>::value);
|
||||
typedef types<Args...> args_list;
|
||||
typedef std::tuple<Args...> args_tuple;
|
||||
typedef T object_type;
|
||||
typedef R return_type;
|
||||
typedef tuple_types<R> returns_list;
|
||||
typedef R(function_type)(Args...);
|
||||
typedef std::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list;
|
||||
typedef std::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type;
|
||||
typedef std::conditional_t<std::is_void<T>::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type;
|
||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||
};
|
||||
|
||||
template<typename Signature, bool b = has_deducible_signature<Signature>::value>
|
||||
struct fx_traits : basic_traits<false, void, void> {};
|
||||
template<typename Signature, bool b = has_deducible_signature<Signature>::value>
|
||||
struct fx_traits : basic_traits<false, void, void> {};
|
||||
|
||||
// Free Functions
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
};
|
||||
// Free Functions
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(*)(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
};
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(*)(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args...);
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args..., ...);
|
||||
};
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args..., ...);
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(*)(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args..., ...);
|
||||
};
|
||||
template<typename R, typename... Args>
|
||||
struct fx_traits<R(*)(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||
typedef R(*function_pointer_type)(Args..., ...);
|
||||
};
|
||||
|
||||
// Member Functions
|
||||
/* C-Style Variadics */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...);
|
||||
};
|
||||
// Member Functions
|
||||
/* C-Style Variadics */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...);
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...);
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...);
|
||||
};
|
||||
|
||||
/* Const Volatile */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const;
|
||||
};
|
||||
/* Const Volatile */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile;
|
||||
};
|
||||
|
||||
/* Member Function Qualifiers */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) &;
|
||||
};
|
||||
/* Member Function Qualifiers */
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) &;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const &;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const &;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile &;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) &&;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) && , false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) && ;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) &&;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) && , false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) && ;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const &&;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const &&;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile &&;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args...) const volatile &&;
|
||||
};
|
||||
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&;
|
||||
};
|
||||
template<typename T, typename R, typename... Args>
|
||||
struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<true, T, R, Args...> {
|
||||
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&;
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {};
|
||||
template<typename Signature>
|
||||
struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {};
|
||||
|
||||
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
|
||||
struct callable_traits : fx_traits<std::decay_t<Signature>> {
|
||||
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
|
||||
struct callable_traits : fx_traits<std::decay_t<Signature>> {
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
struct callable_traits<R(T::*), true> {
|
||||
typedef R Arg;
|
||||
typedef T object_type;
|
||||
using signature_type = R(T::*);
|
||||
static const bool is_member_function = false;
|
||||
static const std::size_t arity = 1;
|
||||
static const std::size_t free_arity = 2;
|
||||
typedef std::tuple<Arg> args_tuple;
|
||||
typedef R return_type;
|
||||
typedef types<Arg> args_list;
|
||||
typedef meta::tuple_types<R> returns_list;
|
||||
typedef R(function_type)(T&, R);
|
||||
typedef R(*function_pointer_type)(T&, R);
|
||||
typedef R(*free_function_pointer_type)(T&, R);
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||
};
|
||||
} // meta_detail
|
||||
template<typename R, typename T>
|
||||
struct callable_traits<R(T::*), true> {
|
||||
typedef R Arg;
|
||||
typedef T object_type;
|
||||
using signature_type = R(T::*);
|
||||
static const bool is_member_function = false;
|
||||
static const std::size_t arity = 1;
|
||||
static const std::size_t free_arity = 2;
|
||||
typedef std::tuple<Arg> args_tuple;
|
||||
typedef R return_type;
|
||||
typedef types<Arg> args_list;
|
||||
typedef meta::tuple_types<R> returns_list;
|
||||
typedef R(function_type)(T&, R);
|
||||
typedef R(*function_pointer_type)(T&, R);
|
||||
typedef R(*free_function_pointer_type)(T&, R);
|
||||
template<std::size_t i>
|
||||
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template<typename Signature>
|
||||
struct bind_traits : meta_detail::callable_traits<Signature> {};
|
||||
template<typename Signature>
|
||||
struct bind_traits : meta_detail::callable_traits<Signature> {};
|
||||
|
||||
template<typename Signature>
|
||||
using function_args_t = typename bind_traits<Signature>::args_list;
|
||||
template<typename Signature>
|
||||
using function_args_t = typename bind_traits<Signature>::args_list;
|
||||
|
||||
template<typename Signature>
|
||||
using function_signature_t = typename bind_traits<Signature>::signature_type;
|
||||
template<typename Signature>
|
||||
using function_signature_t = typename bind_traits<Signature>::signature_type;
|
||||
|
||||
template<typename Signature>
|
||||
using function_return_t = typename bind_traits<Signature>::return_type;
|
||||
template<typename Signature>
|
||||
using function_return_t = typename bind_traits<Signature>::return_type;
|
||||
|
||||
} // meta
|
||||
} // meta
|
||||
} // sol
|
||||
|
||||
#endif // SOL_BIND_TRAITS
|
||||
|
|
672
sol/call.hpp
672
sol/call.hpp
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013-2016 Rappt1101010z, ThePhD and contributors
|
||||
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
@ -27,293 +27,113 @@
|
|||
#include "stack.hpp"
|
||||
|
||||
namespace sol {
|
||||
namespace call_detail {
|
||||
namespace call_detail {
|
||||
|
||||
template <bool b, typename F>
|
||||
inline decltype(auto) pick(std::integral_constant<bool, b>, F&& f) {
|
||||
return std::forward<F>(f);
|
||||
}
|
||||
|
||||
template <typename R, typename W>
|
||||
inline auto& pick(std::true_type, property_wrapper<R, W>& f) {
|
||||
return f.read;
|
||||
}
|
||||
|
||||
template <typename R, typename W>
|
||||
inline auto& pick(std::false_type, property_wrapper<R, W>& f) {
|
||||
return f.write;
|
||||
}
|
||||
|
||||
template <typename T, typename List>
|
||||
struct void_call;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
struct void_call<T, types<Args...>> {
|
||||
static void call(Args...) {}
|
||||
};
|
||||
|
||||
template <typename T, int additional_pop = 0>
|
||||
struct constructor_match {
|
||||
T* obj;
|
||||
|
||||
constructor_match(T* obj) : obj(obj) {}
|
||||
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
|
||||
detail::default_construct func{};
|
||||
return stack::call_into_lua<additional_pop, false>(r, a, L, start, func, obj);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline int destruct(lua_State* L) {
|
||||
T* obj = stack::get<non_null<T*>>(L, 1);
|
||||
std::allocator<T> alloc{};
|
||||
alloc.destroy(obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace overload_detail {
|
||||
template <std::size_t... M, typename Match, typename... Args>
|
||||
inline int overload_match_arity(sol::types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
|
||||
return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types");
|
||||
template <bool b, typename F>
|
||||
inline decltype(auto) pick(std::integral_constant<bool, b>, F&& f) {
|
||||
return std::forward<F>(f);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
|
||||
inline int overload_match_arity(sol::types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
|
||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||
typedef typename traits::free_args_list args_list;
|
||||
typedef typename args_list::indices args_indices;
|
||||
// compile-time eliminate any functions that we know ahead of time are of improper arity
|
||||
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
template <typename R, typename W>
|
||||
inline auto& pick(std::true_type, property_wrapper<R, W>& f) {
|
||||
return f.read;
|
||||
}
|
||||
|
||||
template <typename R, typename W>
|
||||
inline auto& pick(std::false_type, property_wrapper<R, W>& f) {
|
||||
return f.write;
|
||||
}
|
||||
|
||||
template <typename T, typename List>
|
||||
struct void_call;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
struct void_call<T, types<Args...>> {
|
||||
static void call(Args...) {}
|
||||
};
|
||||
|
||||
template <typename T, int additional_pop = 0>
|
||||
struct constructor_match {
|
||||
T* obj;
|
||||
|
||||
constructor_match(T* obj) : obj(obj) {}
|
||||
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
|
||||
detail::default_construct func{};
|
||||
return stack::call_into_lua<additional_pop, false>(r, a, L, start, func, obj);
|
||||
}
|
||||
if (traits::free_arity != fxarity) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
if (!stack::stack_detail::check_types<true>().check(args_list(), args_indices(), L, start, no_panic)) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
} // overload_detail
|
||||
};
|
||||
|
||||
template <typename... Functions, typename Match, typename... Args>
|
||||
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Functions, typename Match, typename... Args>
|
||||
inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) {
|
||||
int fxarity = lua_gettop(L) - (start - 1);
|
||||
return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... TypeLists, typename Match, typename... Args>
|
||||
inline int construct(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
// use same overload resolution matching as all other parts of the framework
|
||||
return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... TypeLists>
|
||||
inline int construct(lua_State* L) {
|
||||
static const auto& meta = usertype_traits<T>::metatable;
|
||||
int argcount = lua_gettop(L);
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
T*& referencepointer = *pointerpointer;
|
||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
||||
referencepointer = obj;
|
||||
reference userdataref(L, -1);
|
||||
userdataref.pop();
|
||||
|
||||
construct<T, TypeLists...>(constructor_match<T>(obj), L, argcount, 1 + static_cast<int>(syntax));
|
||||
|
||||
userdataref.push();
|
||||
luaL_getmetatable(L, &meta[0]);
|
||||
if (type_of(L, -1) == type::nil) {
|
||||
lua_pop(L, 1);
|
||||
return luaL_error(L, "sol: unable to get usertype metatable");
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <typename F, bool is_index, bool is_variable, typename = void>
|
||||
struct agnostic_lua_call_wrapper {
|
||||
static int var_call(std::true_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua<is_index ? 1 : 2>(returns_list(), args_list(), L, is_index ? 2 : 3, caller(), f);
|
||||
}
|
||||
|
||||
static int var_call(std::false_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua(returns_list(), args_list(), L, 1, caller(), f);
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
return var_call(std::integral_constant<bool, is_variable>(), L, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_index, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, is_index, is_variable, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
|
||||
static int call(lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::caller caller;
|
||||
typedef typename wrap::object_type object_type;
|
||||
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, lua_r_CFunction f) {
|
||||
return f(L);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, lua_CFunction f) {
|
||||
return f(L);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, no_prop&) {
|
||||
return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, false, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call_assign(std::true_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::caller caller;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
if (is_variable) {
|
||||
return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)");
|
||||
}
|
||||
return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
|
||||
static int call_assign(std::false_type, lua_State* L, F&) {
|
||||
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
static int call_const(std::false_type, lua_State* L, F& f) {
|
||||
typedef typename traits_type::return_type R;
|
||||
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, f);
|
||||
}
|
||||
|
||||
static int call_const(std::true_type, lua_State* L, F&) {
|
||||
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
return call_const(std::is_const<typename traits_type::return_type>(), L, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, true, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::caller caller;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
if (is_variable) {
|
||||
return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)");
|
||||
}
|
||||
return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, no_construction&) {
|
||||
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args, bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, C> {
|
||||
static int call(lua_State*, bases<Args...>&) {
|
||||
// Uh. How did you even call this, lul
|
||||
template <typename T>
|
||||
inline int destruct(lua_State* L) {
|
||||
T* obj = stack::get<non_null<T*>>(L, 1);
|
||||
std::allocator<T> alloc{};
|
||||
alloc.destroy(obj);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename F, bool is_index, bool is_variable, typename = void>
|
||||
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable> {};
|
||||
namespace overload_detail {
|
||||
template <std::size_t... M, typename Match, typename... Args>
|
||||
inline int overload_match_arity(sol::types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
|
||||
return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types");
|
||||
}
|
||||
|
||||
template <typename T, typename... Args, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, C> {
|
||||
typedef sol::constructor_list<Args...> F;
|
||||
template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
|
||||
inline int overload_match_arity(sol::types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
|
||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||
typedef typename traits::free_args_list args_list;
|
||||
typedef typename args_list::indices args_indices;
|
||||
// compile-time eliminate any functions that we know ahead of time are of improper arity
|
||||
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
if (traits::free_arity != fxarity) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
if (!stack::stack_detail::check_types<true>().check(args_list(), args_indices(), L, start, no_panic)) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
} // overload_detail
|
||||
|
||||
static int call(lua_State* L, F&) {
|
||||
static const auto& metakey = usertype_traits<T>::metatable;
|
||||
template <typename... Functions, typename Match, typename... Args>
|
||||
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Functions, typename Match, typename... Args>
|
||||
inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) {
|
||||
int fxarity = lua_gettop(L) - (start - 1);
|
||||
return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... TypeLists, typename Match, typename... Args>
|
||||
inline int construct(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||
// use same overload resolution matching as all other parts of the framework
|
||||
return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... TypeLists>
|
||||
inline int construct(lua_State* L) {
|
||||
static const auto& meta = usertype_traits<T>::metatable;
|
||||
int argcount = lua_gettop(L);
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot;
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
reference userdataref(L, -1);
|
||||
T*& referencepointer = *pointerpointer;
|
||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
||||
referencepointer = obj;
|
||||
reference userdataref(L, -1);
|
||||
userdataref.pop();
|
||||
|
||||
construct<T, Args...>(constructor_match<T, 1>(obj), L, argcount, 1 + static_cast<int>(syntax));
|
||||
construct<T, TypeLists...>(constructor_match<T>(obj), L, argcount, 1 + static_cast<int>(syntax));
|
||||
|
||||
userdataref.push();
|
||||
luaL_getmetatable(L, &metakey[0]);
|
||||
luaL_getmetatable(L, &meta[0]);
|
||||
if (type_of(L, -1) == type::nil) {
|
||||
lua_pop(L, 1);
|
||||
return luaL_error(L, "sol: unable to get usertype metatable");
|
||||
|
@ -322,108 +142,288 @@ namespace call_detail {
|
|||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Cxs, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, sol::constructor_wrapper<Cxs...>, is_index, is_variable, C> {
|
||||
typedef sol::constructor_wrapper<Cxs...> F;
|
||||
template <typename F, bool is_index, bool is_variable, typename = void>
|
||||
struct agnostic_lua_call_wrapper {
|
||||
static int var_call(std::true_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua<is_index ? 1 : 2>(returns_list(), args_list(), L, is_index ? 2 : 3, caller(), f);
|
||||
}
|
||||
|
||||
static int var_call(std::false_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua(returns_list(), args_list(), L, 1, caller(), f);
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
return var_call(std::integral_constant<bool, is_variable>(), L, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_index, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, is_index, is_variable, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
|
||||
static int call(lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::caller caller;
|
||||
typedef typename wrap::object_type object_type;
|
||||
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, lua_r_CFunction f) {
|
||||
return f(L);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, lua_CFunction f) {
|
||||
return f(L);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, no_prop&) {
|
||||
return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, false, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call_assign(std::true_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::caller caller;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
if (is_variable) {
|
||||
return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)");
|
||||
}
|
||||
return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
|
||||
static int call_assign(std::false_type, lua_State* L, F&) {
|
||||
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
static int call_const(std::false_type, lua_State* L, F& f) {
|
||||
typedef typename traits_type::return_type R;
|
||||
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, f);
|
||||
}
|
||||
|
||||
static int call_const(std::true_type, lua_State* L, F&) {
|
||||
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
return call_const(std::is_const<typename traits_type::return_type>(), L, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, true, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::caller caller;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
if (is_variable) {
|
||||
return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)");
|
||||
}
|
||||
return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)");
|
||||
}
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||
#else
|
||||
object_type& o = stack::get<object_type&>(L, 1);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, no_construction&) {
|
||||
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args, bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, C> {
|
||||
static int call(lua_State*, bases<Args...>&) {
|
||||
// Uh. How did you even call this, lul
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename F, bool is_index, bool is_variable, typename = void>
|
||||
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable> {};
|
||||
|
||||
template <typename T, typename... Args, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, C> {
|
||||
typedef sol::constructor_list<Args...> F;
|
||||
|
||||
static int call(lua_State* L, F&) {
|
||||
static const auto& metakey = usertype_traits<T>::metatable;
|
||||
int argcount = lua_gettop(L);
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
struct onmatch {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
reference userdataref(L, -1);
|
||||
T*& referencepointer = *pointerpointer;
|
||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
||||
referencepointer = obj;
|
||||
|
||||
auto& func = std::get<I>(f.set);
|
||||
stack::call_into_lua<1, false>(r, a, L, start, func, detail::implicit_wrapper<T>(obj));
|
||||
construct<T, Args...>(constructor_match<T, 1>(obj), L, argcount, 1 + static_cast<int>(syntax));
|
||||
|
||||
userdataref.push();
|
||||
luaL_getmetatable(L, &usertype_traits<T>::metatable[0]);
|
||||
luaL_getmetatable(L, &metakey[0]);
|
||||
if (type_of(L, -1) == type::nil) {
|
||||
lua_pop(L, 1);
|
||||
std::string err = "sol: unable to get usertype metatable for ";
|
||||
err += usertype_traits<T>::name;
|
||||
return luaL_error(L, err.c_str());
|
||||
return luaL_error(L, "sol: unable to get usertype metatable");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable);
|
||||
int syntaxval = static_cast<int>(syntax);
|
||||
int argcount = lua_gettop(L) - syntaxval;
|
||||
return construct<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
|
||||
}
|
||||
template <typename T, typename... Cxs, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, sol::constructor_wrapper<Cxs...>, is_index, is_variable, C> {
|
||||
typedef sol::constructor_wrapper<Cxs...> F;
|
||||
|
||||
};
|
||||
struct onmatch {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
reference userdataref(L, -1);
|
||||
T*& referencepointer = *pointerpointer;
|
||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
||||
referencepointer = obj;
|
||||
|
||||
template <typename T, typename Fx, bool is_index, bool is_variable>
|
||||
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, std::enable_if_t<std::is_void<Fx>::value>> {
|
||||
typedef sol::destructor_wrapper<Fx> F;
|
||||
auto& func = std::get<I>(f.set);
|
||||
stack::call_into_lua<1, false>(r, a, L, start, func, detail::implicit_wrapper<T>(obj));
|
||||
|
||||
static int call(lua_State* L, F&) {
|
||||
return destruct<T>(L);
|
||||
}
|
||||
};
|
||||
userdataref.push();
|
||||
luaL_getmetatable(L, &usertype_traits<T>::metatable[0]);
|
||||
if (type_of(L, -1) == type::nil) {
|
||||
lua_pop(L, 1);
|
||||
std::string err = "sol: unable to get usertype metatable for ";
|
||||
err += usertype_traits<T>::name;
|
||||
return luaL_error(L, err.c_str());
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
template <typename T, typename Fx, bool is_index, bool is_variable>
|
||||
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, std::enable_if_t<!std::is_void<Fx>::value>> {
|
||||
typedef sol::destructor_wrapper<Fx> F;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
T* obj = stack::get<non_null<T*>>(L);
|
||||
f.fx(detail::implicit_wrapper<T>(obj));
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
static int call(lua_State* L, F& f) {
|
||||
call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable);
|
||||
int syntaxval = static_cast<int>(syntax);
|
||||
int argcount = lua_gettop(L) - syntaxval;
|
||||
return construct<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
|
||||
}
|
||||
|
||||
template <typename T, typename... Fs, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, C> {
|
||||
typedef overload_set<Fs...> F;
|
||||
};
|
||||
|
||||
struct on_match {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) {
|
||||
auto& f = std::get<I>(fx.set);
|
||||
return lua_call_wrapper<T, Fx, is_index, is_variable>{}.call(L, f);
|
||||
template <typename T, typename Fx, bool is_index, bool is_variable>
|
||||
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, std::enable_if_t<std::is_void<Fx>::value>> {
|
||||
typedef sol::destructor_wrapper<Fx> F;
|
||||
|
||||
static int call(lua_State* L, F&) {
|
||||
return destruct<T>(L);
|
||||
}
|
||||
};
|
||||
|
||||
static int call(lua_State* L, F& fx) {
|
||||
return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx);
|
||||
template <typename T, typename Fx, bool is_index, bool is_variable>
|
||||
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, std::enable_if_t<!std::is_void<Fx>::value>> {
|
||||
typedef sol::destructor_wrapper<Fx> F;
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
T* obj = stack::get<non_null<T*>>(L);
|
||||
f.fx(detail::implicit_wrapper<T>(obj));
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Fs, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, C> {
|
||||
typedef overload_set<Fs...> F;
|
||||
|
||||
struct on_match {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) {
|
||||
auto& f = std::get<I>(fx.set);
|
||||
return lua_call_wrapper<T, Fx, is_index, is_variable>{}.call(L, f);
|
||||
}
|
||||
};
|
||||
|
||||
static int call(lua_State* L, F& fx) {
|
||||
return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool is_index, bool is_variable, typename Fx>
|
||||
int call_wrapped(lua_State* L, Fx&& fx) {
|
||||
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable>{}.call(L, std::forward<Fx>(fx));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool is_index, bool is_variable, typename Fx>
|
||||
int call_wrapped(lua_State* L, Fx&& fx) {
|
||||
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable>{}.call(L, std::forward<Fx>(fx));
|
||||
}
|
||||
template <typename T, typename = void>
|
||||
struct is_var_bind : std::false_type {};
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct is_var_bind : std::false_type {};
|
||||
template <typename T>
|
||||
struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_var_bind<no_prop> : std::true_type {};
|
||||
|
||||
template <typename R, typename W>
|
||||
struct is_var_bind<property_wrapper<R, W>> : std::true_type {};
|
||||
|
||||
} // call_detail
|
||||
|
||||
template <typename T>
|
||||
struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {};
|
||||
struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {};
|
||||
|
||||
template <>
|
||||
struct is_var_bind<no_prop> : std::true_type {};
|
||||
|
||||
template <typename R, typename W>
|
||||
struct is_var_bind<property_wrapper<R, W>> : std::true_type {};
|
||||
|
||||
} // call_detail
|
||||
|
||||
template <typename T>
|
||||
struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {};
|
||||
|
||||
template <typename T>
|
||||
struct is_function_binding : meta::neg<is_variable_binding<T>> {};
|
||||
template <typename T>
|
||||
struct is_function_binding : meta::neg<is_variable_binding<T>> {};
|
||||
|
||||
} // sol
|
||||
|
||||
|
|
|
@ -27,9 +27,10 @@
|
|||
// but has been modified in many places for use with Sol and luajit,
|
||||
// though the core abstractions remain the same
|
||||
|
||||
#include "compatibility/version.hpp"
|
||||
|
||||
#ifndef SOL_NO_COMPAT
|
||||
|
||||
#include "compatibility/version.hpp"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -28,88 +28,89 @@
|
|||
#include "thread.hpp"
|
||||
|
||||
namespace sol {
|
||||
class coroutine : public reference {
|
||||
private:
|
||||
call_status stats = call_status::yielded;
|
||||
class coroutine : public reference {
|
||||
private:
|
||||
call_status stats = call_status::yielded;
|
||||
|
||||
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) {
|
||||
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) {
|
||||
#if SOL_LUA_VERSION < 502
|
||||
stats = static_cast<call_status>(lua_resume(lua_state(), static_cast<int>(argcount)));
|
||||
stats = static_cast<call_status>(lua_resume(lua_state(), static_cast<int>(argcount)));
|
||||
#else
|
||||
stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount)));
|
||||
stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount)));
|
||||
#endif // Lua 5.1 compat
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t... I, typename... Ret>
|
||||
auto invoke( types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n ) {
|
||||
luacall(n, sizeof...(Ret));
|
||||
return stack::pop<std::tuple<Ret...>>(lua_state());
|
||||
}
|
||||
template<std::size_t... I, typename... Ret>
|
||||
auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) {
|
||||
luacall(n, sizeof...(Ret));
|
||||
return stack::pop<std::tuple<Ret...>>(lua_state());
|
||||
}
|
||||
|
||||
template<std::size_t I, typename Ret>
|
||||
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) {
|
||||
luacall(n, 1);
|
||||
return stack::pop<Ret>(lua_state());
|
||||
}
|
||||
template<std::size_t I, typename Ret>
|
||||
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) {
|
||||
luacall(n, 1);
|
||||
return stack::pop<Ret>(lua_state());
|
||||
}
|
||||
|
||||
template <std::size_t I>
|
||||
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) {
|
||||
luacall(n, 0);
|
||||
}
|
||||
template <std::size_t I>
|
||||
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) {
|
||||
luacall(n, 0);
|
||||
}
|
||||
|
||||
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
|
||||
int stacksize = lua_gettop( lua_state() );
|
||||
int firstreturn = (std::max)( 1, stacksize - static_cast<int>( n ) );
|
||||
luacall(n, LUA_MULTRET);
|
||||
int poststacksize = lua_gettop(lua_state());
|
||||
int returncount = poststacksize - (firstreturn - 1);
|
||||
return protected_function_result( lua_state( ), firstreturn, returncount, returncount, status() );
|
||||
}
|
||||
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
|
||||
int stacksize = lua_gettop(lua_state());
|
||||
int firstreturn = (std::max)(1, stacksize - static_cast<int>(n));
|
||||
luacall(n, LUA_MULTRET);
|
||||
int poststacksize = lua_gettop(lua_state());
|
||||
int returncount = poststacksize - (firstreturn - 1);
|
||||
return protected_function_result(lua_state(), firstreturn, returncount, returncount, status());
|
||||
}
|
||||
|
||||
public:
|
||||
coroutine() noexcept = default;
|
||||
coroutine(const coroutine&) noexcept = default;
|
||||
coroutine& operator=(const coroutine&) noexcept = default;
|
||||
coroutine(lua_State* L, int index = -1) : reference(L, index) {
|
||||
public:
|
||||
coroutine() noexcept = default;
|
||||
coroutine(const coroutine&) noexcept = default;
|
||||
coroutine& operator=(const coroutine&) noexcept = default;
|
||||
coroutine(lua_State* L, int index = -1) : reference(L, index) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
stack::check<coroutine>(L, index, type_panic);
|
||||
stack::check<coroutine>(L, index, type_panic);
|
||||
#endif // Safety
|
||||
}
|
||||
}
|
||||
|
||||
call_status status() const noexcept {
|
||||
return stats;
|
||||
}
|
||||
call_status status() const noexcept {
|
||||
return stats;
|
||||
}
|
||||
|
||||
bool error() const noexcept {
|
||||
call_status cs = status();
|
||||
return cs != call_status::ok && cs != call_status::yielded;
|
||||
}
|
||||
bool error() const noexcept {
|
||||
call_status cs = status();
|
||||
return cs != call_status::ok && cs != call_status::yielded;
|
||||
}
|
||||
|
||||
bool runnable () const noexcept {
|
||||
return valid()
|
||||
&& (status() == call_status::yielded);
|
||||
}
|
||||
bool runnable() const noexcept {
|
||||
return valid()
|
||||
&& (status() == call_status::yielded);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return runnable();
|
||||
}
|
||||
explicit operator bool() const noexcept {
|
||||
return runnable();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
protected_function_result operator()( Args&&... args ) {
|
||||
return call<>( std::forward<Args>( args )... );
|
||||
}
|
||||
template<typename... Args>
|
||||
protected_function_result operator()(Args&&... args) {
|
||||
return call<>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) operator()( types<Ret...>, Args&&... args ) {
|
||||
return call<Ret...>( std::forward<Args>( args )... );
|
||||
}
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) operator()(types<Ret...>, Args&&... args) {
|
||||
return call<Ret...>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call(Args&&... args) {
|
||||
push();
|
||||
int pushcount = stack::multi_push(lua_state(), std::forward<Args>(args)...);
|
||||
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount);
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call( Args&&... args ) {
|
||||
push();
|
||||
int pushcount = stack::multi_push( lua_state(), std::forward<Args>( args )... );
|
||||
return invoke( types<Ret...>( ), std::make_index_sequence<sizeof...(Ret)>(), pushcount );
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // SOL_COUROUTINE_HPP
|
||||
|
|
|
@ -26,29 +26,29 @@
|
|||
#include <iostream>
|
||||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
namespace debug {
|
||||
inline std::string dump_types(lua_State* L) {
|
||||
std::string visual;
|
||||
std::size_t size = lua_gettop(L) + 1;
|
||||
for(std::size_t i = 1; i < size; ++i) {
|
||||
if(i != 1) {
|
||||
visual += " | ";
|
||||
}
|
||||
visual += type_name(L, stack::get<type>(L, static_cast<int>(i)));
|
||||
}
|
||||
return visual;
|
||||
}
|
||||
namespace detail {
|
||||
namespace debug {
|
||||
inline std::string dump_types(lua_State* L) {
|
||||
std::string visual;
|
||||
std::size_t size = lua_gettop(L) + 1;
|
||||
for (std::size_t i = 1; i < size; ++i) {
|
||||
if (i != 1) {
|
||||
visual += " | ";
|
||||
}
|
||||
visual += type_name(L, stack::get<type>(L, static_cast<int>(i)));
|
||||
}
|
||||
return visual;
|
||||
}
|
||||
|
||||
inline void print_stack(lua_State* L) {
|
||||
std::cout << dump_types(L) << std::endl;
|
||||
}
|
||||
inline void print_stack(lua_State* L) {
|
||||
std::cout << dump_types(L) << std::endl;
|
||||
}
|
||||
|
||||
inline void print_section(const std::string& message, lua_State* L) {
|
||||
std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl;
|
||||
}
|
||||
} // detail
|
||||
} // debug
|
||||
inline void print_section(const std::string& message, lua_State* L) {
|
||||
std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl;
|
||||
}
|
||||
} // detail
|
||||
} // debug
|
||||
} // sol
|
||||
|
||||
#endif // SOL_DEBUG_HPP
|
||||
|
|
192
sol/demangle.hpp
192
sol/demangle.hpp
|
@ -32,121 +32,121 @@
|
|||
#endif
|
||||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
#ifdef _MSC_VER
|
||||
#ifndef SOL_NO_RTTI
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
std::string realname = id.name();
|
||||
const static std::array<std::string, 2> removals = { { "struct ", "class " } };
|
||||
for (std::size_t r = 0; r < removals.size(); ++r) {
|
||||
auto found = realname.find(removals[r]);
|
||||
while (found != std::string::npos) {
|
||||
realname.erase(found, removals[r].size());
|
||||
found = realname.find(removals[r]);
|
||||
}
|
||||
}
|
||||
return realname;
|
||||
}
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
std::string realname = id.name();
|
||||
const static std::array<std::string, 2> removals = { { "struct ", "class " } };
|
||||
for (std::size_t r = 0; r < removals.size(); ++r) {
|
||||
auto found = realname.find(removals[r]);
|
||||
while (found != std::string::npos) {
|
||||
realname.erase(found, removals[r].size());
|
||||
found = realname.find(removals[r]);
|
||||
}
|
||||
}
|
||||
return realname;
|
||||
}
|
||||
#endif // No RTII
|
||||
template <typename T>
|
||||
inline std::string ctti_get_type_name() {
|
||||
std::string name = __FUNCSIG__;
|
||||
std::size_t start = name.find("get_type_name");
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
else
|
||||
start += 13;
|
||||
if (start < name.size() - 1)
|
||||
start += 1;
|
||||
std::size_t end = name.find_last_of('>');
|
||||
if (end == std::string::npos)
|
||||
end = name.size();
|
||||
name = name.substr(start, end - start);
|
||||
if (name.find("struct", 0) == 0)
|
||||
name.replace(0, 6, "", 0);
|
||||
if (name.find("class", 0) == 0)
|
||||
name.replace(0, 5, "", 0);
|
||||
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin());
|
||||
while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end());
|
||||
return name;
|
||||
}
|
||||
template <typename T>
|
||||
inline std::string ctti_get_type_name() {
|
||||
std::string name = __FUNCSIG__;
|
||||
std::size_t start = name.find("get_type_name");
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
else
|
||||
start += 13;
|
||||
if (start < name.size() - 1)
|
||||
start += 1;
|
||||
std::size_t end = name.find_last_of('>');
|
||||
if (end == std::string::npos)
|
||||
end = name.size();
|
||||
name = name.substr(start, end - start);
|
||||
if (name.find("struct", 0) == 0)
|
||||
name.replace(0, 6, "", 0);
|
||||
if (name.find("class", 0) == 0)
|
||||
name.replace(0, 5, "", 0);
|
||||
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin());
|
||||
while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end());
|
||||
return name;
|
||||
}
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
template <typename T>
|
||||
inline std::string ctti_get_type_name() {
|
||||
std::string name = __PRETTY_FUNCTION__;
|
||||
std::size_t start = name.find_last_of('[');
|
||||
start = name.find_first_of('=', start);
|
||||
std::size_t end = name.find_last_of(']');
|
||||
if (end == std::string::npos)
|
||||
end = name.size();
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
if (start < name.size() - 1)
|
||||
start += 1;
|
||||
name = name.substr(start, end - start);
|
||||
start = name.find(";");
|
||||
if (start != std::string::npos) {
|
||||
name.erase(start, name.length());
|
||||
}
|
||||
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin());
|
||||
while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end());
|
||||
return name;
|
||||
}
|
||||
template <typename T>
|
||||
inline std::string ctti_get_type_name() {
|
||||
std::string name = __PRETTY_FUNCTION__;
|
||||
std::size_t start = name.find_last_of('[');
|
||||
start = name.find_first_of('=', start);
|
||||
std::size_t end = name.find_last_of(']');
|
||||
if (end == std::string::npos)
|
||||
end = name.size();
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
if (start < name.size() - 1)
|
||||
start += 1;
|
||||
name = name.substr(start, end - start);
|
||||
start = name.find(";");
|
||||
if (start != std::string::npos) {
|
||||
name.erase(start, name.length());
|
||||
}
|
||||
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin());
|
||||
while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end());
|
||||
return name;
|
||||
}
|
||||
#ifndef SOL_NO_RTTI
|
||||
#if defined(__clang__)
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
int status;
|
||||
char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status);
|
||||
std::string realname = unmangled;
|
||||
std::free(unmangled);
|
||||
return realname;
|
||||
}
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
int status;
|
||||
char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status);
|
||||
std::string realname = unmangled;
|
||||
std::free(unmangled);
|
||||
return realname;
|
||||
}
|
||||
#elif defined(__GNUC__)
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
int status;
|
||||
char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status);
|
||||
std::string realname = unmangled;
|
||||
std::free(unmangled);
|
||||
return realname;
|
||||
}
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
int status;
|
||||
char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status);
|
||||
std::string realname = unmangled;
|
||||
std::free(unmangled);
|
||||
return realname;
|
||||
}
|
||||
#endif // g++ || clang++
|
||||
#endif // No RTII
|
||||
#else
|
||||
#error Compiler not supported for demangling
|
||||
#endif // compilers
|
||||
|
||||
template <typename T>
|
||||
inline std::string demangle_once() {
|
||||
template <typename T>
|
||||
inline std::string demangle_once() {
|
||||
#ifndef SOL_NO_RTTI
|
||||
std::string realname = get_type_name(typeid(T));
|
||||
std::string realname = get_type_name(typeid(T));
|
||||
#else
|
||||
std::string realname = ctti_get_type_name<T>();
|
||||
std::string realname = ctti_get_type_name<T>();
|
||||
#endif // No Runtime Type Information
|
||||
return realname;
|
||||
}
|
||||
return realname;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string short_demangle_once() {
|
||||
std::string realname = ctti_get_type_name<T>();
|
||||
std::size_t idx = realname.find_last_of(":`'\"{}[]|-)(*^&!@#$%`~", std::string::npos, 23);
|
||||
if (idx != std::string::npos) {
|
||||
realname.erase(0, realname.length() < idx ? realname.length() : idx + 1);
|
||||
}
|
||||
return realname;
|
||||
}
|
||||
template <typename T>
|
||||
inline std::string short_demangle_once() {
|
||||
std::string realname = ctti_get_type_name<T>();
|
||||
std::size_t idx = realname.find_last_of(":`'\"{}[]|-)(*^&!@#$%`~", std::string::npos, 23);
|
||||
if (idx != std::string::npos) {
|
||||
realname.erase(0, realname.length() < idx ? realname.length() : idx + 1);
|
||||
}
|
||||
return realname;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string demangle() {
|
||||
static const std::string d = demangle_once<T>();
|
||||
return d;
|
||||
}
|
||||
template <typename T>
|
||||
inline std::string demangle() {
|
||||
static const std::string d = demangle_once<T>();
|
||||
return d;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string short_demangle() {
|
||||
static const std::string d = short_demangle_once<T>();
|
||||
return d;
|
||||
}
|
||||
} // detail
|
||||
template <typename T>
|
||||
inline std::string short_demangle() {
|
||||
static const std::string d = short_demangle_once<T>();
|
||||
return d;
|
||||
}
|
||||
} // detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_DEMANGLE_HPP
|
||||
|
|
|
@ -33,12 +33,15 @@
|
|||
#endif // SOL_DEPRECATED
|
||||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct SOL_DEPRECATED deprecate_type {
|
||||
using type = T;
|
||||
};
|
||||
} // detail
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct SOL_DEPRECATED deprecate_type {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using deprecate_type_t = typename deprecate_type<T>::type;
|
||||
} // detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_DEPRECATE_HPP
|
||||
|
|
|
@ -26,28 +26,30 @@
|
|||
#include <string>
|
||||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
struct direct_error_tag {};
|
||||
const auto direct_error = direct_error_tag{};
|
||||
} // detail
|
||||
class error : public std::runtime_error {
|
||||
private:
|
||||
// Because VC++ is a fuccboi
|
||||
std::string w;
|
||||
public:
|
||||
error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {}
|
||||
error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {}
|
||||
error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {}
|
||||
namespace detail {
|
||||
struct direct_error_tag {};
|
||||
const auto direct_error = direct_error_tag{};
|
||||
} // detail
|
||||
|
||||
error(const error& e) = default;
|
||||
error(error&& e) = default;
|
||||
error& operator=(const error& e) = default;
|
||||
error& operator=(error&& e) = default;
|
||||
class error : public std::runtime_error {
|
||||
private:
|
||||
// Because VC++ is a fuccboi
|
||||
std::string w;
|
||||
public:
|
||||
error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {}
|
||||
error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {}
|
||||
error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {}
|
||||
|
||||
error(const error& e) = default;
|
||||
error(error&& e) = default;
|
||||
error& operator=(const error& e) = default;
|
||||
error& operator=(error&& e) = default;
|
||||
|
||||
virtual const char* what() const noexcept override {
|
||||
return w.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
virtual const char* what() const noexcept override {
|
||||
return w.c_str();
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
||||
#endif // SOL_ERROR_HPP
|
||||
|
|
170
sol/function.hpp
170
sol/function.hpp
|
@ -31,106 +31,106 @@
|
|||
#include <memory>
|
||||
|
||||
namespace sol {
|
||||
template <typename base_t>
|
||||
class basic_function : public base_t {
|
||||
private:
|
||||
void luacall( std::ptrdiff_t argcount, std::ptrdiff_t resultcount ) const {
|
||||
lua_callk( base_t::lua_state( ), static_cast<int>( argcount ), static_cast<int>( resultcount ), 0, nullptr );
|
||||
}
|
||||
template <typename base_t>
|
||||
class basic_function : public base_t {
|
||||
private:
|
||||
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const {
|
||||
lua_callk(base_t::lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), 0, nullptr);
|
||||
}
|
||||
|
||||
template<std::size_t... I, typename... Ret>
|
||||
auto invoke( types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n ) const {
|
||||
luacall( n, sizeof...( Ret ) );
|
||||
return stack::pop<std::tuple<Ret...>>( base_t::lua_state( ) );
|
||||
}
|
||||
template<std::size_t... I, typename... Ret>
|
||||
auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) const {
|
||||
luacall(n, sizeof...(Ret));
|
||||
return stack::pop<std::tuple<Ret...>>(base_t::lua_state());
|
||||
}
|
||||
|
||||
template<std::size_t I, typename Ret>
|
||||
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n ) const {
|
||||
luacall( n, 1 );
|
||||
return stack::pop<Ret>( base_t::lua_state( ) );
|
||||
}
|
||||
template<std::size_t I, typename Ret>
|
||||
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) const {
|
||||
luacall(n, 1);
|
||||
return stack::pop<Ret>(base_t::lua_state());
|
||||
}
|
||||
|
||||
template <std::size_t I>
|
||||
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const {
|
||||
luacall( n, 0 );
|
||||
}
|
||||
template <std::size_t I>
|
||||
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const {
|
||||
luacall(n, 0);
|
||||
}
|
||||
|
||||
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n ) const {
|
||||
int stacksize = lua_gettop( base_t::lua_state( ) );
|
||||
int firstreturn = (std::max)( 1, stacksize - static_cast<int>( n ) );
|
||||
luacall(n, LUA_MULTRET);
|
||||
int poststacksize = lua_gettop( base_t::lua_state( ) );
|
||||
int returncount = poststacksize - (firstreturn - 1);
|
||||
return function_result( base_t::lua_state( ), firstreturn, returncount );
|
||||
}
|
||||
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const {
|
||||
int stacksize = lua_gettop(base_t::lua_state());
|
||||
int firstreturn = (std::max)(1, stacksize - static_cast<int>(n));
|
||||
luacall(n, LUA_MULTRET);
|
||||
int poststacksize = lua_gettop(base_t::lua_state());
|
||||
int returncount = poststacksize - (firstreturn - 1);
|
||||
return function_result(base_t::lua_state(), firstreturn, returncount);
|
||||
}
|
||||
|
||||
public:
|
||||
basic_function() = default;
|
||||
basic_function(const basic_function&) = default;
|
||||
basic_function& operator=(const basic_function&) = default;
|
||||
basic_function(basic_function&&) = default;
|
||||
basic_function& operator=(basic_function&&) = default;
|
||||
basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {}
|
||||
basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {}
|
||||
basic_function(lua_State* L, int index = -1): base_t(L, index) {
|
||||
public:
|
||||
basic_function() = default;
|
||||
basic_function(const basic_function&) = default;
|
||||
basic_function& operator=(const basic_function&) = default;
|
||||
basic_function(basic_function&&) = default;
|
||||
basic_function& operator=(basic_function&&) = default;
|
||||
basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {}
|
||||
basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {}
|
||||
basic_function(lua_State* L, int index = -1) : base_t(L, index) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
stack::check<basic_function>(L, index, type_panic);
|
||||
stack::check<basic_function>(L, index, type_panic);
|
||||
#endif // Safety
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
function_result operator()( Args&&... args ) const {
|
||||
return call<>( std::forward<Args>( args )... );
|
||||
}
|
||||
template<typename... Args>
|
||||
function_result operator()(Args&&... args) const {
|
||||
return call<>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) operator()( types<Ret...>, Args&&... args ) const {
|
||||
return call<Ret...>( std::forward<Args>( args )... );
|
||||
}
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) operator()(types<Ret...>, Args&&... args) const {
|
||||
return call<Ret...>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call( Args&&... args ) const {
|
||||
base_t::push( );
|
||||
int pushcount = stack::multi_push_reference( base_t::lua_state( ), std::forward<Args>( args )... );
|
||||
return invoke( types<Ret...>( ), std::make_index_sequence<sizeof...(Ret)>(), pushcount );
|
||||
}
|
||||
};
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call(Args&&... args) const {
|
||||
base_t::push();
|
||||
int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward<Args>(args)...);
|
||||
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount);
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
template<typename Signature>
|
||||
struct getter<std::function<Signature>> {
|
||||
typedef meta::bind_traits<Signature> fx_t;
|
||||
typedef typename fx_t::args_list args_lists;
|
||||
typedef meta::tuple_types<typename fx_t::return_type> return_types;
|
||||
namespace stack {
|
||||
template<typename Signature>
|
||||
struct getter<std::function<Signature>> {
|
||||
typedef meta::bind_traits<Signature> fx_t;
|
||||
typedef typename fx_t::args_list args_lists;
|
||||
typedef meta::tuple_types<typename fx_t::return_type> return_types;
|
||||
|
||||
template<typename... Args, typename... Ret>
|
||||
static std::function<Signature> get_std_func(types<Ret...>, types<Args...>, lua_State* L, int index = -1) {
|
||||
sol::function f(L, index);
|
||||
auto fx = [f, L, index](Args&&... args) -> meta::return_type_t<Ret...> {
|
||||
return f.call<Ret...>(std::forward<Args>(args)...);
|
||||
};
|
||||
return std::move(fx);
|
||||
}
|
||||
template<typename... Args, typename... Ret>
|
||||
static std::function<Signature> get_std_func(types<Ret...>, types<Args...>, lua_State* L, int index = -1) {
|
||||
sol::function f(L, index);
|
||||
auto fx = [f, L, index](Args&&... args) -> meta::return_type_t<Ret...> {
|
||||
return f.call<Ret...>(std::forward<Args>(args)...);
|
||||
};
|
||||
return std::move(fx);
|
||||
}
|
||||
|
||||
template<typename... FxArgs>
|
||||
static std::function<Signature> get_std_func(types<void>, types<FxArgs...>, lua_State* L, int index = -1) {
|
||||
sol::function f(L, index);
|
||||
auto fx = [f, L, index](FxArgs&&... args) -> void {
|
||||
f(std::forward<FxArgs>(args)...);
|
||||
};
|
||||
return std::move(fx);
|
||||
}
|
||||
template<typename... FxArgs>
|
||||
static std::function<Signature> get_std_func(types<void>, types<FxArgs...>, lua_State* L, int index = -1) {
|
||||
sol::function f(L, index);
|
||||
auto fx = [f, L, index](FxArgs&&... args) -> void {
|
||||
f(std::forward<FxArgs>(args)...);
|
||||
};
|
||||
return std::move(fx);
|
||||
}
|
||||
|
||||
template<typename... FxArgs>
|
||||
static std::function<Signature> get_std_func(types<>, types<FxArgs...> t, lua_State* L, int index = -1) {
|
||||
return get_std_func(types<void>(), t, L, index);
|
||||
}
|
||||
template<typename... FxArgs>
|
||||
static std::function<Signature> get_std_func(types<>, types<FxArgs...> t, lua_State* L, int index = -1) {
|
||||
return get_std_func(types<void>(), t, L, index);
|
||||
}
|
||||
|
||||
static std::function<Signature> get(lua_State* L, int index) {
|
||||
return get_std_func(return_types(), args_lists(), L, index);
|
||||
}
|
||||
};
|
||||
} // stack
|
||||
static std::function<Signature> get(lua_State* L, int index) {
|
||||
return get_std_func(return_types(), args_lists(), L, index);
|
||||
}
|
||||
};
|
||||
} // stack
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_HPP
|
||||
|
|
|
@ -29,52 +29,52 @@
|
|||
#include <cstdint>
|
||||
|
||||
namespace sol {
|
||||
struct function_result : public proxy_base<function_result> {
|
||||
private:
|
||||
lua_State* L;
|
||||
int index;
|
||||
int returncount;
|
||||
struct function_result : public proxy_base<function_result> {
|
||||
private:
|
||||
lua_State* L;
|
||||
int index;
|
||||
int returncount;
|
||||
|
||||
public:
|
||||
function_result() = default;
|
||||
function_result(lua_State* L, int index = -1, int returncount = 0): L(L), index(index), returncount(returncount) {
|
||||
public:
|
||||
function_result() = default;
|
||||
function_result(lua_State* L, int index = -1, int returncount = 0) : L(L), index(index), returncount(returncount) {
|
||||
|
||||
}
|
||||
function_result(const function_result&) = default;
|
||||
function_result& operator=(const function_result&) = default;
|
||||
function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) {
|
||||
// Must be manual, otherwise destructor will screw us
|
||||
// return count being 0 is enough to keep things clean
|
||||
// but will be thorough
|
||||
o.L = nullptr;
|
||||
o.index = 0;
|
||||
o.returncount = 0;
|
||||
}
|
||||
function_result& operator=(function_result&& o) {
|
||||
L = o.L;
|
||||
index = o.index;
|
||||
returncount = o.returncount;
|
||||
// Must be manual, otherwise destructor will screw us
|
||||
// return count being 0 is enough to keep things clean
|
||||
// but will be thorough
|
||||
o.L = nullptr;
|
||||
o.index = 0;
|
||||
o.returncount = 0;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
function_result(const function_result&) = default;
|
||||
function_result& operator=(const function_result&) = default;
|
||||
function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) {
|
||||
// Must be manual, otherwise destructor will screw us
|
||||
// return count being 0 is enough to keep things clean
|
||||
// but will be thorough
|
||||
o.L = nullptr;
|
||||
o.index = 0;
|
||||
o.returncount = 0;
|
||||
}
|
||||
function_result& operator=(function_result&& o) {
|
||||
L = o.L;
|
||||
index = o.index;
|
||||
returncount = o.returncount;
|
||||
// Must be manual, otherwise destructor will screw us
|
||||
// return count being 0 is enough to keep things clean
|
||||
// but will be thorough
|
||||
o.L = nullptr;
|
||||
o.index = 0;
|
||||
o.returncount = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
decltype(auto) get() const {
|
||||
return stack::get<T>(L, index);
|
||||
}
|
||||
template<typename T>
|
||||
decltype(auto) get() const {
|
||||
return stack::get<T>(L, index);
|
||||
}
|
||||
|
||||
lua_State* lua_state() const { return L; };
|
||||
int stack_index() const { return index; };
|
||||
lua_State* lua_state() const { return L; };
|
||||
int stack_index() const { return index; };
|
||||
|
||||
~function_result() {
|
||||
lua_pop(L, returncount);
|
||||
}
|
||||
};
|
||||
~function_result() {
|
||||
lua_pop(L, returncount);
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_RESULT_HPP
|
||||
|
|
|
@ -31,217 +31,217 @@
|
|||
#include "call.hpp"
|
||||
|
||||
namespace sol {
|
||||
template <typename Sig, typename... Ps>
|
||||
struct function_arguments {
|
||||
std::tuple<Ps...> params;
|
||||
template <typename... Args>
|
||||
function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
|
||||
};
|
||||
template <typename Sig, typename... Ps>
|
||||
struct function_arguments {
|
||||
std::tuple<Ps...> params;
|
||||
template <typename... Args>
|
||||
function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
|
||||
};
|
||||
|
||||
template <typename Sig = function_sig<>, typename... Args>
|
||||
function_arguments<Sig, Args...> function_args( Args&&... args ) {
|
||||
return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Sig = function_sig<>, typename... Args>
|
||||
function_arguments<Sig, Args...> function_args(Args&&... args) {
|
||||
return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
namespace stack {
|
||||
template<typename... Sigs>
|
||||
struct pusher<function_sig<Sigs...>> {
|
||||
template <typename... Sig, typename Fx, typename... Args>
|
||||
static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::functor_function<clean_fx>>(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
set_fx(L, std::move(sptr));
|
||||
}
|
||||
namespace stack {
|
||||
template<typename... Sigs>
|
||||
struct pusher<function_sig<Sigs...>> {
|
||||
template <typename... Sig, typename Fx, typename... Args>
|
||||
static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::functor_function<clean_fx>>(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
set_fx(L, std::move(sptr));
|
||||
}
|
||||
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
using fx_ptr_t = R(*)(A...);
|
||||
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
||||
select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
using fx_ptr_t = R(*)(A...);
|
||||
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
|
||||
select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::decay_t<meta::unwrapped_t<meta::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_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename R, typename... A, typename Fx, typename... Args>
|
||||
static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef std::decay_t<meta::unwrapped_t<meta::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_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef meta::function_signature_t<meta::unwrapped_t<meta::unqualified_t<Fx>>> Sig;
|
||||
select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
typedef meta::function_signature_t<meta::unwrapped_t<meta::unqualified_t<Fx>>> Sig;
|
||||
select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_variable<meta::unqualified_t<T>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
|
||||
set_fx(L, std::move(sptr));
|
||||
}
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_variable<meta::unqualified_t<T>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
set_fx(L, std::move(sptr));
|
||||
}
|
||||
|
||||
template <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>>::call;
|
||||
template <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>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
template <typename Fx>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <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::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_function<meta::unwrapped_t<meta::unqualified_t<T>>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
|
||||
set_fx(L, std::move(sptr));
|
||||
}
|
||||
template <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::remove_pointer_t<std::decay_t<Fx>> clean_fx;
|
||||
std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_function<meta::unwrapped_t<meta::unqualified_t<T>>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
set_fx(L, std::move(sptr));
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_function(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_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_reference_member_function(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_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
template <typename Fx>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_function(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_member_function(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call;
|
||||
template <typename Fx, typename... Args>
|
||||
static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
|
||||
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, target);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, target);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
|
||||
stack::push(L, f);
|
||||
}
|
||||
static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
|
||||
stack::push(L, f);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static void select(lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Fx, typename... Args>
|
||||
static void select(lua_State* L, Fx&& fx, Args&&... args) {
|
||||
select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static void set_fx(lua_State* L, std::unique_ptr<function_detail::base_function> luafunc) {
|
||||
function_detail::base_function* target = luafunc.release();
|
||||
void* targetdata = static_cast<void*>(target);
|
||||
lua_CFunction freefunc = function_detail::call;
|
||||
static void set_fx(lua_State* L, std::unique_ptr<function_detail::base_function> luafunc) {
|
||||
function_detail::base_function* target = luafunc.release();
|
||||
void* targetdata = static_cast<void*>(target);
|
||||
lua_CFunction freefunc = function_detail::call;
|
||||
|
||||
stack::push(L, userdata_value(targetdata));
|
||||
function_detail::free_function_cleanup(L);
|
||||
lua_setmetatable(L, -2);
|
||||
stack::push(L, c_closure(freefunc, 1));
|
||||
}
|
||||
stack::push(L, userdata_value(targetdata));
|
||||
function_detail::free_function_cleanup(L);
|
||||
lua_setmetatable(L, -2);
|
||||
stack::push(L, c_closure(freefunc, 1));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
// Set will always place one thing (function) on the stack
|
||||
select(L, std::forward<Args>(args)...);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
template<typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
// Set will always place one thing (function) on the stack
|
||||
select(L, std::forward<Args>(args)...);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct pusher<function_arguments<T, Args...>> {
|
||||
template <std::size_t... I, typename FP>
|
||||
static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
|
||||
return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
|
||||
}
|
||||
template<typename T, typename... Args>
|
||||
struct pusher<function_arguments<T, Args...>> {
|
||||
template <std::size_t... I, typename FP>
|
||||
static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
|
||||
return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
|
||||
}
|
||||
|
||||
template <typename FP>
|
||||
static int push(lua_State* L, FP&& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<FP>(fp));
|
||||
}
|
||||
};
|
||||
template <typename FP>
|
||||
static int push(lua_State* L, FP&& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<FP>(fp));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<std::function<Signature>> {
|
||||
static int push(lua_State* L, std::function<Signature> fx) {
|
||||
return pusher<function_sig<Signature>>{}.push(L, std::move(fx));
|
||||
}
|
||||
};
|
||||
template<typename Signature>
|
||||
struct pusher<std::function<Signature>> {
|
||||
static int push(lua_State* L, std::function<Signature> fx) {
|
||||
return pusher<function_sig<Signature>>{}.push(L, std::move(fx));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> {
|
||||
template <typename F>
|
||||
static int push(lua_State* L, F&& f) {
|
||||
return pusher<function_sig<>>{}.push(L, std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Functions>
|
||||
struct pusher<overload_set<Functions...>> {
|
||||
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
||||
pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(std::move(set.set)));
|
||||
return 1;
|
||||
}
|
||||
template<typename... Functions>
|
||||
struct pusher<overload_set<Functions...>> {
|
||||
static int push(lua_State* L, overload_set<Functions...>&& set) {
|
||||
pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(std::move(set.set)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
||||
pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(set.set));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
static int push(lua_State* L, const overload_set<Functions...>& set) {
|
||||
pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(set.set));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
} // stack
|
||||
} // stack
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_TYPES_HPP
|
||||
|
|
|
@ -25,178 +25,178 @@
|
|||
#include "stack.hpp"
|
||||
|
||||
namespace sol {
|
||||
namespace function_detail {
|
||||
template<typename Function>
|
||||
struct upvalue_free_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
namespace function_detail {
|
||||
template<typename Function>
|
||||
struct upvalue_free_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
|
||||
static int real_call(lua_State* L) {
|
||||
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
|
||||
function_type* fx = udata.first;
|
||||
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||
return r;
|
||||
}
|
||||
static int real_call(lua_State* L) {
|
||||
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
|
||||
function_type* fx = udata.first;
|
||||
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int call (lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
static int call(lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_member_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_member_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member function pointer
|
||||
// idx n + 1: is the object's void pointer
|
||||
// We don't need to store the size, because the other side is templated
|
||||
// with the same member function pointer type
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
|
||||
function_type& memfx = memberdata.first;
|
||||
auto& item = *objdata.first;
|
||||
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||
}
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member function pointer
|
||||
// idx n + 1: is the object's void pointer
|
||||
// We don't need to store the size, because the other side is templated
|
||||
// with the same member function pointer type
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
|
||||
function_type& memfx = memberdata.first;
|
||||
auto& item = *objdata.first;
|
||||
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||
}
|
||||
|
||||
static int call (lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
static int call(lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_assignable(std::false_type, lua_State* L, M&, V&) {
|
||||
lua_pop(L, N);
|
||||
return luaL_error(L, "sol: cannot write to this type: copy assignment/constructor not available");
|
||||
}
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_assignable(std::false_type, lua_State* L, M&, V&) {
|
||||
lua_pop(L, N);
|
||||
return luaL_error(L, "sol: cannot write to this type: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_assignable(std::true_type, lua_State* L, M& mem, V& var) {
|
||||
(mem.*var) = stack::get<R>(L, N);
|
||||
lua_pop(L, N);
|
||||
return 0;
|
||||
}
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_assignable(std::true_type, lua_State* L, M& mem, V& var) {
|
||||
(mem.*var) = stack::get<R>(L, N);
|
||||
lua_pop(L, N);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_variable(std::true_type, lua_State* L, M& mem, V& var) {
|
||||
return set_assignable<N, R>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, mem, var);
|
||||
}
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_variable(std::true_type, lua_State* L, M& mem, V& var) {
|
||||
return set_assignable<N, R>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, mem, var);
|
||||
}
|
||||
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_variable(std::false_type, lua_State* L, M&, V&) {
|
||||
lua_pop(L, N);
|
||||
return luaL_error(L, "sol: cannot write to a const variable");
|
||||
}
|
||||
template <int N, typename R, typename M, typename V>
|
||||
int set_variable(std::false_type, lua_State* L, M&, V&) {
|
||||
lua_pop(L, N);
|
||||
return luaL_error(L, "sol: cannot write to a const variable");
|
||||
}
|
||||
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_member_variable {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_member_variable {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
// idx n + 1: is the object's void pointer
|
||||
// We don't need to store the size, because the other side is templated
|
||||
// with the same member function pointer type
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
|
||||
auto& mem = *objdata.first;
|
||||
function_type& var = memberdata.first;
|
||||
switch (lua_gettop(L)) {
|
||||
case 0:
|
||||
stack::push(L, (mem.*var));
|
||||
return 1;
|
||||
case 1:
|
||||
set_variable<1, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
|
||||
return 0;
|
||||
default:
|
||||
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
|
||||
}
|
||||
}
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
// idx n + 1: is the object's void pointer
|
||||
// We don't need to store the size, because the other side is templated
|
||||
// with the same member function pointer type
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
|
||||
auto& mem = *objdata.first;
|
||||
function_type& var = memberdata.first;
|
||||
switch (lua_gettop(L)) {
|
||||
case 0:
|
||||
stack::push(L, (mem.*var));
|
||||
return 1;
|
||||
case 1:
|
||||
set_variable<1, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
|
||||
return 0;
|
||||
default:
|
||||
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
|
||||
}
|
||||
}
|
||||
|
||||
static int call (lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
static int call(lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_this_member_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_this_member_function {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
function_type& memfx = memberdata.first;
|
||||
auto fx = [&L, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||
auto& item = stack::get<T>(L, 1);
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
int n = stack::call_into_lua<1>(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 2, fx);
|
||||
return n;
|
||||
}
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
function_type& memfx = memberdata.first;
|
||||
auto fx = [&L, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||
auto& item = stack::get<T>(L, 1);
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
int n = stack::call_into_lua<1>(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 2, fx);
|
||||
return n;
|
||||
}
|
||||
|
||||
static int call (lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
static int call(lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_this_member_variable {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
template<typename T, typename Function>
|
||||
struct upvalue_this_member_variable {
|
||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||
typedef lua_bind_traits<function_type> traits_type;
|
||||
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto& mem = stack::get<T>(L, 1);
|
||||
function_type& var = memberdata.first;
|
||||
switch (lua_gettop(L)) {
|
||||
case 1:
|
||||
lua_pop(L, 1);
|
||||
stack::push(L, (mem.*var));
|
||||
return 1;
|
||||
case 2:
|
||||
set_variable<2, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
|
||||
return 0;
|
||||
default:
|
||||
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
|
||||
}
|
||||
}
|
||||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto& mem = stack::get<T>(L, 1);
|
||||
function_type& var = memberdata.first;
|
||||
switch (lua_gettop(L)) {
|
||||
case 1:
|
||||
lua_pop(L, 1);
|
||||
stack::push(L, (mem.*var));
|
||||
return 1;
|
||||
case 2:
|
||||
set_variable<2, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
|
||||
return 0;
|
||||
default:
|
||||
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
|
||||
}
|
||||
}
|
||||
|
||||
static int call (lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
static int call(lua_State* L) {
|
||||
return detail::static_trampoline<(&real_call)>(L);
|
||||
}
|
||||
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
} // function_detail
|
||||
int operator()(lua_State* L) {
|
||||
return call(L);
|
||||
}
|
||||
};
|
||||
} // function_detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_TYPES_BASIC_HPP
|
||||
|
|
|
@ -27,91 +27,91 @@
|
|||
#include <memory>
|
||||
|
||||
namespace sol {
|
||||
namespace function_detail {
|
||||
inline decltype(auto) cleanup_key() {
|
||||
const auto& name = u8"sol.ƒ.♲.🗑.(/¯◡ ‿ ◡)/¯ ~ ┻━┻ (ノ◕ヮ◕)ノ*:・゚✧";
|
||||
return name;
|
||||
}
|
||||
namespace function_detail {
|
||||
inline decltype(auto) cleanup_key() {
|
||||
const auto& name = u8"sol.ƒ.♲.🗑.(/¯◡ ‿ ◡)/¯ ~ ┻━┻ (ノ◕ヮ◕)ノ*:・゚✧";
|
||||
return name;
|
||||
}
|
||||
|
||||
struct base_function {
|
||||
virtual int operator()(lua_State* L) {
|
||||
return luaL_error(L, "sol: failure to call specialized wrapped C++ function from Lua");
|
||||
}
|
||||
struct base_function {
|
||||
virtual int operator()(lua_State* L) {
|
||||
return luaL_error(L, "sol: failure to call specialized wrapped C++ function from Lua");
|
||||
}
|
||||
|
||||
virtual ~base_function() {}
|
||||
};
|
||||
virtual ~base_function() {}
|
||||
};
|
||||
|
||||
static int base_call(lua_State* L, void* inheritancedata) {
|
||||
if (inheritancedata == nullptr) {
|
||||
return luaL_error(L, "sol: call from Lua to C++ function has null data");
|
||||
}
|
||||
static int base_call(lua_State* L, void* inheritancedata) {
|
||||
if (inheritancedata == nullptr) {
|
||||
return luaL_error(L, "sol: call from Lua to C++ function has null data");
|
||||
}
|
||||
|
||||
base_function* pfx = static_cast<base_function*>(inheritancedata);
|
||||
base_function& fx = *pfx;
|
||||
return detail::trampoline(L, fx);
|
||||
}
|
||||
base_function* pfx = static_cast<base_function*>(inheritancedata);
|
||||
base_function& fx = *pfx;
|
||||
return detail::trampoline(L, fx);
|
||||
}
|
||||
|
||||
static int base_gc(lua_State* L, void* udata) {
|
||||
if (udata == nullptr) {
|
||||
return luaL_error(L, "sol: call from lua to C++ gc function with null data");
|
||||
}
|
||||
static int base_gc(lua_State* L, void* udata) {
|
||||
if (udata == nullptr) {
|
||||
return luaL_error(L, "sol: call from lua to C++ gc function with null data");
|
||||
}
|
||||
|
||||
base_function* ptr = static_cast<base_function*>(udata);
|
||||
std::default_delete<base_function> dx{};
|
||||
dx(ptr);
|
||||
return 0;
|
||||
}
|
||||
base_function* ptr = static_cast<base_function*>(udata);
|
||||
std::default_delete<base_function> dx{};
|
||||
dx(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <std::size_t limit>
|
||||
static void func_gc(std::true_type, lua_State*) {
|
||||
template <std::size_t limit>
|
||||
static void func_gc(std::true_type, lua_State*) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t limit>
|
||||
static void func_gc(std::false_type, lua_State* L) {
|
||||
for (std::size_t i = 0; i < limit; ++i) {
|
||||
void* value = stack::get<lightuserdata_value>(L, up_value_index(static_cast<int>(i + 1)));
|
||||
if (value == nullptr)
|
||||
continue;
|
||||
base_function* obj = static_cast<base_function*>(value);
|
||||
std::allocator<base_function> alloc{};
|
||||
alloc.destroy(obj);
|
||||
alloc.deallocate(obj, 1);
|
||||
}
|
||||
}
|
||||
template <std::size_t limit>
|
||||
static void func_gc(std::false_type, lua_State* L) {
|
||||
for (std::size_t i = 0; i < limit; ++i) {
|
||||
void* value = stack::get<lightuserdata_value>(L, up_value_index(static_cast<int>(i + 1)));
|
||||
if (value == nullptr)
|
||||
continue;
|
||||
base_function* obj = static_cast<base_function*>(value);
|
||||
std::allocator<base_function> alloc{};
|
||||
alloc.destroy(obj);
|
||||
alloc.deallocate(obj, 1);
|
||||
}
|
||||
}
|
||||
|
||||
inline int call(lua_State* L) {
|
||||
void* ludata = stack::get<lightuserdata_value>(L, up_value_index(1));
|
||||
void** pinheritancedata = static_cast<void**>(ludata);
|
||||
return base_call(L, *pinheritancedata);
|
||||
}
|
||||
inline int call(lua_State* L) {
|
||||
void* ludata = stack::get<lightuserdata_value>(L, up_value_index(1));
|
||||
void** pinheritancedata = static_cast<void**>(ludata);
|
||||
return base_call(L, *pinheritancedata);
|
||||
}
|
||||
|
||||
inline int gc(lua_State* L) {
|
||||
void* udata = stack::get<userdata_value>(L, 1);
|
||||
void** pudata = static_cast<void**>(udata);
|
||||
return base_gc(L, *pudata);
|
||||
}
|
||||
inline int gc(lua_State* L) {
|
||||
void* udata = stack::get<userdata_value>(L, 1);
|
||||
void** pudata = static_cast<void**>(udata);
|
||||
return base_gc(L, *pudata);
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
inline int usertype_call(lua_State* L) {
|
||||
// Zero-based template parameter, but upvalues start at 1
|
||||
return base_call(L, stack::get<lightuserdata_value>(L, up_value_index(static_cast<int>(I + 1))));
|
||||
}
|
||||
template<std::size_t I>
|
||||
inline int usertype_call(lua_State* L) {
|
||||
// Zero-based template parameter, but upvalues start at 1
|
||||
return base_call(L, stack::get<lightuserdata_value>(L, up_value_index(static_cast<int>(I + 1))));
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
inline int usertype_gc(lua_State* L) {
|
||||
func_gc<I>(meta::boolean<(I < 1)>(), L);
|
||||
return 0;
|
||||
}
|
||||
template<std::size_t I>
|
||||
inline int usertype_gc(lua_State* L) {
|
||||
func_gc<I>(meta::boolean<(I < 1)>(), L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void free_function_cleanup(lua_State* L) {
|
||||
const static char* metatablename = &cleanup_key()[0];
|
||||
int metapushed = luaL_newmetatable(L, metatablename);
|
||||
if (metapushed == 1) {
|
||||
stack::set_field(L, "__gc", function_detail::gc);
|
||||
}
|
||||
}
|
||||
} // function_detail
|
||||
inline void free_function_cleanup(lua_State* L) {
|
||||
const static char* metatablename = &cleanup_key()[0];
|
||||
int metapushed = luaL_newmetatable(L, metatablename);
|
||||
if (metapushed == 1) {
|
||||
stack::set_field(L, "__gc", function_detail::gc);
|
||||
}
|
||||
}
|
||||
} // function_detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_TYPES_CORE_HPP
|
||||
|
|
|
@ -27,33 +27,33 @@
|
|||
#include "function_types_core.hpp"
|
||||
|
||||
namespace sol {
|
||||
namespace function_detail {
|
||||
template <typename... Functions>
|
||||
struct overloaded_function : base_function {
|
||||
typedef std::tuple<Functions...> overload_list;
|
||||
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
||||
overload_list overloads;
|
||||
namespace function_detail {
|
||||
template <typename... Functions>
|
||||
struct overloaded_function : base_function {
|
||||
typedef std::tuple<Functions...> overload_list;
|
||||
typedef std::make_index_sequence<sizeof...(Functions)> indices;
|
||||
overload_list overloads;
|
||||
|
||||
overloaded_function(overload_list set)
|
||||
: overloads(std::move(set)) {}
|
||||
overloaded_function(overload_list set)
|
||||
: overloads(std::move(set)) {}
|
||||
|
||||
overloaded_function(Functions... fxs)
|
||||
: overloads(fxs...) {
|
||||
overloaded_function(Functions... fxs)
|
||||
: overloads(fxs...) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
auto& func = std::get<I>(overloads);
|
||||
return stack::call_into_lua<0, false>(r, a, L, start, func);
|
||||
}
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
auto& func = std::get<I>(overloads);
|
||||
return stack::call_into_lua<0, false>(r, a, L, start, func);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
auto mfx = [&](auto&&... args){ return this->call(std::forward<decltype(args)>(args)...); };
|
||||
return call_detail::overload_match<Functions...>(mfx, L, 1);
|
||||
}
|
||||
};
|
||||
} // function_detail
|
||||
virtual int operator()(lua_State* L) override {
|
||||
auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); };
|
||||
return call_detail::overload_match<Functions...>(mfx, L, 1);
|
||||
}
|
||||
};
|
||||
} // function_detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_TYPES_OVERLOAD_HPP
|
|
@ -142,13 +142,13 @@ namespace sol {
|
|||
int make_regs(regs_t& l, int index, sol::call_construction, F&&, Args&&... args) {
|
||||
callconstructfunc = call<I + 1>;
|
||||
secondarymeta = true;
|
||||
int endindex = make_regs<I + 2>(l, index + 1, std::forward<Args>(args)...);
|
||||
int endindex = make_regs<I + 2>(l, index, std::forward<Args>(args)...);
|
||||
return endindex;
|
||||
}
|
||||
|
||||
template <std::size_t I = 0, typename... Bases, typename... Args>
|
||||
int make_regs(regs_t& l, int index, base_classes_tag, bases<Bases...>, Args&&... args) {
|
||||
int endindex = make_regs<I + 2>(l, index + 1, std::forward<Args>(args)...);
|
||||
int endindex = make_regs<I + 2>(l, index, std::forward<Args>(args)...);
|
||||
if (sizeof...(Bases) < 1) {
|
||||
(void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = false), 0)... };
|
||||
return endindex;
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
#include <sol.hpp>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include "test_stack_guard.hpp"
|
||||
|
||||
std::string free_function() {
|
||||
|
@ -531,3 +535,21 @@ TEST_CASE("tables/operator[]-optional", "Test if proxies on tables can lazily ev
|
|||
REQUIRE(non_nope3.value() == 35);
|
||||
REQUIRE(non_nope4.value() == 35);
|
||||
}
|
||||
|
||||
TEST_CASE("tables/add", "Basic test to make sure the 'add' feature works") {
|
||||
static const int sz = 120;
|
||||
|
||||
sol::state lua;
|
||||
sol::table t = lua.create_table(sz, 0);
|
||||
|
||||
std::vector<int> bigvec( sz );
|
||||
std::iota(bigvec.begin(), bigvec.end(), 1);
|
||||
|
||||
for (std::size_t i = 0; i < bigvec.size(); ++i) {
|
||||
t.add(bigvec[i]);
|
||||
}
|
||||
for (std::size_t i = 0; i < bigvec.size(); ++i) {
|
||||
int val = t[i + 1];
|
||||
REQUIRE(val == bigvec[i]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user