proxy_functions_detail.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // This file is distributed under the BSD License.
  2. // See "license.txt" for details.
  3. // Copyright 2009-2012, Jonathan Turner ([email protected])
  4. // Copyright 2009-2017, Jason Turner ([email protected])
  5. // http://www.chaiscript.com
  6. // This is an open source non-commercial project. Dear PVS-Studio, please check it.
  7. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
  8. #ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
  9. #define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
  10. #include <functional>
  11. #include <stdexcept>
  12. #include <vector>
  13. #include <array>
  14. #include "../chaiscript_defines.hpp"
  15. #include "boxed_cast.hpp"
  16. #include "boxed_value.hpp"
  17. #include "handle_return.hpp"
  18. #include "type_info.hpp"
  19. #include "callable_traits.hpp"
  20. namespace chaiscript {
  21. class Type_Conversions_State;
  22. namespace exception {
  23. class bad_boxed_cast;
  24. } // namespace exception
  25. } // namespace chaiscript
  26. namespace chaiscript
  27. {
  28. namespace exception
  29. {
  30. /**
  31. * Exception thrown when there is a mismatch in number of
  32. * parameters during Proxy_Function execution
  33. */
  34. struct arity_error : std::range_error
  35. {
  36. arity_error(int t_got, int t_expected)
  37. : std::range_error("Function dispatch arity mismatch"),
  38. got(t_got), expected(t_expected)
  39. {
  40. }
  41. arity_error(const arity_error &) = default;
  42. ~arity_error() noexcept override = default;
  43. int got;
  44. int expected;
  45. };
  46. }
  47. namespace dispatch
  48. {
  49. namespace detail
  50. {
  51. /**
  52. * Used by Proxy_Function_Impl to return a list of all param types
  53. * it contains.
  54. */
  55. template<typename Ret, typename ... Params>
  56. std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
  57. {
  58. /// \note somehow this is responsible for a large part of the code generation
  59. return { user_type<Ret>(), user_type<Params>()... };
  60. }
  61. /**
  62. * Used by Proxy_Function_Impl to determine if it is equivalent to another
  63. * Proxy_Function_Impl object. This function is primarily used to prevent
  64. * registration of two functions with the exact same signatures
  65. */
  66. template<typename Ret, typename ... Params>
  67. bool compare_types_cast(Ret (*)(Params...),
  68. const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
  69. {
  70. try {
  71. std::vector<Boxed_Value>::size_type i = 0;
  72. (void)i;
  73. (void)params; (void)t_conversions;
  74. // this is ok because the order of evaluation of initializer lists is well defined
  75. (void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...};
  76. return true;
  77. } catch (const exception::bad_boxed_cast &) {
  78. return false;
  79. }
  80. }
  81. template<typename Callable, typename Ret, typename ... Params, size_t ... I>
  82. Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &,
  83. std::index_sequence<I...>, const Callable &f,
  84. const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
  85. {
  86. (void)params; (void)t_conversions;
  87. return f(boxed_cast<Params>(params[I], &t_conversions)...);
  88. }
  89. /// Used by Proxy_Function_Impl to perform typesafe execution of a function.
  90. /// The function attempts to unbox each parameter to the expected type.
  91. /// if any unboxing fails the execution of the function fails and
  92. /// the bad_boxed_cast is passed up to the caller.
  93. template<typename Callable, typename Ret, typename ... Params>
  94. Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
  95. const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
  96. {
  97. return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
  98. }
  99. template<typename Callable, typename ... Params>
  100. Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<void (Params...)> &sig, const Callable &f,
  101. const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
  102. {
  103. call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
  104. #ifdef CHAISCRIPT_MSVC
  105. #pragma warning(push)
  106. #pragma warning(disable : 4702)
  107. #endif
  108. // MSVC is reporting that this is unreachable code - and it's wrong.
  109. return Handle_Return<void>::handle();
  110. #ifdef CHAISCRIPT_MSVC
  111. #pragma warning(pop)
  112. #endif
  113. }
  114. }
  115. }
  116. }
  117. #endif