2016-06-04 09:40:23 +08:00
// The MIT License (MIT)
2017-05-15 22:41:50 +08:00
// Copyright (c) 2013-2017 Rapptz, ThePhD and contributors
2016-06-04 09:40:23 +08:00
// 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_CALL_HPP
# define SOL_CALL_HPP
2016-07-08 04:52:39 +08:00
# include "protect.hpp"
2016-06-04 09:40:23 +08:00
# include "wrapper.hpp"
# include "property.hpp"
2017-08-22 03:25:43 +08:00
# include "filters.hpp"
2016-06-04 09:40:23 +08:00
# include "stack.hpp"
2016-06-20 07:02:40 +08:00
namespace sol {
2017-08-22 03:25:43 +08:00
namespace usertype_detail {
} // usertype_detail
namespace filter_detail {
template < int I , int . . . In >
inline void handle_filter ( static_stack_dependencies < I , In . . . > , lua_State * L , int & ) {
if ( sizeof . . . ( In ) = = 0 ) {
return ;
}
absolute_index ai ( L , I ) ;
if ( type_of ( L , ai ) ! = type : : userdata ) {
return ;
}
lua_createtable ( L , static_cast < int > ( sizeof . . . ( In ) ) , 0 ) ;
stack_reference deps ( L , - 1 ) ;
auto per_dep = [ & L , & deps ] ( int i ) {
lua_pushvalue ( L , i ) ;
luaL_ref ( L , deps . stack_index ( ) ) ;
} ;
( void ) per_dep ;
( void ) detail : : swallow { int ( ) , ( per_dep ( In ) , int ( ) ) . . . } ;
lua_setuservalue ( L , ai ) ;
}
template < int . . . In >
inline void handle_filter ( returns_self_with < In . . . > , lua_State * L , int & pushed ) {
pushed = stack : : push ( L , raw_index ( 1 ) ) ;
handle_filter ( static_stack_dependencies < - 1 , In . . . > ( ) , L , pushed ) ;
}
inline void handle_filter ( const stack_dependencies & sdeps , lua_State * L , int & ) {
absolute_index ai ( L , sdeps . target ) ;
if ( type_of ( L , ai ) ! = type : : userdata ) {
return ;
}
lua_createtable ( L , static_cast < int > ( sdeps . size ( ) ) , 0 ) ;
stack_reference deps ( L , - 1 ) ;
for ( std : : size_t i = 0 ; i < sdeps . size ( ) ; + + i ) {
lua_pushvalue ( L , sdeps . stack_indices [ i ] ) ;
luaL_ref ( L , deps . stack_index ( ) ) ;
}
lua_setuservalue ( L , ai ) ;
}
template < typename P , meta : : disable < std : : is_base_of < detail : : filter_base_tag , meta : : unqualified_t < P > > > = meta : : enabler >
inline void handle_filter ( P & & p , lua_State * L , int & pushed ) {
pushed = std : : forward < P > ( p ) ( L , pushed ) ;
}
} // filter_detail
2017-02-20 16:44:41 +08:00
namespace function_detail {
inline int no_construction_error ( lua_State * L ) {
return luaL_error ( L , " sol: cannot call this constructor (tagged as non-constructible) " ) ;
}
2017-08-22 03:25:43 +08:00
} // function_detail
2017-02-20 16:44:41 +08:00
2016-06-20 07:02:40 +08:00
namespace call_detail {
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 ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename T , typename List >
2017-03-16 15:07:20 +08:00
struct void_call : void_call < T , meta : : function_args_t < List > > { } ;
2016-06-20 07:02:40 +08:00
template < typename T , typename . . . Args >
struct void_call < T , types < Args . . . > > {
static void call ( Args . . . ) { }
} ;
2017-08-22 03:25:43 +08:00
template < typename T , bool checked , bool clean_stack >
2016-06-20 07:02:40 +08:00
struct constructor_match {
T * obj ;
2016-11-26 09:47:15 +08:00
constructor_match ( T * o ) : obj ( o ) { }
2016-06-20 07:02:40 +08:00
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 { } ;
2017-08-22 03:25:43 +08:00
return stack : : call_into_lua < checked , clean_stack > ( r , a , L , start , func , obj ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
} ;
namespace overload_detail {
template < std : : size_t . . . M , typename Match , typename . . . Args >
2016-08-08 08:56:05 +08:00
inline int overload_match_arity ( types < > , std : : index_sequence < > , std : : index_sequence < M . . . > , Match & & , lua_State * L , int , int , Args & & . . . ) {
2016-06-20 07:02:40 +08:00
return luaL_error ( L , " sol: no matching function call takes this number of arguments and the specified types " ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename Fx , typename . . . Fxs , std : : size_t I , std : : size_t . . . In , std : : size_t . . . M , typename Match , typename . . . Args >
2016-08-08 08:56:05 +08:00
inline int overload_match_arity ( types < Fx , Fxs . . . > , std : : index_sequence < I , In . . . > , std : : index_sequence < M . . . > , Match & & matchfx , lua_State * L , int fxarity , int start , Args & & . . . args ) {
2017-06-14 04:34:18 +08:00
typedef lua_bind_traits < meta : : unwrap_unqualified_t < Fx > > traits ;
2016-06-20 07:02:40 +08:00
typedef meta : : tuple_types < typename traits : : return_type > return_types ;
typedef typename traits : : free_args_list args_list ;
// compile-time eliminate any functions that we know ahead of time are of improper arity
2017-08-06 07:20:28 +08:00
if ( ! traits : : runtime_variadics_t : : value & & meta : : find_in_pack_v < index_value < traits : : free_arity > , index_value < M > . . . > : : value ) {
2016-06-20 07:02:40 +08:00
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 ) . . . ) ;
}
2017-01-10 05:38:23 +08:00
if ( ! traits : : runtime_variadics_t : : value & & traits : : free_arity ! = fxarity ) {
2016-07-08 04:52:39 +08:00
return overload_match_arity ( types < Fxs . . . > ( ) , std : : index_sequence < In . . . > ( ) , std : : index_sequence < traits : : free_arity , M . . . > ( ) , std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
2016-06-20 07:02:40 +08:00
}
2016-07-29 12:57:47 +08:00
stack : : record tracking { } ;
if ( ! stack : : stack_detail : : check_types < true > { } . check ( args_list ( ) , L , start , no_panic , tracking ) ) {
2016-06-20 07:02:40 +08:00
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 ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2016-10-24 07:17:33 +08:00
template < std : : size_t . . . M , typename Match , typename . . . Args >
inline int overload_match_arity_single ( types < > , std : : index_sequence < > , std : : index_sequence < M . . . > , Match & & matchfx , lua_State * L , int fxarity , int start , Args & & . . . args ) {
return overload_match_arity ( types < > ( ) , std : : index_sequence < > ( ) , std : : index_sequence < M . . . > ( ) , std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
}
template < typename Fx , std : : size_t I , std : : size_t . . . M , typename Match , typename . . . Args >
inline int overload_match_arity_single ( types < Fx > , std : : index_sequence < I > , std : : index_sequence < M . . . > , Match & & matchfx , lua_State * L , int fxarity , int start , Args & & . . . args ) {
2017-06-14 04:34:18 +08:00
typedef lua_bind_traits < meta : : unwrap_unqualified_t < Fx > > traits ;
2016-10-24 07:17:33 +08:00
typedef meta : : tuple_types < typename traits : : return_type > return_types ;
typedef typename traits : : free_args_list args_list ;
// compile-time eliminate any functions that we know ahead of time are of improper arity
2017-08-06 07:20:28 +08:00
if ( ! traits : : runtime_variadics_t : : value & & meta : : find_in_pack_v < index_value < traits : : free_arity > , index_value < M > . . . > : : value ) {
2016-10-24 07:17:33 +08:00
return overload_match_arity ( types < > ( ) , std : : index_sequence < > ( ) , std : : index_sequence < M . . . > ( ) , std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
}
2017-01-10 05:38:23 +08:00
if ( ! traits : : runtime_variadics_t : : value & & traits : : free_arity ! = fxarity ) {
2016-10-24 07:17:33 +08:00
return overload_match_arity ( types < > ( ) , std : : index_sequence < > ( ) , std : : index_sequence < traits : : free_arity , 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 ) . . . ) ;
}
template < typename Fx , typename Fx1 , typename . . . Fxs , std : : size_t I , std : : size_t I1 , std : : size_t . . . In , std : : size_t . . . M , typename Match , typename . . . Args >
inline int overload_match_arity_single ( types < Fx , Fx1 , Fxs . . . > , std : : index_sequence < I , I1 , In . . . > , std : : index_sequence < M . . . > , Match & & matchfx , lua_State * L , int fxarity , int start , Args & & . . . args ) {
2017-06-14 04:34:18 +08:00
typedef lua_bind_traits < meta : : unwrap_unqualified_t < Fx > > traits ;
2016-10-24 07:17:33 +08:00
typedef meta : : tuple_types < typename traits : : return_type > return_types ;
typedef typename traits : : free_args_list args_list ;
// compile-time eliminate any functions that we know ahead of time are of improper arity
2017-08-06 07:20:28 +08:00
if ( ! traits : : runtime_variadics_t : : value & & meta : : find_in_pack_v < index_value < traits : : free_arity > , index_value < M > . . . > : : value ) {
2016-10-24 07:17:33 +08:00
return overload_match_arity ( types < Fx1 , Fxs . . . > ( ) , std : : index_sequence < I1 , In . . . > ( ) , std : : index_sequence < M . . . > ( ) , std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
}
2017-01-10 05:38:23 +08:00
if ( ! traits : : runtime_variadics_t : : value & & traits : : free_arity ! = fxarity ) {
2016-10-24 07:17:33 +08:00
return overload_match_arity ( types < Fx1 , Fxs . . . > ( ) , std : : index_sequence < I1 , In . . . > ( ) , std : : index_sequence < traits : : free_arity , M . . . > ( ) , std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
}
stack : : record tracking { } ;
if ( ! stack : : stack_detail : : check_types < true > { } . check ( args_list ( ) , L , start , no_panic , tracking ) ) {
return overload_match_arity ( types < Fx1 , Fxs . . . > ( ) , std : : index_sequence < I1 , 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 ) . . . ) ;
}
2016-06-20 07:02:40 +08:00
} // overload_detail
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
template < typename . . . Functions , typename Match , typename . . . Args >
inline int overload_match_arity ( Match & & matchfx , lua_State * L , int fxarity , int start , Args & & . . . args ) {
2016-10-24 07:17:33 +08:00
return overload_detail : : overload_match_arity_single ( types < Functions . . . > ( ) , std : : make_index_sequence < sizeof . . . ( Functions ) > ( ) , std : : index_sequence < > ( ) , std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
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 ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename T , typename . . . TypeLists , typename Match , typename . . . Args >
2016-07-08 04:52:39 +08:00
inline int construct_match ( Match & & matchfx , lua_State * L , int fxarity , int start , Args & & . . . args ) {
2016-06-20 07:02:40 +08:00
// 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 ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2017-08-22 03:25:43 +08:00
template < typename T , bool checked , bool clean_stack , typename . . . TypeLists >
2016-06-20 07:02:40 +08:00
inline int construct ( lua_State * L ) {
2016-10-22 05:32:27 +08:00
static const auto & meta = usertype_traits < T > : : metatable ( ) ;
2016-06-20 07:02:40 +08:00
int argcount = lua_gettop ( L ) ;
2016-10-22 05:32:27 +08:00
call_syntax syntax = argcount > 0 ? stack : : get_call_syntax ( L , & usertype_traits < T > : : user_metatable ( ) [ 0 ] , 1 ) : call_syntax : : dot ;
2016-06-20 07:02:40 +08:00
argcount - = static_cast < int > ( syntax ) ;
2016-06-08 08:32:10 +08:00
2016-06-20 07:02:40 +08:00
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 ( ) ;
2017-08-22 03:25:43 +08:00
construct_match < T , TypeLists . . . > ( constructor_match < T , checked , clean_stack > ( obj ) , L , argcount , 1 + static_cast < int > ( syntax ) ) ;
2016-06-20 07:02:40 +08:00
userdataref . push ( ) ;
luaL_getmetatable ( L , & meta [ 0 ] ) ;
2016-12-03 20:33:18 +08:00
if ( type_of ( L , - 1 ) = = type : : lua_nil ) {
2016-06-20 07:02:40 +08:00
lua_pop ( L , 1 ) ;
return luaL_error ( L , " sol: unable to get usertype metatable " ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
lua_setmetatable ( L , - 2 ) ;
return 1 ;
2016-06-08 08:32:10 +08:00
}
2017-08-22 03:25:43 +08:00
template < typename F , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename = void >
2016-06-20 07:02:40 +08:00
struct agnostic_lua_call_wrapper {
2016-08-08 08:56:05 +08:00
template < typename Fx , typename . . . Args >
static int call ( lua_State * L , Fx & & f , Args & & . . . args ) {
2016-06-20 07:02:40 +08:00
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 ;
2017-08-22 03:25:43 +08:00
return stack : : call_into_lua < checked , clean_stack > ( returns_list ( ) , args_list ( ) , L , boost + 1 , caller ( ) , std : : forward < Fx > ( f ) , std : : forward < Args > ( args ) . . . ) ;
2016-06-20 07:02:40 +08:00
}
2016-08-08 08:56:05 +08:00
} ;
2016-06-08 08:32:10 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < var_wrapper < T > , true , is_variable , checked , boost , clean_stack , C > {
2016-08-08 08:56:05 +08:00
template < typename F >
static int call ( lua_State * L , F & & f ) {
2017-08-22 03:25:43 +08:00
typedef is_stack_based < meta : : unqualified_t < decltype ( detail : : unwrap ( f . value ) ) > > is_stack ;
if ( clean_stack & & ! is_stack : : value ) {
lua_settop ( L , 0 ) ;
}
2016-08-08 08:56:05 +08:00
return stack : : push_reference ( L , detail : : unwrap ( f . value ) ) ;
2016-06-20 07:02:40 +08:00
}
2016-08-08 08:56:05 +08:00
} ;
2016-06-20 07:02:40 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < var_wrapper < T > , false , is_variable , checked , boost , clean_stack , C > {
2016-08-08 08:56:05 +08:00
template < typename V >
static int call_assign ( std : : true_type , lua_State * L , V & & f ) {
detail : : unwrap ( f . value ) = stack : : get < meta : : unwrapped_t < T > > ( L , boost + ( is_variable ? 3 : 1 ) ) ;
2017-08-22 03:25:43 +08:00
if ( clean_stack ) {
lua_settop ( L , 0 ) ;
}
2016-08-08 08:56:05 +08:00
return 0 ;
2016-06-20 07:02:40 +08:00
}
2016-06-04 09:40:23 +08:00
2016-08-08 08:56:05 +08:00
template < typename . . . Args >
static int call_assign ( std : : false_type , lua_State * L , Args & & . . . ) {
return luaL_error ( L , " sol: cannot write to this variable: copy assignment/constructor not available " ) ;
}
template < typename . . . Args >
static int call_const ( std : : false_type , lua_State * L , Args & & . . . args ) {
typedef meta : : unwrapped_t < T > R ;
return call_assign ( std : : is_assignable < std : : add_lvalue_reference_t < meta : : unqualified_t < R > > , R > ( ) , L , std : : forward < Args > ( args ) . . . ) ;
}
template < typename . . . Args >
static int call_const ( std : : true_type , lua_State * L , Args & & . . . ) {
return luaL_error ( L , " sol: cannot write to a readonly (const) variable " ) ;
}
template < typename V >
static int call ( lua_State * L , V & & f ) {
return call_const ( std : : is_const < meta : : unwrapped_t < T > > ( ) , L , f ) ;
2016-08-07 05:29:07 +08:00
}
} ;
2017-08-22 03:25:43 +08:00
template < bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < lua_r_CFunction , is_index , is_variable , checked , boost , clean_stack , C > {
2016-06-20 07:02:40 +08:00
static int call ( lua_State * L , lua_r_CFunction f ) {
return f ( L ) ;
}
} ;
2016-06-04 09:40:23 +08:00
2017-08-22 03:25:43 +08:00
template < bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < lua_CFunction , is_index , is_variable , checked , boost , clean_stack , C > {
2016-06-20 07:02:40 +08:00
static int call ( lua_State * L , lua_CFunction f ) {
return f ( L ) ;
}
} ;
2017-08-06 07:20:28 +08:00
2017-06-17 12:43:26 +08:00
# ifdef SOL_NOEXCEPT_FUNCTION_TYPE
2017-08-22 03:25:43 +08:00
template < bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < detail : : lua_CFunction_noexcept , is_index , is_variable , checked , boost , clean_stack , C > {
2017-06-17 12:43:26 +08:00
static int call ( lua_State * L , detail : : lua_CFunction_noexcept f ) {
return f ( L ) ;
}
} ;
# endif // noexcept function types
2016-06-04 09:40:23 +08:00
2017-08-22 03:25:43 +08:00
template < bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < no_prop , is_index , is_variable , checked , boost , clean_stack , C > {
2016-06-30 02:08:26 +08:00
static int call ( lua_State * L , const no_prop & ) {
2016-06-20 07:02:40 +08:00
return luaL_error ( L , is_index ? " sol: cannot read from a writeonly property " : " sol: cannot write to a readonly property " ) ;
}
} ;
2016-06-04 09:40:23 +08:00
2017-08-22 03:25:43 +08:00
template < bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < no_construction , is_index , is_variable , checked , boost , clean_stack , C > {
2016-06-30 02:08:26 +08:00
static int call ( lua_State * L , const no_construction & ) {
2017-02-20 16:44:41 +08:00
return function_detail : : no_construction_error ( L ) ;
2016-06-23 01:26:27 +08:00
}
} ;
2017-08-22 03:25:43 +08:00
template < typename . . . Args , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < bases < Args . . . > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-06-30 02:08:26 +08:00
static int call ( lua_State * , const bases < Args . . . > & ) {
2016-06-23 01:26:27 +08:00
// Uh. How did you even call this, lul
return 0 ;
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct agnostic_lua_call_wrapper < std : : reference_wrapper < T > , is_index , is_variable , checked , boost , clean_stack , C > {
2017-06-14 04:34:18 +08:00
static int call ( lua_State * L , std : : reference_wrapper < T > f ) {
2017-08-22 03:25:43 +08:00
return agnostic_lua_call_wrapper < T , is_index , is_variable , checked , boost , clean_stack > { } . call ( L , f . get ( ) ) ;
2017-06-14 04:34:18 +08:00
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename F , bool is_index , bool is_variable , bool checked = stack : : stack_detail : : default_check_arguments , int boost = 0 , bool clean_stack = true , typename = void >
struct lua_call_wrapper : agnostic_lua_call_wrapper < F , is_index , is_variable , checked , boost , clean_stack > { } ;
2016-06-23 01:26:27 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , typename F , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack >
struct lua_call_wrapper < T , F , is_index , is_variable , checked , boost , clean_stack , std : : enable_if_t < std : : is_member_function_pointer < F > : : value > > {
2016-07-09 13:12:33 +08:00
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : object_type object_type ;
template < typename Fx >
static int call ( lua_State * L , Fx & & f , object_type & o ) {
2016-06-23 01:26:27 +08:00
typedef typename wrap : : returns_list returns_list ;
typedef typename wrap : : args_list args_list ;
typedef typename wrap : : caller caller ;
2017-08-22 03:25:43 +08:00
return stack : : call_into_lua < checked , clean_stack > ( returns_list ( ) , args_list ( ) , L , boost + ( is_variable ? 3 : 2 ) , caller ( ) , std : : forward < Fx > ( f ) , o ) ;
2016-07-09 13:12:33 +08:00
}
2016-06-23 01:26:27 +08:00
2016-07-09 13:12:33 +08:00
template < typename Fx >
static int call ( lua_State * L , Fx & & f ) {
typedef std : : conditional_t < std : : is_void < T > : : value , object_type , T > Ta ;
2016-06-23 01:26:27 +08:00
# ifdef SOL_SAFE_USERTYPE
2016-11-07 05:34:05 +08:00
auto maybeo = stack : : check_get < Ta * > ( L , 1 ) ;
if ( ! maybeo | | maybeo . value ( ) = = nullptr ) {
2016-12-03 20:33:18 +08:00
return luaL_error ( L , " sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax) " ) ;
2016-06-23 01:26:27 +08:00
}
2016-11-07 05:34:05 +08:00
object_type * o = static_cast < object_type * > ( maybeo . value ( ) ) ;
2016-07-09 13:12:33 +08:00
return call ( L , std : : forward < Fx > ( f ) , * o ) ;
2016-06-23 01:26:27 +08:00
# else
2016-08-24 09:42:27 +08:00
object_type & o = static_cast < object_type & > ( * stack : : get < non_null < Ta * > > ( L , 1 ) ) ;
2016-07-09 13:12:33 +08:00
return call ( L , std : : forward < Fx > ( f ) , o ) ;
2016-06-23 01:26:27 +08:00
# endif // Safety
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename F , bool is_variable , bool checked , int boost , bool clean_stack >
struct lua_call_wrapper < T , F , false , is_variable , checked , boost , clean_stack , std : : enable_if_t < std : : is_member_object_pointer < F > : : value > > {
2016-08-08 08:56:05 +08:00
typedef lua_bind_traits < F > traits_type ;
2016-07-09 13:12:33 +08:00
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : object_type object_type ;
2016-06-04 09:40:23 +08:00
2016-07-09 13:12:33 +08:00
template < typename V >
static int call_assign ( std : : true_type , lua_State * L , V & & f , object_type & o ) {
2016-06-20 07:02:40 +08:00
typedef typename wrap : : args_list args_list ;
typedef typename wrap : : caller caller ;
2017-08-22 03:25:43 +08:00
return stack : : call_into_lua < checked , clean_stack > ( types < void > ( ) , args_list ( ) , L , boost + ( is_variable ? 3 : 2 ) , caller ( ) , f , o ) ;
2016-07-09 13:12:33 +08:00
}
template < typename V >
static int call_assign ( std : : true_type , lua_State * L , V & & f ) {
typedef std : : conditional_t < std : : is_void < T > : : value , object_type , T > Ta ;
2016-06-04 09:40:23 +08:00
# ifdef SOL_SAFE_USERTYPE
2016-11-07 05:34:05 +08:00
auto maybeo = stack : : check_get < Ta * > ( L , 1 ) ;
if ( ! maybeo | | maybeo . value ( ) = = nullptr ) {
2016-06-20 07:02:40 +08:00
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) " ) ;
2016-06-04 09:40:23 +08:00
}
2016-11-07 05:34:05 +08:00
object_type * o = static_cast < object_type * > ( maybeo . value ( ) ) ;
2016-07-09 13:12:33 +08:00
return call_assign ( std : : true_type ( ) , L , f , * o ) ;
2016-06-04 09:40:23 +08:00
# else
2016-08-24 09:42:27 +08:00
object_type & o = static_cast < object_type & > ( * stack : : get < non_null < Ta * > > ( L , 1 ) ) ;
2016-07-09 13:12:33 +08:00
return call_assign ( std : : true_type ( ) , L , f , o ) ;
2016-06-04 09:40:23 +08:00
# endif // Safety
2016-06-20 07:02:40 +08:00
}
2016-06-04 09:40:23 +08:00
2016-07-09 13:12:33 +08:00
template < typename . . . Args >
static int call_assign ( std : : false_type , lua_State * L , Args & & . . . ) {
2016-06-20 07:02:40 +08:00
return luaL_error ( L , " sol: cannot write to this variable: copy assignment/constructor not available " ) ;
}
2016-06-07 03:46:53 +08:00
2016-07-09 13:12:33 +08:00
template < typename . . . Args >
static int call_const ( std : : false_type , lua_State * L , Args & & . . . args ) {
2016-06-20 07:02:40 +08:00
typedef typename traits_type : : return_type R ;
2017-05-17 08:20:59 +08:00
return call_assign ( std : : is_copy_assignable < meta : : unqualified_t < R > > ( ) , L , std : : forward < Args > ( args ) . . . ) ;
2016-06-20 07:02:40 +08:00
}
2016-06-04 09:40:23 +08:00
2016-07-09 13:12:33 +08:00
template < typename . . . Args >
static int call_const ( std : : true_type , lua_State * L , Args & & . . . ) {
2016-06-20 07:02:40 +08:00
return luaL_error ( L , " sol: cannot write to a readonly (const) variable " ) ;
}
2016-06-04 09:40:23 +08:00
2016-07-09 13:12:33 +08:00
template < typename V >
static int call ( lua_State * L , V & & f ) {
2017-03-16 15:07:20 +08:00
return call_const ( std : : is_const < typename traits_type : : return_type > ( ) , L , std : : forward < V > ( f ) ) ;
2016-06-20 07:02:40 +08:00
}
2016-07-09 13:12:33 +08:00
template < typename V >
static int call ( lua_State * L , V & & f , object_type & o ) {
2017-03-16 15:07:20 +08:00
return call_const ( std : : is_const < typename traits_type : : return_type > ( ) , L , std : : forward < V > ( f ) , o ) ;
2016-07-09 13:12:33 +08:00
}
2016-06-20 07:02:40 +08:00
} ;
2016-06-04 09:40:23 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , typename F , bool is_variable , bool checked , int boost , bool clean_stack >
struct lua_call_wrapper < T , F , true , is_variable , checked , boost , clean_stack , std : : enable_if_t < std : : is_member_object_pointer < F > : : value > > {
2016-08-08 08:56:05 +08:00
typedef lua_bind_traits < F > traits_type ;
2016-07-09 13:12:33 +08:00
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : object_type object_type ;
2016-06-04 09:40:23 +08:00
2016-07-09 13:12:33 +08:00
template < typename V >
2017-05-29 22:32:37 +08:00
static int call ( lua_State * L , V & & v , object_type & o ) {
2016-06-20 07:02:40 +08:00
typedef typename wrap : : returns_list returns_list ;
typedef typename wrap : : caller caller ;
2017-05-29 22:32:37 +08:00
F f ( std : : forward < V > ( v ) ) ;
2017-08-22 03:25:43 +08:00
return stack : : call_into_lua < checked , clean_stack > ( returns_list ( ) , types < > ( ) , L , boost + ( is_variable ? 3 : 2 ) , caller ( ) , f , o ) ;
2016-07-09 13:12:33 +08:00
}
template < typename V >
static int call ( lua_State * L , V & & f ) {
typedef std : : conditional_t < std : : is_void < T > : : value , object_type , T > Ta ;
2016-06-20 07:02:40 +08:00
# ifdef SOL_SAFE_USERTYPE
2016-11-07 05:34:05 +08:00
auto maybeo = stack : : check_get < Ta * > ( L , 1 ) ;
if ( ! maybeo | | maybeo . value ( ) = = nullptr ) {
2016-06-20 07:02:40 +08:00
if ( is_variable ) {
2016-12-03 20:33:18 +08:00
return luaL_error ( L , " sol: 'self' argument is lua_nil (bad '.' access?) " ) ;
2016-06-20 07:02:40 +08:00
}
2016-12-03 20:33:18 +08:00
return luaL_error ( L , " sol: 'self' argument is lua_nil (pass 'self' as first argument) " ) ;
2016-06-20 07:02:40 +08:00
}
2016-11-07 05:34:05 +08:00
object_type * o = static_cast < object_type * > ( maybeo . value ( ) ) ;
2016-07-09 13:12:33 +08:00
return call ( L , f , * o ) ;
2016-06-20 07:02:40 +08:00
# else
2016-08-24 09:42:27 +08:00
object_type & o = static_cast < object_type & > ( * stack : : get < non_null < Ta * > > ( L , 1 ) ) ;
2016-07-09 13:12:33 +08:00
return call ( L , f , o ) ;
2016-06-20 07:02:40 +08:00
# endif // Safety
}
} ;
2016-06-04 09:40:23 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , typename F , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , readonly_wrapper < F > , false , is_variable , checked , boost , clean_stack , C > {
2017-05-29 22:32:37 +08:00
typedef lua_bind_traits < F > traits_type ;
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : object_type object_type ;
template < typename V >
static int call ( lua_State * L , V & & ) {
return luaL_error ( L , " sol: cannot write to a sol::readonly variable " ) ;
}
template < typename V >
static int call ( lua_State * L , V & & , object_type & ) {
return luaL_error ( L , " sol: cannot write to a sol::readonly variable " ) ;
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename F , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , readonly_wrapper < F > , true , is_variable , checked , boost , clean_stack , C > : lua_call_wrapper < T , F , true , is_variable , checked , boost , clean_stack , C > {
2017-05-29 22:32:37 +08:00
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename . . . Args , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , constructor_list < Args . . . > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-08-08 08:56:05 +08:00
typedef constructor_list < Args . . . > F ;
2016-06-20 07:02:40 +08:00
static int call ( lua_State * L , F & ) {
2016-10-22 05:32:27 +08:00
const auto & metakey = usertype_traits < T > : : metatable ( ) ;
2016-06-20 07:02:40 +08:00
int argcount = lua_gettop ( L ) ;
2016-10-22 05:32:27 +08:00
call_syntax syntax = argcount > 0 ? stack : : get_call_syntax ( L , & usertype_traits < T > : : user_metatable ( ) [ 0 ] , 1 ) : call_syntax : : dot ;
2016-06-20 07:02:40 +08:00
argcount - = static_cast < int > ( syntax ) ;
2016-06-07 03:46:53 +08:00
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 ;
2017-08-22 03:25:43 +08:00
construct_match < T , Args . . . > ( constructor_match < T , false , clean_stack > ( obj ) , L , argcount , boost + 1 + static_cast < int > ( syntax ) ) ;
2016-06-07 03:46:53 +08:00
userdataref . push ( ) ;
2016-06-20 07:02:40 +08:00
luaL_getmetatable ( L , & metakey [ 0 ] ) ;
2016-12-03 20:33:18 +08:00
if ( type_of ( L , - 1 ) = = type : : lua_nil ) {
2016-06-07 03:46:53 +08:00
lua_pop ( L , 1 ) ;
2016-06-20 07:02:40 +08:00
return luaL_error ( L , " sol: unable to get usertype metatable " ) ;
2016-06-07 03:46:53 +08:00
}
2016-06-20 07:02:40 +08:00
lua_setmetatable ( L , - 2 ) ;
2016-06-07 03:46:53 +08:00
return 1 ;
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename . . . Cxs , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , constructor_wrapper < Cxs . . . > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-08-08 08:56:05 +08:00
typedef constructor_wrapper < Cxs . . . > F ;
2016-06-20 07:02:40 +08:00
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 ) {
2016-10-22 05:32:27 +08:00
const auto & metakey = usertype_traits < T > : : metatable ( ) ;
2016-06-20 07:02:40 +08:00
T * * pointerpointer = reinterpret_cast < T * * > ( lua_newuserdata ( L , sizeof ( T * ) + sizeof ( T ) ) ) ;
2016-07-29 01:33:08 +08:00
reference userdataref ( L , - 1 ) ;
2016-06-20 07:02:40 +08:00
T * & referencepointer = * pointerpointer ;
T * obj = reinterpret_cast < T * > ( pointerpointer + 1 ) ;
referencepointer = obj ;
2016-09-14 12:02:15 +08:00
auto & func = std : : get < I > ( f . functions ) ;
2017-08-22 03:25:43 +08:00
stack : : call_into_lua < checked , clean_stack > ( r , a , L , boost + start , func , detail : : implicit_wrapper < T > ( obj ) ) ;
2016-06-20 07:02:40 +08:00
userdataref . push ( ) ;
2016-06-22 13:20:38 +08:00
luaL_getmetatable ( L , & metakey [ 0 ] ) ;
2016-12-03 20:33:18 +08:00
if ( type_of ( L , - 1 ) = = type : : lua_nil ) {
2016-06-20 07:02:40 +08:00
lua_pop ( L , 1 ) ;
std : : string err = " sol: unable to get usertype metatable for " ;
2016-10-22 05:32:27 +08:00
err + = usertype_traits < T > : : name ( ) ;
2016-06-20 07:02:40 +08:00
return luaL_error ( L , err . c_str ( ) ) ;
}
lua_setmetatable ( L , - 2 ) ;
return 1 ;
}
} ;
static int call ( lua_State * L , F & f ) {
2016-11-16 11:45:34 +08:00
call_syntax syntax = stack : : get_call_syntax ( L , & usertype_traits < T > : : user_metatable ( ) [ 0 ] , 1 ) ;
2016-06-20 07:02:40 +08:00
int syntaxval = static_cast < int > ( syntax ) ;
int argcount = lua_gettop ( L ) - syntaxval ;
2016-07-08 04:52:39 +08:00
return construct_match < T , meta : : pop_front_type_t < meta : : function_args_t < Cxs > > . . . > ( onmatch ( ) , L , argcount , 1 + syntaxval , f ) ;
2016-06-20 07:02:40 +08:00
}
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
} ;
2016-06-07 03:46:53 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , typename Fx , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack >
struct lua_call_wrapper < T , destructor_wrapper < Fx > , is_index , is_variable , checked , boost , clean_stack , std : : enable_if_t < std : : is_void < Fx > : : value > > {
2016-08-08 08:56:05 +08:00
typedef destructor_wrapper < Fx > F ;
2016-06-07 03:46:53 +08:00
2016-06-30 02:08:26 +08:00
static int call ( lua_State * L , const F & ) {
2017-08-22 03:25:43 +08:00
return detail : : usertype_alloc_destruct < T > ( L ) ;
2016-06-20 07:02:40 +08:00
}
} ;
2016-06-07 03:46:53 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , typename Fx , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack >
struct lua_call_wrapper < T , destructor_wrapper < Fx > , is_index , is_variable , checked , boost , clean_stack , std : : enable_if_t < ! std : : is_void < Fx > : : value > > {
2016-08-08 08:56:05 +08:00
typedef destructor_wrapper < Fx > F ;
2016-06-07 03:46:53 +08:00
2016-06-30 02:08:26 +08:00
static int call ( lua_State * L , const F & f ) {
T & obj = stack : : get < T > ( L ) ;
2016-06-20 07:02:40 +08:00
f . fx ( detail : : implicit_wrapper < T > ( obj ) ) ;
return 0 ;
}
} ;
2016-06-07 03:46:53 +08:00
2017-08-22 03:25:43 +08:00
template < typename T , typename . . . Fs , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , overload_set < Fs . . . > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-06-20 07:02:40 +08:00
typedef overload_set < Fs . . . > F ;
2016-06-08 08:32:10 +08:00
2016-06-20 07:02:40 +08:00
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 ) {
2016-09-14 12:02:15 +08:00
auto & f = std : : get < I > ( fx . functions ) ;
2016-08-17 13:16:44 +08:00
return lua_call_wrapper < T , Fx , is_index , is_variable , checked , boost > { } . call ( L , f ) ;
}
} ;
static int call ( lua_State * L , F & fx ) {
return overload_match_arity < Fs . . . > ( on_match ( ) , L , lua_gettop ( L ) , 1 , fx ) ;
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename . . . Fs , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , factory_wrapper < Fs . . . > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-08-17 13:16:44 +08:00
typedef factory_wrapper < 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 ) {
2016-09-14 12:02:15 +08:00
auto & f = std : : get < I > ( fx . functions ) ;
2017-08-22 03:25:43 +08:00
return lua_call_wrapper < T , Fx , is_index , is_variable , checked , boost , clean_stack > { } . call ( L , f ) ;
2016-06-20 07:02:40 +08:00
}
} ;
static int call ( lua_State * L , F & fx ) {
2017-01-10 12:25:28 +08:00
return overload_match_arity < Fs . . . > ( on_match ( ) , L , lua_gettop ( L ) - boost , 1 + boost , fx ) ;
2016-06-08 08:32:10 +08:00
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename R , typename W , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , property_wrapper < R , W > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-08-08 08:56:05 +08:00
typedef std : : conditional_t < is_index , R , W > P ;
typedef meta : : unqualified_t < P > U ;
2017-04-26 07:44:53 +08:00
typedef wrapper < U > wrap ;
2016-08-08 08:56:05 +08:00
typedef lua_bind_traits < U > traits_type ;
2017-04-26 07:44:53 +08:00
typedef meta : : unqualified_t < typename traits_type : : template arg_at < 0 > > object_type ;
2016-08-08 08:56:05 +08:00
template < typename F >
2017-04-26 07:44:53 +08:00
static int self_call ( std : : true_type , lua_State * L , F & & f ) {
// The type being void means we don't have any arguments, so it might be a free functions?
typedef typename traits_type : : free_args_list args_list ;
typedef typename wrap : : returns_list returns_list ;
typedef typename wrap : : caller caller ;
2017-08-22 03:25:43 +08:00
return stack : : call_into_lua < checked , clean_stack > ( returns_list ( ) , args_list ( ) , L , boost + ( is_variable ? 3 : 2 ) , caller ( ) , f ) ;
2017-04-26 07:44:53 +08:00
}
template < typename F >
static int self_call ( std : : false_type , lua_State * L , F & & f ) {
2016-08-08 08:56:05 +08:00
typedef meta : : pop_front_type_t < typename traits_type : : free_args_list > args_list ;
typedef T Ta ;
# ifdef SOL_SAFE_USERTYPE
2016-11-07 05:34:05 +08:00
auto maybeo = stack : : check_get < Ta * > ( L , 1 ) ;
if ( ! maybeo | | maybeo . value ( ) = = nullptr ) {
2016-08-08 08:56:05 +08:00
if ( is_variable ) {
2016-12-03 20:33:18 +08:00
return luaL_error ( L , " sol: 'self' argument is lua_nil (bad '.' access?) " ) ;
2016-08-08 08:56:05 +08:00
}
2016-12-03 20:33:18 +08:00
return luaL_error ( L , " sol: 'self' argument is lua_nil (pass 'self' as first argument) " ) ;
2016-08-08 08:56:05 +08:00
}
2016-11-07 05:34:05 +08:00
object_type * o = static_cast < object_type * > ( maybeo . value ( ) ) ;
2016-08-08 08:56:05 +08:00
# else
2016-11-07 05:34:05 +08:00
object_type * o = static_cast < object_type * > ( stack : : get < non_null < Ta * > > ( L , 1 ) ) ;
2016-08-08 08:56:05 +08:00
# endif // Safety
typedef typename wrap : : returns_list returns_list ;
typedef typename wrap : : caller caller ;
2017-08-22 03:25:43 +08:00
return stack : : call_into_lua < checked , clean_stack > ( returns_list ( ) , args_list ( ) , L , boost + ( is_variable ? 3 : 2 ) , caller ( ) , f , * o ) ;
2016-08-08 08:56:05 +08:00
}
template < typename F , typename . . . Args >
static int defer_call ( std : : false_type , lua_State * L , F & & f , Args & & . . . args ) {
2017-04-26 07:44:53 +08:00
return self_call ( meta : : any < std : : is_void < object_type > , meta : : boolean < lua_type_of < meta : : unwrap_unqualified_t < object_type > > : : value ! = type : : userdata > > ( ) , L , pick ( meta : : boolean < is_index > ( ) , f ) , std : : forward < Args > ( args ) . . . ) ;
2016-08-08 08:56:05 +08:00
}
template < typename F , typename . . . Args >
static int defer_call ( std : : true_type , lua_State * L , F & & f , Args & & . . . args ) {
auto & p = pick ( meta : : boolean < is_index > ( ) , std : : forward < F > ( f ) ) ;
2017-08-22 03:25:43 +08:00
return lua_call_wrapper < T , meta : : unqualified_t < decltype ( p ) > , is_index , is_variable , checked , boost , clean_stack > { } . call ( L , p , std : : forward < Args > ( args ) . . . ) ;
2016-08-08 08:56:05 +08:00
}
template < typename F , typename . . . Args >
static int call ( lua_State * L , F & & f , Args & & . . . args ) {
typedef meta : : any <
std : : is_void < U > ,
std : : is_same < U , no_prop > ,
meta : : is_specialization_of < var_wrapper , U > ,
meta : : is_specialization_of < constructor_wrapper , U > ,
meta : : is_specialization_of < constructor_list , U > ,
std : : is_member_pointer < U >
> is_specialized ;
return defer_call ( is_specialized ( ) , L , std : : forward < F > ( f ) , std : : forward < Args > ( args ) . . . ) ;
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename V , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , protect_t < V > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-07-08 04:52:39 +08:00
typedef protect_t < V > F ;
2016-07-09 13:12:33 +08:00
template < typename . . . Args >
static int call ( lua_State * L , F & fx , Args & & . . . args ) {
2017-08-22 03:25:43 +08:00
return lua_call_wrapper < T , V , is_index , is_variable , true , boost , clean_stack > { } . call ( L , fx . value , std : : forward < Args > ( args ) . . . ) ;
2016-07-08 04:52:39 +08:00
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , typename F , typename . . . Filters , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , filter_wrapper < F , Filters . . . > , is_index , is_variable , checked , boost , clean_stack , C > {
typedef filter_wrapper < F , Filters . . . > P ;
template < std : : size_t . . . In >
static int call ( std : : index_sequence < In . . . > , lua_State * L , P & fx ) {
int pushed = lua_call_wrapper < T , F , is_index , is_variable , checked , boost , false , C > { } . call ( L , fx . value ) ;
( void ) detail : : swallow { int ( ) , ( filter_detail : : handle_filter ( std : : get < In > ( fx . filters ) , L , pushed ) , int ( ) ) . . . } ;
return pushed ;
}
static int call ( lua_State * L , P & fx ) {
typedef typename P : : indices indices ;
return call ( indices ( ) , L , fx ) ;
}
} ;
template < typename T , typename Sig , typename P , bool is_index , bool is_variable , bool checked , int boost , bool clean_stack , typename C >
struct lua_call_wrapper < T , function_arguments < Sig , P > , is_index , is_variable , checked , boost , clean_stack , C > {
2016-09-14 00:37:08 +08:00
template < typename F >
static int call ( lua_State * L , F & & f ) {
2017-08-22 03:25:43 +08:00
return lua_call_wrapper < T , meta : : unqualified_t < P > , is_index , is_variable , checked , boost , clean_stack > { } . call ( L , std : : get < 0 > ( f . arguments ) ) ;
2016-09-14 00:37:08 +08:00
}
} ;
2017-08-22 03:25:43 +08:00
template < typename T , bool is_index , bool is_variable , int boost = 0 , bool checked = stack : : stack_detail : : default_check_arguments , bool clean_stack = true , typename Fx , typename . . . Args >
2016-07-09 13:12:33 +08:00
inline int call_wrapped ( lua_State * L , Fx & & fx , Args & & . . . args ) {
2017-08-22 03:25:43 +08:00
return lua_call_wrapper < T , meta : : unqualified_t < Fx > , is_index , is_variable , checked , boost , clean_stack > { } . call ( L , std : : forward < Fx > ( fx ) , std : : forward < Args > ( args ) . . . ) ;
2016-06-08 08:32:10 +08:00
}
2017-08-22 03:25:43 +08:00
template < typename T , bool is_index , bool is_variable , typename F , int start = 1 , bool checked = stack : : stack_detail : : default_check_arguments , bool clean_stack = true >
2016-07-08 04:52:39 +08:00
inline int call_user ( lua_State * L ) {
2017-05-10 01:24:56 +08:00
auto & fx = stack : : get < user < F > > ( L , upvalue_index ( start ) ) ;
2017-08-22 03:25:43 +08:00
return call_wrapped < T , is_index , is_variable , 0 , checked , clean_stack > ( L , fx ) ;
2016-07-08 04:52:39 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename T , typename = void >
struct is_var_bind : std : : false_type { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename T >
struct is_var_bind < T , std : : enable_if_t < std : : is_member_object_pointer < T > : : value > > : std : : true_type { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < >
struct is_var_bind < no_prop > : std : : true_type { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename R , typename W >
struct is_var_bind < property_wrapper < R , W > > : std : : true_type { } ;
2016-06-04 09:40:23 +08:00
2016-08-07 05:29:07 +08:00
template < typename T >
struct is_var_bind < var_wrapper < T > > : std : : true_type { } ;
2017-05-29 22:32:37 +08:00
template < typename T >
2017-08-22 03:25:43 +08:00
struct is_var_bind < readonly_wrapper < T > > : is_var_bind < meta : : unqualified_t < T > > { } ;
template < typename F , typename . . . Filters >
struct is_var_bind < filter_wrapper < F , Filters . . . > > : is_var_bind < meta : : unqualified_t < F > > { } ;
2016-06-20 07:02:40 +08:00
} // call_detail
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename T >
struct is_variable_binding : call_detail : : is_var_bind < meta : : unqualified_t < T > > { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename T >
struct is_function_binding : meta : : neg < is_variable_binding < T > > { } ;
2016-06-04 09:40:23 +08:00
} // sol
2016-07-08 04:52:39 +08:00
# endif // SOL_CALL_HPP