call.hpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. // sol2
  2. // The MIT License (MIT)
  3. // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. // this software and associated documentation files (the "Software"), to deal in
  6. // the Software without restriction, including without limitation the rights to
  7. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. // the Software, and to permit persons to whom the Software is furnished to do so,
  9. // subject to the following conditions:
  10. // The above copyright notice and this permission notice shall be included in all
  11. // copies or substantial portions of the Software.
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  14. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  15. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  16. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  17. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  18. #pragma once
  19. #ifndef SOL_CALL_HPP
  20. #define SOL_CALL_HPP
  21. #include <sol/property.hpp>
  22. #include <sol/protect.hpp>
  23. #include <sol/wrapper.hpp>
  24. #include <sol/trampoline.hpp>
  25. #include <sol/policies.hpp>
  26. #include <sol/stack.hpp>
  27. #include <sol/unique_usertype_traits.hpp>
  28. namespace sol {
  29. namespace u_detail {
  30. } // namespace u_detail
  31. namespace policy_detail {
  32. template <int I, int... In>
  33. inline void handle_policy(static_stack_dependencies<I, In...>, lua_State* L, int&) {
  34. if constexpr (sizeof...(In) == 0) {
  35. (void)L;
  36. return;
  37. }
  38. else {
  39. absolute_index ai(L, I);
  40. if (type_of(L, ai) != type::userdata) {
  41. return;
  42. }
  43. lua_createtable(L, static_cast<int>(sizeof...(In)), 0);
  44. stack_reference deps(L, -1);
  45. auto per_dep = [&L, &deps](int i) {
  46. #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
  47. luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
  48. #endif // make sure stack doesn't overflow
  49. lua_pushvalue(L, i);
  50. luaL_ref(L, deps.stack_index());
  51. };
  52. (void)per_dep;
  53. (void)detail::swallow { int(), (per_dep(In), int())... };
  54. lua_setuservalue(L, ai);
  55. }
  56. }
  57. template <int... In>
  58. inline void handle_policy(returns_self_with<In...>, lua_State* L, int& pushed) {
  59. pushed = stack::push(L, raw_index(1));
  60. handle_policy(static_stack_dependencies<-1, In...>(), L, pushed);
  61. }
  62. inline void handle_policy(const stack_dependencies& sdeps, lua_State* L, int&) {
  63. absolute_index ai(L, sdeps.target);
  64. if (type_of(L, ai) != type::userdata) {
  65. return;
  66. }
  67. lua_createtable(L, static_cast<int>(sdeps.size()), 0);
  68. stack_reference deps(L, -1);
  69. #if SOL_IS_ON(SOL_SAFE_STACK_CHECK)
  70. luaL_checkstack(L, static_cast<int>(sdeps.size()), detail::not_enough_stack_space_generic);
  71. #endif // make sure stack doesn't overflow
  72. for (std::size_t i = 0; i < sdeps.size(); ++i) {
  73. lua_pushvalue(L, sdeps.stack_indices[i]);
  74. luaL_ref(L, deps.stack_index());
  75. }
  76. lua_setuservalue(L, ai);
  77. }
  78. template <typename P, meta::disable<std::is_base_of<detail::policy_base_tag, meta::unqualified_t<P>>> = meta::enabler>
  79. inline void handle_policy(P&& p, lua_State* L, int& pushed) {
  80. pushed = std::forward<P>(p)(L, pushed);
  81. }
  82. } // namespace policy_detail
  83. namespace function_detail {
  84. inline int no_construction_error(lua_State* L) {
  85. return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
  86. }
  87. } // namespace function_detail
  88. namespace call_detail {
  89. template <typename R, typename W>
  90. inline auto& pick(std::true_type, property_wrapper<R, W>& f) {
  91. return f.read();
  92. }
  93. template <typename R, typename W>
  94. inline auto& pick(std::false_type, property_wrapper<R, W>& f) {
  95. return f.write();
  96. }
  97. template <typename T, typename List>
  98. struct void_call : void_call<T, meta::function_args_t<List>> { };
  99. template <typename T, typename... Args>
  100. struct void_call<T, types<Args...>> {
  101. static void call(Args...) {
  102. }
  103. };
  104. template <typename T, bool checked, bool clean_stack>
  105. struct constructor_match {
  106. T* obj_;
  107. reference* obj_lua_ref_;
  108. stack::stack_detail::undefined_metatable* p_umf_;
  109. constructor_match(T* obj_ptr, reference& obj_lua_ref, stack::stack_detail::undefined_metatable& umf)
  110. : obj_(obj_ptr), obj_lua_ref_(&obj_lua_ref), p_umf_(&umf) {
  111. }
  112. template <typename Fx, std::size_t I, typename... R, typename... Args>
  113. int operator()(types<Fx>, meta::index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
  114. detail::default_construct func {};
  115. int result = stack::call_into_lua<checked, clean_stack>(r, a, L, start, func, this->obj_);
  116. // construct userdata table
  117. // SPECIFICALLY, after we've created it successfully.
  118. // If the constructor exits for any reason we have to break things down...
  119. if constexpr (clean_stack) {
  120. obj_lua_ref_->push();
  121. (*this->p_umf_)();
  122. obj_lua_ref_->pop();
  123. }
  124. else {
  125. (*this->p_umf_)();
  126. }
  127. return result;
  128. }
  129. };
  130. namespace overload_detail {
  131. template <std::size_t... M, typename Match, typename... Args>
  132. inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
  133. return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types");
  134. }
  135. template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
  136. inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L,
  137. int fxarity, int start, Args&&... args) {
  138. typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
  139. typedef meta::tuple_types<typename traits::return_type> return_types;
  140. typedef typename traits::free_args_list args_list;
  141. // compile-time eliminate any functions that we know ahead of time are of improper arity
  142. if constexpr (!traits::runtime_variadics_t::value
  143. && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
  144. return overload_match_arity(types<Fxs...>(),
  145. std::index_sequence<In...>(),
  146. std::index_sequence<M...>(),
  147. std::forward<Match>(matchfx),
  148. L,
  149. fxarity,
  150. start,
  151. std::forward<Args>(args)...);
  152. }
  153. else {
  154. if constexpr (!traits::runtime_variadics_t::value) {
  155. if (traits::free_arity != fxarity) {
  156. return overload_match_arity(types<Fxs...>(),
  157. std::index_sequence<In...>(),
  158. std::index_sequence<traits::free_arity, M...>(),
  159. std::forward<Match>(matchfx),
  160. L,
  161. fxarity,
  162. start,
  163. std::forward<Args>(args)...);
  164. }
  165. }
  166. stack::record tracking {};
  167. if (!stack::stack_detail::check_types(args_list(), L, start, &no_panic, tracking)) {
  168. return overload_match_arity(types<Fxs...>(),
  169. std::index_sequence<In...>(),
  170. std::index_sequence<M...>(),
  171. std::forward<Match>(matchfx),
  172. L,
  173. fxarity,
  174. start,
  175. std::forward<Args>(args)...);
  176. }
  177. return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
  178. }
  179. }
  180. template <std::size_t... M, typename Match, typename... Args>
  181. inline int overload_match_arity_single(
  182. types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
  183. return overload_match_arity(types<>(),
  184. std::index_sequence<>(),
  185. std::index_sequence<M...>(),
  186. std::forward<Match>(matchfx),
  187. L,
  188. fxarity,
  189. start,
  190. std::forward<Args>(args)...);
  191. }
  192. template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
  193. inline int overload_match_arity_single(
  194. types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
  195. typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
  196. typedef meta::tuple_types<typename traits::return_type> return_types;
  197. typedef typename traits::free_args_list args_list;
  198. // compile-time eliminate any functions that we know ahead of time are of improper arity
  199. if constexpr (!traits::runtime_variadics_t::value
  200. && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
  201. return overload_match_arity(types<>(),
  202. std::index_sequence<>(),
  203. std::index_sequence<M...>(),
  204. std::forward<Match>(matchfx),
  205. L,
  206. fxarity,
  207. start,
  208. std::forward<Args>(args)...);
  209. }
  210. if constexpr (!traits::runtime_variadics_t::value) {
  211. if (traits::free_arity != fxarity) {
  212. return overload_match_arity(types<>(),
  213. std::index_sequence<>(),
  214. std::index_sequence<traits::free_arity, M...>(),
  215. std::forward<Match>(matchfx),
  216. L,
  217. fxarity,
  218. start,
  219. std::forward<Args>(args)...);
  220. }
  221. }
  222. return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
  223. }
  224. 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,
  225. typename... Args>
  226. inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx,
  227. lua_State* L, int fxarity, int start, Args&&... args) {
  228. typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
  229. typedef meta::tuple_types<typename traits::return_type> return_types;
  230. typedef typename traits::free_args_list args_list;
  231. // compile-time eliminate any functions that we know ahead of time are of improper arity
  232. if constexpr (!traits::runtime_variadics_t::value
  233. && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
  234. return overload_match_arity(types<Fx1, Fxs...>(),
  235. std::index_sequence<I1, In...>(),
  236. std::index_sequence<M...>(),
  237. std::forward<Match>(matchfx),
  238. L,
  239. fxarity,
  240. start,
  241. std::forward<Args>(args)...);
  242. }
  243. else {
  244. if constexpr (!traits::runtime_variadics_t::value) {
  245. if (traits::free_arity != fxarity) {
  246. return overload_match_arity(types<Fx1, Fxs...>(),
  247. std::index_sequence<I1, In...>(),
  248. std::index_sequence<traits::free_arity, M...>(),
  249. std::forward<Match>(matchfx),
  250. L,
  251. fxarity,
  252. start,
  253. std::forward<Args>(args)...);
  254. }
  255. }
  256. stack::record tracking {};
  257. if (!stack::stack_detail::check_types(args_list(), L, start, &no_panic, tracking)) {
  258. return overload_match_arity(types<Fx1, Fxs...>(),
  259. std::index_sequence<I1, In...>(),
  260. std::index_sequence<M...>(),
  261. std::forward<Match>(matchfx),
  262. L,
  263. fxarity,
  264. start,
  265. std::forward<Args>(args)...);
  266. }
  267. return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
  268. }
  269. }
  270. } // namespace overload_detail
  271. template <typename... Functions, typename Match, typename... Args>
  272. inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
  273. return overload_detail::overload_match_arity_single(types<Functions...>(),
  274. std::make_index_sequence<sizeof...(Functions)>(),
  275. std::index_sequence<>(),
  276. std::forward<Match>(matchfx),
  277. L,
  278. fxarity,
  279. start,
  280. std::forward<Args>(args)...);
  281. }
  282. template <typename... Functions, typename Match, typename... Args>
  283. inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) {
  284. int fxarity = lua_gettop(L) - (start - 1);
  285. return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
  286. }
  287. template <typename T, typename... TypeLists, typename Match, typename... Args>
  288. inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
  289. // use same overload resolution matching as all other parts of the framework
  290. return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(
  291. std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
  292. }
  293. template <typename T, bool checked, bool clean_stack, typename... TypeLists>
  294. inline int construct_trampolined(lua_State* L) {
  295. static const auto& meta = usertype_traits<T>::metatable();
  296. int argcount = lua_gettop(L);
  297. call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
  298. argcount -= static_cast<int>(syntax);
  299. T* obj = detail::usertype_allocate<T>(L);
  300. reference userdataref(L, -1);
  301. stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
  302. // put userdata at the first index
  303. lua_insert(L, 1);
  304. construct_match<T, TypeLists...>(constructor_match<T, checked, clean_stack>(obj, userdataref, umf), L, argcount, 1 + static_cast<int>(syntax));
  305. userdataref.push();
  306. return 1;
  307. }
  308. template <typename T, bool checked, bool clean_stack, typename... TypeLists>
  309. inline int construct(lua_State* L) {
  310. return detail::static_trampoline<&construct_trampolined<T, checked, clean_stack, TypeLists...>>(L);
  311. }
  312. template <typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename = void>
  313. struct agnostic_lua_call_wrapper {
  314. template <typename Fx, typename... Args>
  315. static int call(lua_State* L, Fx&& f, Args&&... args) {
  316. using uFx = meta::unqualified_t<Fx>;
  317. static constexpr bool is_ref = is_lua_reference_v<uFx>;
  318. if constexpr (is_ref) {
  319. if constexpr (is_index) {
  320. return stack::push(L, std::forward<Fx>(f), std::forward<Args>(args)...);
  321. }
  322. else {
  323. std::forward<Fx>(f) = stack::unqualified_get<F>(L, boost + (is_variable ? 3 : 1));
  324. return 0;
  325. }
  326. }
  327. else {
  328. using wrap = wrapper<uFx>;
  329. using traits_type = typename wrap::traits_type;
  330. using fp_t = typename traits_type::function_pointer_type;
  331. constexpr bool is_function_pointer_convertible = std::is_class_v<uFx> && std::is_convertible_v<std::decay_t<Fx>, fp_t>;
  332. if constexpr (is_function_pointer_convertible) {
  333. fp_t fx = f;
  334. return agnostic_lua_call_wrapper<fp_t, is_index, is_variable, checked, boost, clean_stack> {}.call(
  335. L, fx, std::forward<Args>(args)...);
  336. }
  337. else {
  338. using returns_list = typename wrap::returns_list;
  339. using args_list = typename wrap::free_args_list;
  340. using caller = typename wrap::caller;
  341. return stack::call_into_lua<checked, clean_stack>(
  342. returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...);
  343. }
  344. }
  345. }
  346. };
  347. template <typename T, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  348. struct agnostic_lua_call_wrapper<var_wrapper<T>, is_index, is_variable, checked, boost, clean_stack, C> {
  349. template <typename F>
  350. static int call(lua_State* L, F&& f) {
  351. if constexpr (is_index) {
  352. constexpr bool is_stack = is_stack_based_v<meta::unqualified_t<decltype(detail::unwrap(f.value()))>>;
  353. if constexpr (clean_stack && !is_stack) {
  354. lua_settop(L, 0);
  355. }
  356. return stack::push_reference(L, detail::unwrap(f.value()));
  357. }
  358. else {
  359. if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
  360. (void)f;
  361. return luaL_error(L, "sol: cannot write to a readonly (const) variable");
  362. }
  363. else {
  364. using R = meta::unwrapped_t<T>;
  365. if constexpr (std::is_assignable_v<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>) {
  366. detail::unwrap(f.value()) = stack::unqualified_get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1));
  367. if (clean_stack) {
  368. lua_settop(L, 0);
  369. }
  370. return 0;
  371. }
  372. else {
  373. return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
  374. }
  375. }
  376. }
  377. }
  378. };
  379. template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  380. struct agnostic_lua_call_wrapper<lua_CFunction_ref, is_index, is_variable, checked, boost, clean_stack, C> {
  381. static int call(lua_State* L, lua_CFunction_ref f) {
  382. return f(L);
  383. }
  384. };
  385. template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  386. struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, clean_stack, C> {
  387. static int call(lua_State* L, lua_CFunction f) {
  388. return f(L);
  389. }
  390. };
  391. #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
  392. template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  393. struct agnostic_lua_call_wrapper<detail::lua_CFunction_noexcept, is_index, is_variable, checked, boost, clean_stack, C> {
  394. static int call(lua_State* L, detail::lua_CFunction_noexcept f) {
  395. return f(L);
  396. }
  397. };
  398. #endif // noexcept function types
  399. template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  400. struct agnostic_lua_call_wrapper<detail::no_prop, is_index, is_variable, checked, boost, clean_stack, C> {
  401. static int call(lua_State* L, const detail::no_prop&) {
  402. return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
  403. }
  404. };
  405. template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  406. struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, clean_stack, C> {
  407. static int call(lua_State* L, const no_construction&) {
  408. return function_detail::no_construction_error(L);
  409. }
  410. };
  411. template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  412. struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, clean_stack, C> {
  413. static int call(lua_State*, const bases<Args...>&) {
  414. // Uh. How did you even call this, lul
  415. return 0;
  416. }
  417. };
  418. template <typename T, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  419. struct agnostic_lua_call_wrapper<std::reference_wrapper<T>, is_index, is_variable, checked, boost, clean_stack, C> {
  420. static int call(lua_State* L, std::reference_wrapper<T> f) {
  421. agnostic_lua_call_wrapper<T, is_index, is_variable, checked, boost, clean_stack> alcw {};
  422. return alcw.call(L, f.get());
  423. }
  424. };
  425. template <typename T, typename F, bool is_index, bool is_variable, bool checked = detail::default_safe_function_calls, int boost = 0,
  426. bool clean_stack = true, typename = void>
  427. struct lua_call_wrapper {
  428. template <typename Fx, typename... Args>
  429. static int call(lua_State* L, Fx&& fx, Args&&... args) {
  430. if constexpr (std::is_member_function_pointer_v<F>) {
  431. using wrap = wrapper<F>;
  432. using object_type = typename wrap::object_type;
  433. if constexpr (sizeof...(Args) < 1) {
  434. using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
  435. static_assert(std::is_base_of_v<object_type, Ta>,
  436. "It seems like you might have accidentally bound a class type with a member function method that does not correspond to the "
  437. "class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one class \"T\" "
  438. "but then bind member methods from a complete unrelated class. Check things over!");
  439. #if SOL_IS_ON(SOL_SAFE_USERTYPE)
  440. auto maybeo = stack::check_get<Ta*>(L, 1);
  441. if (!maybeo || maybeo.value() == nullptr) {
  442. return luaL_error(L,
  443. "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are "
  444. "preceeded by the "
  445. "actual object with '.' syntax)");
  446. }
  447. object_type* o = static_cast<object_type*>(maybeo.value());
  448. return call(L, std::forward<Fx>(fx), *o);
  449. #else
  450. object_type& o = static_cast<object_type&>(*stack::unqualified_get<non_null<Ta*>>(L, 1));
  451. return call(L, std::forward<Fx>(fx), o);
  452. #endif // Safety
  453. }
  454. else {
  455. using returns_list = typename wrap::returns_list;
  456. using args_list = typename wrap::args_list;
  457. using caller = typename wrap::caller;
  458. return stack::call_into_lua<checked, clean_stack>(
  459. returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), std::forward<Args>(args)...);
  460. }
  461. }
  462. else if constexpr (std::is_member_object_pointer_v<F>) {
  463. using wrap = wrapper<F>;
  464. using object_type = typename wrap::object_type;
  465. if constexpr (is_index) {
  466. if constexpr (sizeof...(Args) < 1) {
  467. using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
  468. static_assert(std::is_base_of_v<object_type, Ta>,
  469. "It seems like you might have accidentally bound a class type with a member function method that does not correspond "
  470. "to the class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one "
  471. "class \"T\" but then bind member methods from a complete unrelated class. Check things over!");
  472. #if SOL_IS_ON(SOL_SAFE_USERTYPE)
  473. auto maybeo = stack::check_get<Ta*>(L, 1);
  474. if (!maybeo || maybeo.value() == nullptr) {
  475. if (is_variable) {
  476. return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");
  477. }
  478. return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)");
  479. }
  480. object_type* o = static_cast<object_type*>(maybeo.value());
  481. return call(L, std::forward<Fx>(fx), *o);
  482. #else
  483. object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
  484. return call(L, std::forward<Fx>(fx), o);
  485. #endif // Safety
  486. }
  487. else {
  488. using returns_list = typename wrap::returns_list;
  489. using caller = typename wrap::caller;
  490. return stack::call_into_lua<checked, clean_stack>(returns_list(),
  491. types<>(),
  492. L,
  493. boost + (is_variable ? 3 : 2),
  494. caller(),
  495. std::forward<Fx>(fx),
  496. std::forward<Args>(args)...);
  497. }
  498. }
  499. else {
  500. using traits_type = lua_bind_traits<F>;
  501. using return_type = typename traits_type::return_type;
  502. constexpr bool ret_is_const = std::is_const_v<std::remove_reference_t<return_type>>;
  503. if constexpr (ret_is_const) {
  504. (void)fx;
  505. (void)detail::swallow { 0, (static_cast<void>(args), 0)... };
  506. return luaL_error(L, "sol: cannot write to a readonly (const) variable");
  507. }
  508. else {
  509. using u_return_type = meta::unqualified_t<return_type>;
  510. constexpr bool is_assignable = std::is_copy_assignable_v<u_return_type> || std::is_array_v<u_return_type>;
  511. if constexpr (!is_assignable) {
  512. (void)fx;
  513. (void)detail::swallow { 0, ((void)args, 0)... };
  514. return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
  515. }
  516. else {
  517. using args_list = typename wrap::args_list;
  518. using caller = typename wrap::caller;
  519. if constexpr (sizeof...(Args) > 0) {
  520. return stack::call_into_lua<checked, clean_stack>(types<void>(),
  521. args_list(),
  522. L,
  523. boost + (is_variable ? 3 : 2),
  524. caller(),
  525. std::forward<Fx>(fx),
  526. std::forward<Args>(args)...);
  527. }
  528. else {
  529. using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
  530. #if SOL_IS_ON(SOL_SAFE_USERTYPE)
  531. auto maybeo = stack::check_get<Ta*>(L, 1);
  532. if (!maybeo || maybeo.value() == nullptr) {
  533. if (is_variable) {
  534. return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)");
  535. }
  536. return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)");
  537. }
  538. object_type* po = static_cast<object_type*>(maybeo.value());
  539. object_type& o = *po;
  540. #else
  541. object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
  542. #endif // Safety
  543. return stack::call_into_lua<checked, clean_stack>(
  544. types<void>(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), o);
  545. }
  546. }
  547. }
  548. }
  549. }
  550. else {
  551. agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost, clean_stack> alcw {};
  552. return alcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  553. }
  554. }
  555. };
  556. template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  557. struct lua_call_wrapper<T, readonly_wrapper<F>, is_index, is_variable, checked, boost, clean_stack, C> {
  558. using traits_type = lua_bind_traits<F>;
  559. using wrap = wrapper<F>;
  560. using object_type = typename wrap::object_type;
  561. static int call(lua_State* L, readonly_wrapper<F>&& rw) {
  562. if constexpr (!is_index) {
  563. (void)rw;
  564. return luaL_error(L, "sol: cannot write to a sol::readonly variable");
  565. }
  566. else {
  567. lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
  568. return lcw.call(L, std::move(rw.value()));
  569. }
  570. }
  571. static int call(lua_State* L, readonly_wrapper<F>&& rw, object_type& o) {
  572. if constexpr (!is_index) {
  573. (void)o;
  574. return call(L, std::move(rw));
  575. }
  576. else {
  577. lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
  578. return lcw.call(L, rw.value(), o);
  579. }
  580. }
  581. static int call(lua_State* L, const readonly_wrapper<F>& rw) {
  582. if constexpr (!is_index) {
  583. (void)rw;
  584. return luaL_error(L, "sol: cannot write to a sol::readonly variable");
  585. }
  586. else {
  587. lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
  588. return lcw.call(L, rw.value());
  589. }
  590. }
  591. static int call(lua_State* L, const readonly_wrapper<F>& rw, object_type& o) {
  592. if constexpr (!is_index) {
  593. (void)o;
  594. return call(L, rw);
  595. }
  596. else {
  597. lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
  598. return lcw.call(L, rw.value(), o);
  599. }
  600. }
  601. };
  602. template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  603. struct lua_call_wrapper<T, constructor_list<Args...>, is_index, is_variable, checked, boost, clean_stack, C> {
  604. typedef constructor_list<Args...> F;
  605. static int call(lua_State* L, F&) {
  606. const auto& meta = usertype_traits<T>::metatable();
  607. int argcount = lua_gettop(L);
  608. call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
  609. argcount -= static_cast<int>(syntax);
  610. T* obj = detail::usertype_allocate<T>(L);
  611. reference userdataref(L, -1);
  612. stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
  613. // put userdata at the first index
  614. lua_insert(L, 1);
  615. // Because of the way constructors work,
  616. // we have to kill the data, but only if the cosntructor is successfulyl invoked...
  617. // if it's not successfully invoked and we panic,
  618. // we cannot actually deallcoate/delete the data.
  619. construct_match<T, Args...>(
  620. constructor_match<T, checked, clean_stack>(obj, userdataref, umf), L, argcount, boost + 1 + 1 + static_cast<int>(syntax));
  621. userdataref.push();
  622. return 1;
  623. }
  624. };
  625. template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  626. struct lua_call_wrapper<T, constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, clean_stack, C> {
  627. typedef constructor_wrapper<Cxs...> F;
  628. struct onmatch {
  629. template <typename Fx, std::size_t I, typename... R, typename... Args>
  630. int operator()(types<Fx>, meta::index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
  631. const auto& meta = usertype_traits<T>::metatable();
  632. T* obj = detail::usertype_allocate<T>(L);
  633. reference userdataref(L, -1);
  634. stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
  635. umf();
  636. auto& func = std::get<I>(f.functions);
  637. // put userdata at the first index
  638. lua_insert(L, 1);
  639. stack::call_into_lua<checked, clean_stack>(r, a, L, boost + 1 + start, func, detail::implicit_wrapper<T>(obj));
  640. userdataref.push();
  641. return 1;
  642. }
  643. };
  644. static int call(lua_State* L, F& f) {
  645. call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1);
  646. int syntaxval = static_cast<int>(syntax);
  647. int argcount = lua_gettop(L) - syntaxval;
  648. return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
  649. }
  650. };
  651. template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  652. struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, clean_stack, C> {
  653. template <typename F>
  654. static int call(lua_State* L, F&& f) {
  655. if constexpr (std::is_void_v<Fx>) {
  656. return detail::usertype_alloc_destroy<T>(L);
  657. }
  658. else {
  659. using uFx = meta::unqualified_t<Fx>;
  660. lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack> lcw {};
  661. return lcw.call(L, std::forward<F>(f).fx);
  662. }
  663. }
  664. };
  665. template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  666. struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> {
  667. typedef overload_set<Fs...> F;
  668. struct on_match {
  669. template <typename Fx, std::size_t I, typename... R, typename... Args>
  670. int operator()(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) {
  671. auto& f = std::get<I>(fx.functions);
  672. return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost> {}.call(L, f);
  673. }
  674. };
  675. static int call(lua_State* L, F& fx) {
  676. return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx);
  677. }
  678. };
  679. template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  680. struct lua_call_wrapper<T, factory_wrapper<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> {
  681. typedef factory_wrapper<Fs...> F;
  682. struct on_match {
  683. template <typename Fx, std::size_t I, typename... R, typename... Args>
  684. int operator()(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) {
  685. auto& f = std::get<I>(fx.functions);
  686. return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost, clean_stack> {}.call(L, f);
  687. }
  688. };
  689. static int call(lua_State* L, F& fx) {
  690. return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx);
  691. }
  692. };
  693. template <typename T, typename R, typename W, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  694. struct lua_call_wrapper<T, property_wrapper<R, W>, is_index, is_variable, checked, boost, clean_stack, C> {
  695. typedef meta::conditional_t<is_index, R, W> P;
  696. typedef meta::unqualified_t<P> U;
  697. typedef wrapper<U> wrap;
  698. typedef lua_bind_traits<U> traits_type;
  699. typedef meta::unqualified_t<typename traits_type::template arg_at<0>> object_type;
  700. template <typename F, typename... Args>
  701. static int call(lua_State* L, F&& f, Args&&... args) {
  702. constexpr bool is_specialized = meta::any<std::is_same<U, detail::no_prop>,
  703. meta::is_specialization_of<U, var_wrapper>,
  704. meta::is_specialization_of<U, constructor_wrapper>,
  705. meta::is_specialization_of<U, constructor_list>,
  706. std::is_member_pointer<U>>::value;
  707. if constexpr (is_specialized) {
  708. if constexpr (is_index) {
  709. decltype(auto) p = f.read();
  710. lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost, clean_stack> lcw {};
  711. return lcw.call(L, p, std::forward<Args>(args)...);
  712. }
  713. else {
  714. decltype(auto) p = f.write();
  715. lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost, clean_stack> lcw {};
  716. return lcw.call(L, p, std::forward<Args>(args)...);
  717. }
  718. }
  719. else {
  720. constexpr bool non_class_object_type = meta::any<std::is_void<object_type>,
  721. meta::boolean<lua_type_of<meta::unwrap_unqualified_t<object_type>>::value != type::userdata>>::value;
  722. if constexpr (non_class_object_type) {
  723. // The type being void means we don't have any arguments, so it might be a free functions?
  724. using args_list = typename traits_type::free_args_list;
  725. using returns_list = typename wrap::returns_list;
  726. using caller = typename wrap::caller;
  727. if constexpr (is_index) {
  728. decltype(auto) pf = f.read();
  729. return stack::call_into_lua<checked, clean_stack>(
  730. returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf);
  731. }
  732. else {
  733. decltype(auto) pf = f.write();
  734. return stack::call_into_lua<checked, clean_stack>(
  735. returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf);
  736. }
  737. }
  738. else {
  739. using args_list = meta::pop_front_type_t<typename traits_type::free_args_list>;
  740. using Ta = T;
  741. using Oa = std::remove_pointer_t<object_type>;
  742. #if SOL_IS_ON(SOL_SAFE_USERTYPE)
  743. auto maybeo = stack::check_get<Ta*>(L, 1);
  744. if (!maybeo || maybeo.value() == nullptr) {
  745. if (is_variable) {
  746. return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");
  747. }
  748. return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)");
  749. }
  750. Oa* o = static_cast<Oa*>(maybeo.value());
  751. #else
  752. Oa* o = static_cast<Oa*>(stack::get<non_null<Ta*>>(L, 1));
  753. #endif // Safety
  754. using returns_list = typename wrap::returns_list;
  755. using caller = typename wrap::caller;
  756. if constexpr (is_index) {
  757. decltype(auto) pf = f.read();
  758. return stack::call_into_lua<checked, clean_stack>(
  759. returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper<Oa>(*o));
  760. }
  761. else {
  762. decltype(auto) pf = f.write();
  763. return stack::call_into_lua<checked, clean_stack>(
  764. returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper<Oa>(*o));
  765. }
  766. }
  767. }
  768. }
  769. };
  770. template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  771. struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, clean_stack, C> {
  772. typedef protect_t<V> F;
  773. template <typename... Args>
  774. static int call(lua_State* L, F& fx, Args&&... args) {
  775. return lua_call_wrapper<T, V, is_index, is_variable, true, boost, clean_stack> {}.call(L, fx.value, std::forward<Args>(args)...);
  776. }
  777. };
  778. template <typename T, typename F, typename... Policies, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  779. struct lua_call_wrapper<T, policy_wrapper<F, Policies...>, is_index, is_variable, checked, boost, clean_stack, C> {
  780. typedef policy_wrapper<F, Policies...> P;
  781. template <std::size_t... In>
  782. static int call(std::index_sequence<In...>, lua_State* L, P& fx) {
  783. int pushed = lua_call_wrapper<T, F, is_index, is_variable, checked, boost, false, C> {}.call(L, fx.value);
  784. (void)detail::swallow { int(), (policy_detail::handle_policy(std::get<In>(fx.policies), L, pushed), int())... };
  785. return pushed;
  786. }
  787. static int call(lua_State* L, P& fx) {
  788. typedef typename P::indices indices;
  789. return call(indices(), L, fx);
  790. }
  791. };
  792. template <typename T, typename Y, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  793. struct lua_call_wrapper<T, yielding_t<Y>, is_index, is_variable, checked, boost, clean_stack, C> {
  794. template <typename F>
  795. static int call(lua_State* L, F&& f) {
  796. return lua_call_wrapper<T, meta::unqualified_t<Y>, is_index, is_variable, checked, boost, clean_stack> {}.call(L, f.func);
  797. }
  798. };
  799. template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
  800. struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> {
  801. static int call(lua_State* L, const function_arguments<Sig, P>& f) {
  802. lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw {};
  803. return lcw.call(L, std::get<0>(f.arguments));
  804. }
  805. static int call(lua_State* L, function_arguments<Sig, P>& f) {
  806. lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw {};
  807. return lcw.call(L, std::get<0>(f.arguments));
  808. }
  809. static int call(lua_State* L, function_arguments<Sig, P>&& f) {
  810. lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw {};
  811. return lcw.call(L, std::get<0>(std::move(f.arguments)));
  812. }
  813. };
  814. template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true,
  815. typename Fx, typename... Args>
  816. inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) {
  817. using uFx = meta::unqualified_t<Fx>;
  818. if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) {
  819. using real_fx = meta::unqualified_t<decltype(std::forward<Fx>(fx).func)>;
  820. lua_call_wrapper<T, real_fx, is_index, is_variable, checked, boost, clean_stack> lcw {};
  821. return lcw.call(L, std::forward<Fx>(fx).func, std::forward<Args>(args)...);
  822. }
  823. else {
  824. lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack> lcw {};
  825. return lcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  826. }
  827. }
  828. template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls,
  829. bool clean_stack = true>
  830. inline int call_user(lua_State* L) {
  831. auto& fx = stack::unqualified_get<user<F>>(L, upvalue_index(start));
  832. using uFx = meta::unqualified_t<F>;
  833. int nr = call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx);
  834. if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) {
  835. return lua_yield(L, nr);
  836. }
  837. else {
  838. return nr;
  839. }
  840. }
  841. template <typename T, typename = void>
  842. struct is_var_bind : std::false_type { };
  843. template <typename T>
  844. struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type { };
  845. template <typename T>
  846. struct is_var_bind<T, std::enable_if_t<is_lua_reference_or_proxy<T>::value>> : std::true_type { };
  847. template <>
  848. struct is_var_bind<detail::no_prop> : std::true_type { };
  849. template <typename R, typename W>
  850. struct is_var_bind<property_wrapper<R, W>> : std::true_type { };
  851. template <typename T>
  852. struct is_var_bind<var_wrapper<T>> : std::true_type { };
  853. template <typename T>
  854. struct is_var_bind<readonly_wrapper<T>> : is_var_bind<meta::unqualified_t<T>> { };
  855. template <typename F, typename... Policies>
  856. struct is_var_bind<policy_wrapper<F, Policies...>> : is_var_bind<meta::unqualified_t<F>> { };
  857. } // namespace call_detail
  858. template <typename T>
  859. struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> { };
  860. template <typename T>
  861. using is_var_wrapper = meta::is_specialization_of<T, var_wrapper>;
  862. template <typename T>
  863. struct is_function_binding : meta::neg<is_variable_binding<T>> { };
  864. } // namespace sol
  865. #endif // SOL_CALL_HPP