Fixed usertype checking for overloading resolution (and for userdata in general)

This commit is contained in:
ThePhD 2016-02-11 02:28:38 -05:00
parent 427194bc92
commit a71c9737d4
2 changed files with 42 additions and 14 deletions

View File

@ -64,7 +64,7 @@ struct overloaded_function : base_function {
if (!detail::check_types(args_type(), args_type(), L)) {
return match_arity(L, x, indices<In...>());
}
return stack::typed_call(return_type(), args_type(), func, L);
return stack::typed_call<false>(return_type(), args_type(), func, L);
}
int match_arity(lua_State* L) {
@ -120,7 +120,7 @@ struct usertype_overloaded_function : base_function {
return match_arity(L, x, indices<In...>());
}
func.item = ptr(stack::get<T>(L, 1));
return stack::typed_call(return_type(), args_type(), func, L);
return stack::typed_call<false>(return_type(), args_type(), func, L);
}
int match_arity(lua_State* L) {
@ -175,7 +175,7 @@ struct usertype_indexing_function<overload_set<Functions...>, T> : base_function
return match_arity(L, x, indices<In...>());
}
func.item = ptr(stack::get<T>(L, 1));
return stack::typed_call(return_type(), args_type(), func, L);
return stack::typed_call<false>(return_type(), args_type(), func, L);
}
int match_arity(lua_State* L) {

View File

@ -203,19 +203,47 @@ struct checker {
}
};
template <typename T, type expected, typename C>
struct checker<T*, expected, C> {
template <typename T, typename C>
struct checker<T*, type::userdata, C> {
template <typename Handler>
static bool check (lua_State* L, int index, const Handler& handler) {
const type indextype = type_of(L, index);
// Allow nil to be transformed to nullptr
bool success = expected == indextype || indextype == type::nil;
if (!success) {
// expected type, actual type
handler(L, index, expected, indextype);
if (indextype == type::nil) {
return true;
}
return checker<T, type::userdata, C>{}.check(L, indextype, index, handler);
}
};
template <typename T,typename C>
struct checker<T, type::userdata, C> {
template <typename Handler>
static bool check (lua_State* L, type indextype, int index, const Handler& handler) {
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype);
return false;
}
if (lua_getmetatable(L, index) == 0) {
handler(L, index, type::userdata, indextype);
return false;
}
const type expectedmetatabletype = static_cast<type>(luaL_getmetatable(L, &usertype_traits<T>::metatable[0]));
if (expectedmetatabletype == type::nil) {
lua_pop(L, 2);
handler(L, index, type::userdata, indextype);
return false;
}
bool success = lua_rawequal(L, -1, -2) == 1;
lua_pop(L, 2);
return success;
}
template <typename Handler>
static bool check (lua_State* L, int index, const Handler& handler) {
const type indextype = type_of(L, index);
return check(L, indextype, index, handler);
}
};
template<typename T, typename>
@ -628,17 +656,17 @@ inline void call(lua_State* L, types<void> tr, types<Args...> ta, Fx&& fx, FxArg
call<checkargs>(L, 0, ta, tr, ta, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
template<typename... Args, typename Fx>
template<bool check_args = detail::default_check_arguments, typename... Args, typename Fx>
inline int typed_call(types<void> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
stack::call(L, 0, tr, ta, fx);
stack::call<check_args>(L, 0, tr, ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return 0;
}
template<typename... Ret, typename... Args, typename Fx>
template<bool check_args = detail::default_check_arguments, typename... Ret, typename... Args, typename Fx>
inline int typed_call(types<Ret...> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
decltype(auto) r = stack::call(L, 0, tr, ta, fx);
decltype(auto) r = stack::call<check_args>(L, 0, tr, ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return stack::push(L, std::forward<decltype(r)>(r));