ChaiScript / ChaiScript
1
// This file is distributed under the BSD License.
2
// See "license.txt" for details.
3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5
// http://www.chaiscript.com
6

7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9

10

11
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
12
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
13

14
#include <functional>
15
#include <stdexcept>
16
#include <vector>
17
#include <array>
18

19
#include "../chaiscript_defines.hpp"
20
#include "boxed_cast.hpp"
21
#include "boxed_value.hpp"
22
#include "handle_return.hpp"
23
#include "type_info.hpp"
24
#include "function_params.hpp"
25

26
namespace chaiscript {
27
class Type_Conversions_State;
28
namespace exception {
29
class bad_boxed_cast;
30
}  // namespace exception
31
}  // namespace chaiscript
32

33
namespace chaiscript
34
{
35
  namespace exception
36
  {
37
    /**
38
     * Exception thrown when there is a mismatch in number of
39
     * parameters during Proxy_Function execution
40
     */
41
    struct arity_error : std::range_error
42
    {
43 1
      arity_error(int t_got, int t_expected)
44 1
        : std::range_error("Function dispatch arity mismatch"),
45 1
        got(t_got), expected(t_expected)
46
      {
47
      }
48

49
      arity_error(const arity_error &) = default;
50

51 1
      ~arity_error() noexcept override = default;
52

53
      int got;
54
      int expected;
55
    };
56
  }
57

58
  namespace dispatch
59
  {
60
    namespace detail
61
    {
62
      /**
63
       * Used by Proxy_Function_Impl to return a list of all param types
64
       * it contains.
65
       */
66
      template<typename Ret, typename ... Params>
67 1
        std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
68
        {
69
          /// \note somehow this is responsible for a large part of the code generation
70 1
          return { user_type<Ret>(), user_type<Params>()... };
71
        }
72

73

74
      /**
75
       * Used by Proxy_Function_Impl to determine if it is equivalent to another
76
       * Proxy_Function_Impl object. This function is primarily used to prevent
77
       * registration of two functions with the exact same signatures
78
       */
79
      template<typename Ret, typename ... Params>
80 1
        bool compare_types_cast(Ret (*)(Params...),
81
             const chaiscript::Function_Params &params, const Type_Conversions_State &t_conversions) noexcept
82
        {
83
          try {
84 1
            std::vector<Boxed_Value>::size_type i = 0;
85 1
            ( boxed_cast<Params>(params[i++], &t_conversions), ... );
86 1
            return true;
87 1
          } catch (const exception::bad_boxed_cast &) {
88 1
            return false;
89
          }
90
        }
91

92

93
      template<typename Callable, typename Ret, typename ... Params, size_t ... I>
94 1
        Ret call_func(Ret (*)(Params...), 
95
                      std::index_sequence<I...>, const Callable &f,
96
                      [[maybe_unused]] const chaiscript::Function_Params &params, 
97
                      [[maybe_unused]] const Type_Conversions_State &t_conversions)
98
        {
99 1
          return f(boxed_cast<Params>(params[I], &t_conversions)...);
100
        }
101

102

103
      /// Used by Proxy_Function_Impl to perform typesafe execution of a function.
104
      /// The function attempts to unbox each parameter to the expected type.
105
      /// if any unboxing fails the execution of the function fails and
106
      /// the bad_boxed_cast is passed up to the caller.
107
      template<typename Callable, typename Ret, typename ... Params>
108
        Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f,
109
            const chaiscript::Function_Params &params, const Type_Conversions_State &t_conversions)
110
        {
111
          if constexpr (std::is_same_v<Ret, void>) {
112
            call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
113
            return Handle_Return<void>::handle();
114
          } else {
115
            return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
116
          }
117
        }
118

119
    }
120
  }
121

122
}
123

124

125
#endif

Read our documentation on viewing source code .

Loading