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