bootstrap.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  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_BOOTSTRAP_HPP_
  9. #define CHAISCRIPT_BOOTSTRAP_HPP_
  10. #include "../utility/utility.hpp"
  11. #include "register_function.hpp"
  12. namespace chaiscript
  13. {
  14. /// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
  15. namespace bootstrap
  16. {
  17. template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
  18. void array(const std::string &type, Module& m)
  19. {
  20. typedef typename std::remove_extent<T>::type ReturnType;
  21. const auto extent = std::extent<T>::value;
  22. m.add(user_type<T>(), type);
  23. m.add(fun(
  24. [extent](T& t, size_t index)->ReturnType &{
  25. if (extent > 0 && index >= extent) {
  26. throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
  27. } else {
  28. return t[index];
  29. }
  30. }
  31. ), "[]"
  32. );
  33. m.add(fun(
  34. [extent](const T &t, size_t index)->const ReturnType &{
  35. if (extent > 0 && index >= extent) {
  36. throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
  37. } else {
  38. return t[index];
  39. }
  40. }
  41. ), "[]"
  42. );
  43. m.add(fun(
  44. [extent](const T &) {
  45. return extent;
  46. }), "size");
  47. }
  48. /// \brief Adds a copy constructor for the given type to the given Model
  49. /// \param[in] type The name of the type. The copy constructor will be named "type".
  50. /// \param[in,out] m The Module to add the copy constructor to
  51. /// \tparam T The type to add a copy constructor for
  52. /// \returns The passed in Module
  53. template<typename T>
  54. void copy_constructor(const std::string &type, Module& m)
  55. {
  56. m.add(constructor<T (const T &)>(), type);
  57. }
  58. /// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
  59. /// \tparam T Type to create comparison operators for
  60. /// \param[in,out] m module to add comparison operators to
  61. /// \returns the passed in Module.
  62. template<typename T>
  63. void opers_comparison(Module& m)
  64. {
  65. operators::equal<T>(m);
  66. operators::greater_than<T>(m);
  67. operators::greater_than_equal<T>(m);
  68. operators::less_than<T>(m);
  69. operators::less_than_equal<T>(m);
  70. operators::not_equal<T>(m);
  71. }
  72. /// \brief Adds default and copy constructors for the given type
  73. /// \param[in] type The name of the type to add the constructors for.
  74. /// \param[in,out] m The Module to add the basic constructors to
  75. /// \tparam T Type to generate basic constructors for
  76. /// \returns The passed in Module
  77. /// \sa copy_constructor
  78. /// \sa constructor
  79. template<typename T>
  80. void basic_constructors(const std::string &type, Module& m)
  81. {
  82. m.add(constructor<T ()>(), type);
  83. copy_constructor<T>(type, m);
  84. }
  85. /// \brief Adds a constructor for a POD type
  86. /// \tparam T The type to add the constructor for
  87. /// \param[in] type The name of the type
  88. /// \param[in,out] m The Module to add the constructor to
  89. template<typename T>
  90. void construct_pod(const std::string &type, Module& m)
  91. {
  92. m.add(fun([](const Boxed_Number &bn){ return bn.get_as<T>(); }), type);
  93. }
  94. /// Internal function for converting from a string to a value
  95. /// uses ostream operator >> to perform the conversion
  96. template<typename Input>
  97. auto parse_string(const std::string &i)
  98. -> typename std::enable_if<
  99. !std::is_same<Input, wchar_t>::value
  100. && !std::is_same<Input, char16_t>::value
  101. && !std::is_same<Input, char32_t>::value,
  102. Input>::type
  103. {
  104. std::stringstream ss(i);
  105. Input t;
  106. ss >> t;
  107. return t;
  108. }
  109. template<typename Input>
  110. auto parse_string(const std::string &)
  111. -> typename std::enable_if<
  112. std::is_same<Input, wchar_t>::value
  113. || std::is_same<Input, char16_t>::value
  114. || std::is_same<Input, char32_t>::value,
  115. Input>::type
  116. {
  117. throw std::runtime_error("Parsing of wide characters is not yet supported");
  118. }
  119. /// Add all common functions for a POD type. All operators, and
  120. /// common conversions
  121. template<typename T>
  122. void bootstrap_pod_type(const std::string &name, Module& m)
  123. {
  124. m.add(user_type<T>(), name);
  125. m.add(constructor<T()>(), name);
  126. construct_pod<T>(name, m);
  127. m.add(fun(&parse_string<T>), "to_" + name);
  128. }
  129. /// "clone" function for a shared_ptr type. This is used in the case
  130. /// where you do not want to make a deep copy of an object during cloning
  131. /// but want to instead maintain the shared_ptr. It is needed internally
  132. /// for handling of Proxy_Function object (that is,
  133. /// function variables.
  134. template<typename Type>
  135. auto shared_ptr_clone(const std::shared_ptr<Type> &p)
  136. {
  137. return p;
  138. }
  139. /// Specific version of shared_ptr_clone just for Proxy_Functions
  140. template<typename Type>
  141. std::shared_ptr<typename std::remove_const<Type>::type> shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
  142. {
  143. return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
  144. }
  145. /// Assignment function for shared_ptr objects, does not perform a copy of the
  146. /// object pointed to, instead maintains the shared_ptr concept.
  147. /// Similar to shared_ptr_clone. Used for Proxy_Function.
  148. template<typename Type>
  149. Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
  150. {
  151. if (lhs.is_undef()
  152. || (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
  153. {
  154. lhs.assign(Boxed_Value(rhs));
  155. return lhs;
  156. } else {
  157. throw exception::bad_boxed_cast("type mismatch in pointer assignment");
  158. }
  159. }
  160. /// Class consisting of only static functions. All default bootstrapping occurs
  161. /// from this class.
  162. class Bootstrap
  163. {
  164. private:
  165. /// Function allowing for assignment of an unknown type to any other value
  166. static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
  167. {
  168. if (lhs.is_undef())
  169. {
  170. return (lhs.assign(rhs));
  171. } else {
  172. throw exception::bad_boxed_cast("boxed_value has a set type already");
  173. }
  174. }
  175. static void print(const std::string &s)
  176. {
  177. fwrite(s.c_str(), 1, s.size(), stdout);
  178. }
  179. static void println(const std::string &s)
  180. {
  181. puts(s.c_str());
  182. }
  183. /// Add all arithmetic operators for PODs
  184. static void opers_arithmetic_pod(Module& m)
  185. {
  186. m.add(fun(&Boxed_Number::equals), "==");
  187. m.add(fun(&Boxed_Number::less_than), "<");
  188. m.add(fun(&Boxed_Number::greater_than), ">");
  189. m.add(fun(&Boxed_Number::greater_than_equal), ">=");
  190. m.add(fun(&Boxed_Number::less_than_equal), "<=");
  191. m.add(fun(&Boxed_Number::not_equal), "!=");
  192. m.add(fun(&Boxed_Number::pre_decrement), "--");
  193. m.add(fun(&Boxed_Number::pre_increment), "++");
  194. m.add(fun(&Boxed_Number::sum), "+");
  195. m.add(fun(&Boxed_Number::unary_plus), "+");
  196. m.add(fun(&Boxed_Number::unary_minus), "-");
  197. m.add(fun(&Boxed_Number::difference), "-");
  198. m.add(fun(&Boxed_Number::assign_bitwise_and), "&=");
  199. m.add(fun(&Boxed_Number::assign), "=");
  200. m.add(fun(&Boxed_Number::assign_bitwise_or), "|=");
  201. m.add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
  202. m.add(fun(&Boxed_Number::assign_remainder), "%=");
  203. m.add(fun(&Boxed_Number::assign_shift_left), "<<=");
  204. m.add(fun(&Boxed_Number::assign_shift_right), ">>=");
  205. m.add(fun(&Boxed_Number::bitwise_and), "&");
  206. m.add(fun(&Boxed_Number::bitwise_complement), "~");
  207. m.add(fun(&Boxed_Number::bitwise_xor), "^");
  208. m.add(fun(&Boxed_Number::bitwise_or), "|");
  209. m.add(fun(&Boxed_Number::assign_product), "*=");
  210. m.add(fun(&Boxed_Number::assign_quotient), "/=");
  211. m.add(fun(&Boxed_Number::assign_sum), "+=");
  212. m.add(fun(&Boxed_Number::assign_difference), "-=");
  213. m.add(fun(&Boxed_Number::quotient), "/");
  214. m.add(fun(&Boxed_Number::shift_left), "<<");
  215. m.add(fun(&Boxed_Number::product), "*");
  216. m.add(fun(&Boxed_Number::remainder), "%");
  217. m.add(fun(&Boxed_Number::shift_right), ">>");
  218. }
  219. /// Create a bound function object. The first param is the function to bind
  220. /// the remaining parameters are the args to bind into the result
  221. static Boxed_Value bind_function(const std::vector<Boxed_Value> &params)
  222. {
  223. if (params.empty()) {
  224. throw exception::arity_error(0, 1);
  225. }
  226. Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
  227. if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1)
  228. {
  229. throw exception::arity_error(static_cast<int>(params.size()), f->get_arity());
  230. }
  231. return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(std::move(f),
  232. std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
  233. }
  234. static bool has_guard(const Const_Proxy_Function &t_pf)
  235. {
  236. auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
  237. return pf && pf->get_guard();
  238. }
  239. static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
  240. {
  241. const auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
  242. if (pf && pf->get_guard())
  243. {
  244. return pf->get_guard();
  245. } else {
  246. throw std::runtime_error("Function does not have a guard");
  247. }
  248. }
  249. template<typename FunctionType>
  250. static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
  251. const dispatch::Proxy_Function_Base *b)
  252. {
  253. auto v = (b->*f)();
  254. std::vector<Boxed_Value> vbv;
  255. for (const auto &o: v)
  256. {
  257. vbv.push_back(const_var(o));
  258. }
  259. return vbv;
  260. }
  261. static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
  262. {
  263. const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
  264. return bool(pf);
  265. }
  266. static const chaiscript::AST_Node &get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
  267. {
  268. const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
  269. if (pf)
  270. {
  271. return pf->get_parse_tree();
  272. } else {
  273. throw std::runtime_error("Function does not have a parse tree");
  274. }
  275. }
  276. template<typename Function>
  277. static auto return_boxed_value_vector(const Function &f)
  278. {
  279. return [f](const dispatch::Proxy_Function_Base *b) {
  280. return do_return_boxed_value_vector(f, b);
  281. };
  282. }
  283. public:
  284. /// \brief perform all common bootstrap functions for std::string, void and POD types
  285. /// \param[in,out] m Module to add bootstrapped functions to
  286. /// \returns passed in Module
  287. static void bootstrap(Module& m)
  288. {
  289. m.add(user_type<void>(), "void");
  290. m.add(user_type<bool>(), "bool");
  291. m.add(user_type<Boxed_Value>(), "Object");
  292. m.add(user_type<Boxed_Number>(), "Number");
  293. m.add(user_type<Proxy_Function>(), "Function");
  294. m.add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
  295. m.add(user_type<std::exception>(), "exception");
  296. m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
  297. m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
  298. m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
  299. m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
  300. m.add(fun([](const std::exception &e){ return std::string(e.what()); }), "what");
  301. m.add(user_type<std::out_of_range>(), "out_of_range");
  302. m.add(user_type<std::logic_error>(), "logic_error");
  303. m.add(chaiscript::base_class<std::exception, std::logic_error>());
  304. m.add(chaiscript::base_class<std::logic_error, std::out_of_range>());
  305. m.add(chaiscript::base_class<std::exception, std::out_of_range>());
  306. m.add(user_type<std::runtime_error>(), "runtime_error");
  307. m.add(chaiscript::base_class<std::exception, std::runtime_error>());
  308. m.add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
  309. m.add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
  310. m.add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
  311. m.add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
  312. m.add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
  313. m.add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
  314. m.add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
  315. m.add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
  316. m.add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr");
  317. m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
  318. m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
  319. m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
  320. m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
  321. m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
  322. m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
  323. m.eval(R"chaiscript(
  324. def Dynamic_Object::clone() {
  325. auto &new_o = Dynamic_Object(this.get_type_name());
  326. for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
  327. new_o;
  328. }
  329. def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
  330. {
  331. for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
  332. }
  333. def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
  334. {
  335. var rhs_attrs := rhs.get_attrs();
  336. var lhs_attrs := lhs.get_attrs();
  337. if (rhs_attrs.size() != lhs_attrs.size()) {
  338. true;
  339. } else {
  340. return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } );
  341. }
  342. }
  343. def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
  344. {
  345. var rhs_attrs := rhs.get_attrs();
  346. var lhs_attrs := lhs.get_attrs();
  347. if (rhs_attrs.size() != lhs_attrs.size()) {
  348. false;
  349. } else {
  350. return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } );
  351. }
  352. }
  353. )chaiscript");
  354. m.add(fun(&has_guard), "has_guard");
  355. m.add(fun(&get_guard), "get_guard");
  356. m.add(fun(&Boxed_Value::is_undef), "is_var_undef");
  357. m.add(fun(&Boxed_Value::is_null), "is_var_null");
  358. m.add(fun(&Boxed_Value::is_const), "is_var_const");
  359. m.add(fun(&Boxed_Value::is_ref), "is_var_reference");
  360. m.add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
  361. m.add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
  362. m.add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
  363. m.add(fun(&Boxed_Value::is_type), "is_type");
  364. m.add(fun(&Boxed_Value::get_attr), "get_var_attr");
  365. m.add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
  366. m.add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
  367. m.add(fun(&Boxed_Value::get_type_info), "get_type_info");
  368. m.add(user_type<Type_Info>(), "Type_Info");
  369. m.add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
  370. operators::equal<Type_Info>(m);
  371. m.add(fun(&Type_Info::is_const), "is_type_const");
  372. m.add(fun(&Type_Info::is_reference), "is_type_reference");
  373. m.add(fun(&Type_Info::is_void), "is_type_void");
  374. m.add(fun(&Type_Info::is_undef), "is_type_undef");
  375. m.add(fun(&Type_Info::is_pointer), "is_type_pointer");
  376. m.add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
  377. m.add(fun(&Type_Info::name), "cpp_name");
  378. m.add(fun(&Type_Info::bare_name), "cpp_bare_name");
  379. m.add(fun(&Type_Info::bare_equal), "bare_equal");
  380. basic_constructors<bool>("bool", m);
  381. operators::assign<bool>(m);
  382. operators::equal<bool>(m);
  383. operators::not_equal<bool>(m);
  384. m.add(fun([](const std::string &s) { return s; }), "to_string");
  385. m.add(fun([](const bool b) { return std::string(b?"true":"false"); }), "to_string");
  386. m.add(fun(&unknown_assign), "=");
  387. m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
  388. m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
  389. m.add(fun(&Boxed_Number::to_string), "to_string");
  390. bootstrap_pod_type<double>("double", m);
  391. bootstrap_pod_type<long double>("long_double", m);
  392. bootstrap_pod_type<float>("float", m);
  393. bootstrap_pod_type<int>("int", m);
  394. bootstrap_pod_type<long>("long", m);
  395. bootstrap_pod_type<unsigned int>("unsigned_int", m);
  396. bootstrap_pod_type<unsigned long>("unsigned_long", m);
  397. bootstrap_pod_type<long long>("long_long", m);
  398. bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
  399. bootstrap_pod_type<size_t>("size_t", m);
  400. bootstrap_pod_type<char>("char", m);
  401. bootstrap_pod_type<wchar_t>("wchar_t", m);
  402. bootstrap_pod_type<char16_t>("char16_t", m);
  403. bootstrap_pod_type<char32_t>("char32_t", m);
  404. bootstrap_pod_type<std::int8_t>("int8_t", m);
  405. bootstrap_pod_type<std::int16_t>("int16_t", m);
  406. bootstrap_pod_type<std::int32_t>("int32_t", m);
  407. bootstrap_pod_type<std::int64_t>("int64_t", m);
  408. bootstrap_pod_type<std::uint8_t>("uint8_t", m);
  409. bootstrap_pod_type<std::uint16_t>("uint16_t", m);
  410. bootstrap_pod_type<std::uint32_t>("uint32_t", m);
  411. bootstrap_pod_type<std::uint64_t>("uint64_t", m);
  412. operators::logical_compliment<bool>(m);
  413. opers_arithmetic_pod(m);
  414. m.add(fun(&Build_Info::version_major), "version_major");
  415. m.add(fun(&Build_Info::version_minor), "version_minor");
  416. m.add(fun(&Build_Info::version_patch), "version_patch");
  417. m.add(fun(&Build_Info::version), "version");
  418. m.add(fun(&Build_Info::compiler_version), "compiler_version");
  419. m.add(fun(&Build_Info::compiler_name), "compiler_name");
  420. m.add(fun(&Build_Info::compiler_id), "compiler_id");
  421. m.add(fun(&Build_Info::debug_build), "debug_build");
  422. m.add(fun(&print), "print_string");
  423. m.add(fun(&println), "println_string");
  424. m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
  425. m.add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
  426. m.add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
  427. m.add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
  428. m.add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
  429. m.add(fun(
  430. [](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
  431. t_lhs.assign(t_rhs);
  432. }
  433. ), "="
  434. );
  435. m.add(fun(&Boxed_Value::type_match), "type_match");
  436. m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
  437. m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
  438. m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
  439. m.add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
  440. m.add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
  441. m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
  442. m.add(chaiscript::base_class<std::exception, chaiscript::exception::arithmetic_error>());
  443. // chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
  444. chaiscript::utility::add_class<chaiscript::exception::eval_error>(m,
  445. "eval_error",
  446. { },
  447. { {fun(&chaiscript::exception::eval_error::reason), "reason"},
  448. {fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
  449. {fun([](const chaiscript::exception::eval_error &t_eval_error) {
  450. std::vector<Boxed_Value> retval;
  451. std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
  452. std::back_inserter(retval),
  453. &chaiscript::var<const chaiscript::AST_Node_Trace &>);
  454. return retval;
  455. }), "call_stack"} }
  456. );
  457. chaiscript::utility::add_class<chaiscript::File_Position>(m,
  458. "File_Position",
  459. { constructor<File_Position()>(),
  460. constructor<File_Position(int, int)>() },
  461. { {fun(&File_Position::line), "line"},
  462. {fun(&File_Position::column), "column"} }
  463. );
  464. chaiscript::utility::add_class<AST_Node>(m,
  465. "AST_Node",
  466. { },
  467. { {fun(&AST_Node::text), "text"},
  468. {fun(&AST_Node::identifier), "identifier"},
  469. {fun(&AST_Node::filename), "filename"},
  470. {fun(&AST_Node::start), "start"},
  471. {fun(&AST_Node::end), "end"},
  472. {fun(&AST_Node::to_string), "to_string"},
  473. {fun([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
  474. std::vector<Boxed_Value> retval;
  475. const auto children = t_node.get_children();
  476. std::transform(children.begin(), children.end(),
  477. std::back_inserter(retval),
  478. &chaiscript::var<const std::reference_wrapper<chaiscript::AST_Node> &>);
  479. return retval;
  480. }), "children"}
  481. }
  482. );
  483. }
  484. };
  485. }
  486. }
  487. #endif