dynamic_object_detail.hpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. #ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
  7. #define CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
  8. #include <cassert>
  9. #include <map>
  10. #include <memory>
  11. #include <string>
  12. #include <typeinfo>
  13. #include <utility>
  14. #include <vector>
  15. #include "../chaiscript_defines.hpp"
  16. #include "boxed_cast.hpp"
  17. #include "boxed_cast_helper.hpp"
  18. #include "boxed_value.hpp"
  19. #include "proxy_functions.hpp"
  20. #include "type_info.hpp"
  21. #include "dynamic_object.hpp"
  22. namespace chaiscript {
  23. class Type_Conversions;
  24. namespace dispatch {
  25. class Proxy_Function_Base;
  26. } // namespace dispatch
  27. } // namespace chaiscript
  28. namespace chaiscript
  29. {
  30. namespace dispatch
  31. {
  32. namespace detail
  33. {
  34. /// A Proxy_Function implementation designed for calling a function
  35. /// that is automatically guarded based on the first param based on the
  36. /// param's type name
  37. class Dynamic_Object_Function final : public Proxy_Function_Base
  38. {
  39. public:
  40. Dynamic_Object_Function(
  41. std::string t_type_name,
  42. const Proxy_Function &t_func,
  43. bool t_is_attribute = false)
  44. : Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
  45. m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>()),
  46. m_is_attribute(t_is_attribute)
  47. {
  48. assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
  49. && "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
  50. }
  51. Dynamic_Object_Function(
  52. std::string t_type_name,
  53. const Proxy_Function &t_func,
  54. const Type_Info &t_ti,
  55. bool t_is_attribute = false)
  56. : Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
  57. 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>()),
  58. m_is_attribute(t_is_attribute)
  59. {
  60. assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
  61. && "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
  62. }
  63. Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
  64. Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
  65. bool operator==(const Proxy_Function_Base &f) const override
  66. {
  67. if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
  68. {
  69. return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
  70. } else {
  71. return false;
  72. }
  73. }
  74. bool is_attribute_function() const override { return m_is_attribute; }
  75. bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
  76. {
  77. if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
  78. {
  79. return m_func->call_match(vals, t_conversions);
  80. } else {
  81. return false;
  82. }
  83. }
  84. std::vector<Const_Proxy_Function> get_contained_functions() const override
  85. {
  86. return {m_func};
  87. }
  88. protected:
  89. Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
  90. {
  91. if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
  92. {
  93. return (*m_func)(params, t_conversions);
  94. } else {
  95. throw exception::guard_error();
  96. }
  97. }
  98. bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
  99. {
  100. return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
  101. }
  102. private:
  103. static std::vector<Type_Info> build_param_types(
  104. const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
  105. {
  106. std::vector<Type_Info> types(t_inner_types);
  107. assert(types.size() > 1);
  108. //assert(types[1].bare_equal(user_type<Boxed_Value>()));
  109. types[1] = t_objectti;
  110. return types;
  111. }
  112. bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
  113. const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
  114. {
  115. if (bv.get_type_info().bare_equal(m_doti))
  116. {
  117. try {
  118. const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
  119. return name == "Dynamic_Object" || d.get_type_name() == name;
  120. } catch (const std::bad_cast &) {
  121. return false;
  122. }
  123. } else {
  124. if (ti)
  125. {
  126. return bv.get_type_info().bare_equal(*ti);
  127. } else {
  128. return false;
  129. }
  130. }
  131. }
  132. bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
  133. const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
  134. {
  135. if (!bvs.empty())
  136. {
  137. return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
  138. } else {
  139. return false;
  140. }
  141. }
  142. std::string m_type_name;
  143. Proxy_Function m_func;
  144. std::unique_ptr<Type_Info> m_ti;
  145. const Type_Info m_doti;
  146. const bool m_is_attribute;
  147. };
  148. /**
  149. * A Proxy_Function implementation designed for creating a new
  150. * Dynamic_Object
  151. * that is automatically guarded based on the first param based on the
  152. * param's type name
  153. */
  154. class Dynamic_Object_Constructor final : public Proxy_Function_Base
  155. {
  156. public:
  157. Dynamic_Object_Constructor(
  158. std::string t_type_name,
  159. const Proxy_Function &t_func)
  160. : Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
  161. m_type_name(std::move(t_type_name)), m_func(t_func)
  162. {
  163. assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
  164. && "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
  165. }
  166. static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
  167. {
  168. auto begin = tl.begin();
  169. auto end = tl.end();
  170. if (begin != end)
  171. {
  172. ++begin;
  173. }
  174. return std::vector<Type_Info>(begin, end);
  175. }
  176. bool operator==(const Proxy_Function_Base &f) const override
  177. {
  178. const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
  179. return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
  180. }
  181. bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
  182. {
  183. std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
  184. new_vals.insert(new_vals.end(), vals.begin(), vals.end());
  185. return m_func->call_match(new_vals, t_conversions);
  186. }
  187. protected:
  188. Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
  189. {
  190. auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
  191. std::vector<Boxed_Value> new_params{bv};
  192. new_params.insert(new_params.end(), params.begin(), params.end());
  193. (*m_func)(new_params, t_conversions);
  194. return bv;
  195. }
  196. private:
  197. const std::string m_type_name;
  198. const Proxy_Function m_func;
  199. };
  200. }
  201. }
  202. }
  203. #endif