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> &params)
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