function_call_detail.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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_FUNCTION_CALL_DETAIL_HPP_
  9. #define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
  10. #include <functional>
  11. #include <memory>
  12. #include <string>
  13. #include <type_traits>
  14. #include <vector>
  15. #include "boxed_cast.hpp"
  16. #include "boxed_number.hpp"
  17. #include "boxed_value.hpp"
  18. #include "type_conversions.hpp"
  19. #include "proxy_functions.hpp"
  20. namespace chaiscript
  21. {
  22. namespace dispatch
  23. {
  24. namespace detail
  25. {
  26. /// Internal helper class for handling the return
  27. /// value of a build_function_caller
  28. template<typename Ret, bool is_arithmetic>
  29. struct Function_Caller_Ret
  30. {
  31. static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
  32. const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
  33. {
  34. if (t_conversions != nullptr) {
  35. return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
  36. } else {
  37. Type_Conversions conv;
  38. Type_Conversions_State state(conv, conv.conversion_saves());
  39. return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, state), t_conversions);
  40. }
  41. }
  42. };
  43. /**
  44. * Specialization for arithmetic return types
  45. */
  46. template<typename Ret>
  47. struct Function_Caller_Ret<Ret, true>
  48. {
  49. static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
  50. const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
  51. {
  52. if (t_conversions != nullptr) {
  53. return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
  54. } else {
  55. Type_Conversions conv;
  56. Type_Conversions_State state(conv, conv.conversion_saves());
  57. return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as<Ret>();
  58. }
  59. }
  60. };
  61. /**
  62. * Specialization for void return types
  63. */
  64. template<>
  65. struct Function_Caller_Ret<void, false>
  66. {
  67. static void call(const std::vector<Const_Proxy_Function> &t_funcs,
  68. const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
  69. {
  70. if (t_conversions != nullptr) {
  71. dispatch::dispatch(t_funcs, params, *t_conversions);
  72. } else {
  73. Type_Conversions conv;
  74. Type_Conversions_State state(conv, conv.conversion_saves());
  75. dispatch::dispatch(t_funcs, params, state);
  76. }
  77. }
  78. };
  79. /**
  80. * used internally for unwrapping a function call's types
  81. */
  82. template<typename Ret, typename ... Param>
  83. struct Build_Function_Caller_Helper
  84. {
  85. Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions *t_conversions)
  86. : m_funcs(std::move(t_funcs)),
  87. m_conversions(t_conversions)
  88. {
  89. }
  90. template<typename ... P>
  91. Ret operator()(P&& ... param)
  92. {
  93. if (m_conversions) {
  94. Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
  95. return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
  96. box<P>(std::forward<P>(param))...
  97. }, &state
  98. );
  99. } else {
  100. return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
  101. box<P>(std::forward<P>(param))...
  102. }, nullptr
  103. );
  104. }
  105. }
  106. template<typename P, typename Q>
  107. static auto box(Q&& q) -> typename std::enable_if<std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
  108. {
  109. return Boxed_Value(std::ref(std::forward<Q>(q)));
  110. }
  111. template<typename P, typename Q>
  112. static auto box(Q&& q) -> typename std::enable_if<!std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
  113. {
  114. return Boxed_Value(std::forward<Q>(q));
  115. }
  116. template<typename P>
  117. static Boxed_Value box(Boxed_Value bv)
  118. {
  119. return bv;
  120. }
  121. std::vector<Const_Proxy_Function> m_funcs;
  122. const Type_Conversions *m_conversions;
  123. };
  124. /// \todo what happens if t_conversions is deleted out from under us?!
  125. template<typename Ret, typename ... Params>
  126. std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
  127. {
  128. /*
  129. if (funcs.size() == 1)
  130. {
  131. std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
  132. std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
  133. (funcs[0]);
  134. if (pfi)
  135. {
  136. return pfi->internal_function();
  137. }
  138. // looks like this either wasn't a Proxy_Function_Impl or the types didn't match
  139. // we cannot make any other guesses or assumptions really, so continuing
  140. }
  141. */
  142. return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
  143. }
  144. }
  145. }
  146. }
  147. #endif