Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes by @qweasdd136963 #13

Merged
merged 3 commits into from
Sep 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions luabind/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,18 @@
// C code has undefined behavior, lua is written in C).

// LUABIND_XRAY_NO_BACKWARDS_COMPATIBILITY
// In VS2015: Go to Property Manager -> Common.props -> C\C++ -> Preprocessor to turn it on\off
// In VS2017: Go to Property Manager -> Common.props -> C\C++ -> Preprocessor to turn it on\off
// this define will turn OFF some code for backward compability with some original .lua-code
// from XRay 1.6 Engine, like:
// - native converter from number to string\char*

// XRAY_SCRIPTS_NO_BACKWARDS_COMPATIBILITY
// In VS2017: Go to Property Manager -> Common.props -> C\C++ -> Preprocessor to turn it on\off
// this define will turn OFF some code for backward compability with some original .lua-code
// from XRay 1.6 Engine, like:
// - original script behaviour when you didn't pass some parametres
// - turn off "LUA error: cannot cast lua value to ..."

#ifdef LUABIND_DYNAMIC_LINK
# if defined (_WIN32)
# ifdef LUABIND_BUILDING
Expand Down Expand Up @@ -114,9 +121,6 @@
#define _FARQ
#endif // _FARQ

// This switches between using tag arguments / structure specialization for code size tests
#define LUABIND_NO_INTERNAL_TAG_ARGUMENTS

namespace luabind {

LUABIND_API void disable_super_deprecation();
Expand Down
264 changes: 58 additions & 206 deletions luabind/detail/call.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
#include <luabind/yield_policy.hpp>
#include <luabind/detail/decorate_type.hpp>
#include <luabind/detail/object.hpp>

#ifdef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
#include <tuple>
#endif

namespace luabind {
namespace detail {
Expand All @@ -32,7 +29,7 @@ namespace luabind {
virtual ~function_object()
{}

virtual int call(lua_State* L, invoke_context& ctx) /* const */ = 0;
virtual int call(lua_State* L, invoke_context& ctx, const int args) const = 0;
virtual int format_signature(lua_State* L, char const* function, bool concat = true) const = 0;

lua_CFunction entry;
Expand Down Expand Up @@ -128,180 +125,8 @@ namespace luabind {
static void postcall(lua_State* /*L*/, int /*results*/) {}
};

#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
template< typename... ArgumentConverters >
struct compute_invoke_values {
using consumed_list = meta::index_list< FooFoo<ArgumentConverters>::consumed_args... >;
using stack_index_list = typename compute_stack_indices< consumed_list, 1 >::type;
enum { arity = meta::sum<consumed_list>::value };
};
#endif


}

#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
inline int match_deferred(lua_State* L, meta::index_list<>, meta::type_list<>)
{
return 0;
}

template< unsigned int StackIndex0, unsigned int... StackIndices,
typename ArgumentType0, typename... ArgumentTypes,
typename ArgumentConverter0, typename... ArgumentConverters >
int match_deferred(lua_State* L,
meta::index_list< StackIndex0, StackIndices... >,
meta::type_list< ArgumentType0, ArgumentTypes... >,
ArgumentConverter0& converter0, ArgumentConverters&... converters
)
{
const int this_match = converter0.match(L, decorated_type<ArgumentType0>(), StackIndex0);
const int other_match = match_deferred(L, meta::index_list<StackIndices...>(), meta::type_list<ArgumentTypes...>(), converters...);
return (this_match >= 0) ? // could also sum them all up unconditionally
this_match + match_deferred(L, meta::index_list<StackIndices...>(), meta::type_list<ArgumentTypes...>(), converters...)
: no_match;
}

template< typename T, bool isvoid, bool memfun = std::is_member_function_pointer<T>::value > struct do_call_struct;

template< typename T >
struct do_call_struct< T, true, true /*memfun*/> {
template< typename F, typename ArgumentType0, typename... ArgumentTypes, unsigned int StackIndex0, unsigned int... StackIndices, typename ReturnConverter, typename Argument0Converter, typename... ArgumentConverters >
static void do_call(lua_State* L, F& f,
meta::index_list<StackIndex0, StackIndices...>, meta::type_list<ArgumentType0, ArgumentTypes...>,
ReturnConverter& result_converter, Argument0Converter& arg0_converter, ArgumentConverters&... arg_converters
)
{
((arg0_converter.to_cpp(L, decorated_type<ArgumentType0>(), StackIndex0)).*f)(
arg_converters.to_cpp(L, decorated_type<ArgumentTypes>(), StackIndices)...
);
}
};

template< typename T >
struct do_call_struct< T, false, true /*memfun*/> {
template< typename F, typename ArgumentType0, typename... ArgumentTypes, unsigned int StackIndex0, unsigned int... StackIndices, typename ReturnConverter, typename Argument0Converter, typename... ArgumentConverters >
static void do_call(lua_State* L, F& f,
meta::index_list<StackIndex0, StackIndices...>, meta::type_list<ArgumentType0, ArgumentTypes...>,
ReturnConverter& result_converter, Argument0Converter& arg0_converter, ArgumentConverters&... arg_converters
)
{
result_converter.to_lua(L,
((arg0_converter.to_cpp(L, decorated_type<ArgumentType0>(), StackIndex0)).*f)(
arg_converters.to_cpp(L, decorated_type<ArgumentTypes>(), StackIndices)...
)
);
}
};


template< typename T >
struct do_call_struct< T, true, false > {
template<
typename F,
typename... ArgumentTypes, unsigned int... StackIndices,
typename ReturnConverter, typename... ArgumentConverters
>
static void do_call(lua_State* L, F& f,
meta::index_list<StackIndices...>, meta::type_list<ArgumentTypes...>,
ReturnConverter& result_converter, ArgumentConverters&... arg_converters)
{
f(arg_converters.to_cpp(L, decorated_type<ArgumentTypes>(), StackIndices)...);
}
};

template< typename T >
struct do_call_struct< T, false, false > {
template<
typename F,
typename... ArgumentTypes, unsigned int... StackIndices,
typename ReturnConverter, typename... ArgumentConverters
>
static void do_call(lua_State* L, F& f,
meta::index_list<StackIndices...>, meta::type_list<ArgumentTypes...>,
ReturnConverter& result_converter, ArgumentConverters&... arg_converters)
{
result_converter.to_lua(L,
f(arg_converters.to_cpp(L, decorated_type<ArgumentTypes>(), StackIndices)...)
);
}
};

template< typename F, typename ReturnType, typename... Arguments,
typename ReturnConverter, typename... ArgumentConverters,
unsigned int Index0, unsigned int... Indices, typename PolicyList
>
int invoke3(lua_State* L, function_object const& self, invoke_context& ctx, F& f,
PolicyList, meta::index_list< Index0, Indices... > index_list, meta::type_list<ReturnType, Arguments...> signature_list,
ReturnConverter return_converter, ArgumentConverters... argument_converters)
{
using invoke_values = typename call_detail_new::compute_invoke_values< ArgumentConverters... >;
using argument_list_type = meta::type_list<Arguments...>;
using argument_index_list = meta::index_list<Indices...>;

int const arguments = lua_gettop(L);
int score = no_match;

if(invoke_values::arity == arguments) {
score = match_deferred(L, typename invoke_values::stack_index_list(), argument_list_type(), argument_converters...);
}

if(score >= 0 && score < ctx.best_score) {
ctx.best_score = score;
ctx.candidates[0] = &self;
ctx.candidate_index = 1;
} else if(score == ctx.best_score) {
ctx.candidates[ctx.candidate_index++] = &self;
}

int results = 0;

if(self.next)
{
results = self.next->call(L, ctx);
}

if(score == ctx.best_score && ctx.candidate_index == 1)
{
do_call_struct<F, std::is_void<ReturnType>::value>::do_call(L, f, typename invoke_values::stack_index_list(), argument_list_type(), return_converter, argument_converters...);
meta::init_order{ (argument_converters.converter_postcall(L, decorated_type<Arguments>(), meta::get< typename invoke_values::stack_index_list, Indices - 1 >::value), 0)... };

results = lua_gettop(L) - invoke_values::arity;
if(has_call_policy<PolicyList, yield_policy>::value) {
results = lua_yield(L, results);
}

// call policiy list postcall
call_detail_new::policy_list_postcall < PolicyList, typename meta::push_front< typename invoke_values::stack_index_list, meta::index<invoke_values::arity> >::type >::postcall(L, results);
}

return results;
}

template< typename F, typename ReturnType, typename... Arguments, unsigned int Index0, unsigned int... Indices, typename PolicyList >
int invoke2(lua_State* L, function_object const& self, invoke_context& ctx, F& f,
meta::type_list<ReturnType, Arguments...> signature, meta::index_list<Index0, Indices...>, PolicyList)
{
using signature_type = meta::type_list<ReturnType, Arguments...>;
using return_converter = specialized_converter_policy_n<0, PolicyList, ReturnType, cpp_to_lua>;
return invoke3(L, self, ctx, f,
PolicyList(), meta::index_list<Index0, Indices...>(), signature,
return_converter(), specialized_converter_policy_n<Indices, PolicyList, Arguments, lua_to_cpp>()...
);
}


template <class F, class Signature, typename... PolicyInjectors>
// boost::bind's operator() is const, std::bind's is not
inline int invoke(lua_State* L, function_object const& self, invoke_context& ctx, F& f, Signature,
meta::type_list< PolicyInjectors... > const& injectors)
{
return invoke2(L, self, ctx, f, Signature(), typename meta::make_index_range<0, meta::size<Signature>::value>::type(), injectors);
}
#endif

#ifdef LUABIND_NO_INTERNAL_TAG_ARGUMENTS

// VC2013RC doesn't support expanding a template and its member template in one expression, that's why we have to to incrementally build
// the converter list instead of a single combined expansion.
template< typename ArgumentList, typename PolicyList, typename CurrentList = meta::type_list<>, unsigned int Counter = 1 >
Expand Down Expand Up @@ -480,65 +305,92 @@ namespace luabind {
}
};

static int invoke(lua_State* L, function_object const& self, invoke_context& ctx, F& f) {
int const arguments = lua_gettop(L);
int score = no_match;
template< typename TupleType >
static int call_fun(lua_State* L, invoke_context& ctx, F& f, const int args, TupleType& tuple)
{
int results = 0;

call_struct<
std::is_member_function_pointer<F>::value,
std::is_void<typename traits::result_type>::value,
typename traits::argument_index_list
>::call(L, f, tuple);

results = lua_gettop(L) - args;
if (has_call_policy<PolicyList, yield_policy>::value) {
results = lua_yield(L, results);
}

call_detail_new::policy_list_postcall < PolicyList, typename meta::push_front< typename traits::stack_index_list, meta::index<traits::arity> >::type >::postcall(L, results);

return results;
}

static int call_best_match(lua_State* L, function_object const& self, invoke_context& ctx, F& f, const int args)
{
// Even match needs the tuple, since pointer_converters buffer the cast result
typename traits::argument_converter_tuple_type converter_tuple;

if(traits::arity == arguments) {
// Things to remember:
// 0 is the perfect match. match > 0 means that objects had to be casted, where the value
// is the total distance of all arguments to their given types (graph distance).
// This is why we can say MaxArguments = 100, MaxDerivationDepth = 100, so no match will be > 100*100=10k and -10k1 absorbs every match.
// This gets rid of the awkward checks during converter match traversal.
int score = no_match;
if (traits::arity == args)
{
using struct_type = match_struct< typename traits::stack_index_list, typename traits::signature_list >;
score = struct_type::match(L, converter_tuple);
}

if(score >= 0 && score < ctx.best_score) {
if (score >= 0 && score < ctx.best_score) {
ctx.best_score = score;
ctx.candidates[0] = &self;
ctx.candidate_index = 1;
} else if(score == ctx.best_score) {
}
else if (score == ctx.best_score) {
ctx.candidates[ctx.candidate_index++] = &self;
}

int results = 0;
if (self.next)
results = self.next->call(L, ctx, args);

if(self.next)
{
results = self.next->call(L, ctx);
}
if (ctx.best_score == score && ctx.candidate_index == 1)
results = call_fun(L, ctx, f, args, converter_tuple);

return results;
}

static int invoke(lua_State* L, function_object const& self, invoke_context& ctx, F& f) {
int const arguments = lua_gettop(L);

if(score == ctx.best_score && ctx.candidate_index == 1)
#ifndef XRAY_SCRIPTS_NO_BACKWARDS_COMPATIBILITY
if (!self.next)
{
call_struct<
std::is_member_function_pointer<F>::value,
std::is_void<typename traits::result_type>::value,
typename traits::argument_index_list
>::call(L, f, converter_tuple);

results = lua_gettop(L) - traits::arity;
if(has_call_policy<PolicyList, yield_policy>::value) {
results = lua_yield(L, results);
}

call_detail_new::policy_list_postcall < PolicyList, typename meta::push_front< typename traits::stack_index_list, meta::index<traits::arity> >::type >::postcall(L, results);
// Even match needs the tuple, since pointer_converters buffer the cast result
typename traits::argument_converter_tuple_type converter_tuple;

using struct_type = match_struct< typename traits::stack_index_list, typename traits::signature_list >;
ctx.best_score = struct_type::match(L, converter_tuple);
ctx.candidates[0] = &self;
ctx.candidate_index = 1;

return call_fun(L, ctx, f, arguments, converter_tuple);
}
#endif

return results;
return call_best_match(L, self, ctx, f, arguments);
}

};

template< typename PolicyList, typename Signature, typename F>
inline int call_best_match(lua_State* L, function_object const& self, invoke_context& ctx, F& f, const int args)
{
return invoke_struct<PolicyList, Signature, F>::call_best_match(L, self, ctx, f, args);
}

template< typename PolicyList, typename Signature, typename F>
inline int invoke(lua_State* L, function_object const& self, invoke_context& ctx, F& f)
{
return invoke_struct<PolicyList, Signature, F>::invoke(L, self, ctx, f);
}
#endif

}
} // namespace luabind::detail
Expand Down
Loading