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
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
8
#define CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
9

10
#include <cassert>
11
#include <map>
12
#include <memory>
13
#include <string>
14
#include <typeinfo>
15
#include <utility>
16
#include <vector>
17

18
#include "../chaiscript_defines.hpp"
19
#include "boxed_cast.hpp"
20
#include "boxed_cast_helper.hpp"
21
#include "boxed_value.hpp"
22
#include "proxy_functions.hpp"
23
#include "type_info.hpp"
24
#include "dynamic_object.hpp"
25

26
namespace chaiscript {
27
class Type_Conversions;
28
namespace dispatch {
29
class Proxy_Function_Base;
30
}  // namespace dispatch
31
}  // namespace chaiscript
32

33
namespace chaiscript
34
{
35
  namespace dispatch
36
  {
37
    namespace detail
38
    {
39
      /// A Proxy_Function implementation designed for calling a function
40
      /// that is automatically guarded based on the first param based on the
41
      /// param's type name
42
      class Dynamic_Object_Function final : public Proxy_Function_Base
43
      {
44
        public:
45 1
          Dynamic_Object_Function(
46
              std::string t_type_name,
47
              const Proxy_Function &t_func,
48
              bool t_is_attribute = false)
49 1
            : Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
50 1
              m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>()),
51 1
              m_is_attribute(t_is_attribute)
52
          {
53
            assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
54
                && "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
55
          }
56

57 1
          Dynamic_Object_Function(
58
              std::string t_type_name,
59
              const Proxy_Function &t_func,
60
              const Type_Info &t_ti,
61
              bool t_is_attribute = false)
62 1
            : Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
63 1
              m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>()),
64 1
              m_is_attribute(t_is_attribute)
65
          {
66
            assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
67
                && "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
68
          }
69

70

71
          Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
72
          Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
73

74 1
          bool operator==(const Proxy_Function_Base &f) const noexcept override
75
          {
76
            if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
77
            {
78 1
              return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
79
            } else {
80 1
              return false;
81
            }
82
          }
83

84 1
          bool is_attribute_function() const noexcept override { return m_is_attribute; } 
85

86 1
          bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
87
          {
88 1
            if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
89
            {
90 1
              return m_func->call_match(vals, t_conversions);
91
            } else {
92 1
              return false;
93
            }
94
          }
95

96 0
          std::vector<Const_Proxy_Function> get_contained_functions() const override
97
          {
98 0
            return {m_func};
99
          }
100

101
        protected:
102 1
          Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
103
          {
104 1
            if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
105
            {
106 1
              return (*m_func)(params, t_conversions);
107
            } else {
108 1
              throw exception::guard_error();
109
            } 
110
          }
111

112 1
          bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const noexcept override
113
          {
114 1
            return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
115
          }
116

117
        private:
118 1
          static std::vector<Type_Info> build_param_types(
119
              const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
120
          {
121 1
            std::vector<Type_Info> types(t_inner_types);
122

123
            assert(types.size() > 1);
124
            //assert(types[1].bare_equal(user_type<Boxed_Value>()));
125 1
            types[1] = t_objectti;
126 1
            return types;
127
          }
128

129 1
          bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
130
              const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const noexcept
131
          {
132 1
            if (bv.get_type_info().bare_equal(m_doti))
133
            {
134
              try {
135 1
                const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
136 1
                return name == "Dynamic_Object" || d.get_type_name() == name;
137 0
              } catch (const std::bad_cast &) {
138 0
                return false;
139
              } 
140
            } else {
141 1
              if (ti)
142
              {
143 1
                return bv.get_type_info().bare_equal(*ti);
144
              } else {
145 1
                return false;
146
              }
147
            }
148

149
          }
150

151 1
          bool dynamic_object_typename_match(const Function_Params &bvs, const std::string &name,
152
              const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const noexcept
153
          {
154 1
            if (!bvs.empty())
155
            {
156 1
              return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
157
            } else {
158 0
              return false;
159
            }
160
          }
161

162
          std::string m_type_name;
163
          Proxy_Function m_func;
164
          std::unique_ptr<Type_Info> m_ti;
165
          const Type_Info m_doti;
166
          const bool m_is_attribute;
167
      };
168

169

170
      /**
171
       * A Proxy_Function implementation designed for creating a new
172
       * Dynamic_Object
173
       * that is automatically guarded based on the first param based on the
174
       * param's type name
175
       */
176
      class Dynamic_Object_Constructor final : public Proxy_Function_Base
177
      {
178
        public:
179 1
          Dynamic_Object_Constructor(
180
              std::string t_type_name,
181
              const Proxy_Function &t_func)
182 1
            : Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
183 1
              m_type_name(std::move(t_type_name)), m_func(t_func)
184
          {
185
            assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
186
                && "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
187
          }
188

189 1
          static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
190
          {
191 1
            auto begin = tl.begin();
192 1
            auto end = tl.end();
193

194 1
            if (begin != end)
195
            {
196 1
              ++begin;
197
            }
198

199 1
            return std::vector<Type_Info>(begin, end);
200
          }
201

202 1
          bool operator==(const Proxy_Function_Base &f) const noexcept override
203
          {
204
            const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
205 1
            return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
206
          }
207

208 0
          bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const override
209
          {
210 0
            std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
211 0
            new_vals.insert(new_vals.end(), vals.begin(), vals.end());
212

213 0
            return m_func->call_match(Function_Params{new_vals}, t_conversions);
214
          }
215

216
        protected:
217
          Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
218
          {
219
            auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
220
            std::vector<Boxed_Value> new_params{bv};
221
            new_params.insert(new_params.end(), params.begin(), params.end());
222

223
            (*m_func)(Function_Params{new_params}, t_conversions);
224

225
            return bv;
226
          }
227

228
        private:
229
          const std::string m_type_name;
230
          const Proxy_Function m_func;
231

232
      };
233
    }
234
  }
235
}
236
#endif
237

Read our documentation on viewing source code .

Loading