GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
chaiscript_eval.hpp
Go to the documentation of this file.
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_EVAL_HPP_
12#define CHAISCRIPT_EVAL_HPP_
13
14#include <exception>
15#include <functional>
16#include <limits>
17#include <map>
18#include <memory>
19#include <ostream>
20#include <stdexcept>
21#include <string>
22#include <vector>
23
35#include "chaiscript_common.hpp"
36
37namespace chaiscript {
38namespace exception {
39class bad_boxed_cast;
40} // namespace exception
41} // namespace chaiscript
42
43namespace chaiscript
44{
46 namespace eval
47 {
48 template<typename T> struct AST_Node_Impl;
49
50 template<typename T> using AST_Node_Impl_Ptr = typename std::unique_ptr<AST_Node_Impl<T>>;
51
52 namespace detail
53 {
55 template<typename T>
56 static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr, bool has_this_capture = false) {
58
59 const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
60 auto &stack = t_ss.get_stack_data(state.stack_holder()).back();
61 if (!stack.empty() && stack.back().first == "__this") {
62 return &stack.back().second;
63 } else if (!t_vals.empty()) {
64 return &t_vals[0];
65 } else {
66 return nullptr;
67 }
68 }();
69
71 if (thisobj && !has_this_capture) { state.add_object("this", *thisobj); }
72
73 if (t_locals) {
74 for (const auto &local : *t_locals) {
75 state.add_object(local.first, local.second);
76 }
77 }
78
79 for (size_t i = 0; i < t_param_names.size(); ++i) {
80 if (t_param_names[i] != "this") {
81 state.add_object(t_param_names[i], t_vals[i]);
82 }
83 }
84
85 try {
86 return t_node.eval(state);
87 } catch (detail::Return_Value &rv) {
88 return std::move(rv.retval);
89 }
90 }
91
92 inline Boxed_Value clone_if_necessary(Boxed_Value incoming, std::atomic_uint_fast32_t &t_loc, const chaiscript::detail::Dispatch_State &t_ss)
93 {
94 if (!incoming.is_return_value())
95 {
96 if (incoming.get_type_info().is_arithmetic()) {
97 return Boxed_Number::clone(incoming);
98 } else if (incoming.get_type_info().bare_equal_type_info(typeid(bool))) {
99 return Boxed_Value(*static_cast<const bool*>(incoming.get_const_ptr()));
100 } else {
101 return t_ss->call_function("clone", t_loc, {incoming}, t_ss.conversions());
102 }
103 } else {
104 incoming.reset_return_value();
105 return incoming;
106 }
107 }
108 }
109
110 template<typename T>
112 {
113 AST_Node_Impl(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc,
114 std::vector<AST_Node_Impl_Ptr<T>> t_children = std::vector<AST_Node_Impl_Ptr<T>>())
115 : AST_Node(std::move(t_ast_node_text), t_id, std::move(t_loc)),
116 children(std::move(t_children))
117 {
118 }
119
122 return get_bool_condition(node.eval(t_ss), t_ss);
123 }
124
125
126 std::vector<std::reference_wrapper<AST_Node>> get_children() const final {
127 std::vector<std::reference_wrapper<AST_Node>> retval;
128 retval.reserve(children.size());
129 for (auto &&child : children) {
130 retval.emplace_back(*child);
131 }
132
133 return retval;
134 }
135
137 {
138 try {
139 T::trace(t_e, this);
140 return eval_internal(t_e);
141 } catch (exception::eval_error &ee) {
142 ee.call_stack.push_back(*this);
143 throw;
144 }
145 }
146
147 std::vector<AST_Node_Impl_Ptr<T>> children;
148
149 protected:
151 {
152 throw std::runtime_error("Undispatched ast_node (internal error)");
153 }
154 };
155
156
157 template<typename T>
159 Compiled_AST_Node(AST_Node_Impl_Ptr<T> t_original_node, std::vector<AST_Node_Impl_Ptr<T>> t_children,
160 std::function<Boxed_Value (const std::vector<AST_Node_Impl_Ptr<T>> &, const chaiscript::detail::Dispatch_State &t_ss)> t_func) :
161 AST_Node_Impl<T>(t_original_node->text, AST_Node_Type::Compiled, t_original_node->location, std::move(t_children)),
162 m_func(std::move(t_func)),
163 m_original_node(std::move(t_original_node))
164 { }
165
167 return m_func(this->children, t_ss);
168 }
169
170 std::function<Boxed_Value (const std::vector<AST_Node_Impl_Ptr<T>> &, const chaiscript::detail::Dispatch_State &t_ss)> m_func;
172 };
173
174
175 template<typename T>
177 Fold_Right_Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children, Boxed_Value t_rhs) :
178 AST_Node_Impl<T>(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)),
179 m_oper(Operators::to_operator(t_oper)),
180 m_rhs(std::move(t_rhs))
181 { }
182
184 return do_oper(t_ss, this->text, this->children[0]->eval(t_ss));
185 }
186
187 protected:
189 const std::string &t_oper_string, const Boxed_Value &t_lhs) const
190 {
191 try {
192 if (t_lhs.get_type_info().is_arithmetic())
193 {
194 // If it's an arithmetic operation we want to short circuit dispatch
195 try{
196 return Boxed_Number::do_oper(m_oper, t_lhs, m_rhs);
198 throw;
199 } catch (...) {
200 throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
201 }
202 } else {
204 fpp.save_params({t_lhs, m_rhs});
205 return t_ss->call_function(t_oper_string, m_loc, {t_lhs, m_rhs}, t_ss.conversions());
206 }
207 }
208 catch(const exception::dispatch_error &e){
209 throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, *t_ss);
210 }
211 }
212
213 private:
214 Operators::Opers m_oper;
215 Boxed_Value m_rhs;
216 mutable std::atomic_uint_fast32_t m_loc = {0};
217 };
218
219
220 template<typename T>
222 Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
223 AST_Node_Impl<T>(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)),
224 m_oper(Operators::to_operator(t_oper))
225 { }
226
228 auto lhs = this->children[0]->eval(t_ss);
229 auto rhs = this->children[1]->eval(t_ss);
230 return do_oper(t_ss, m_oper, this->text, lhs, rhs);
231 }
232
233 protected:
235 Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) const
236 {
237 try {
239 {
240 // If it's an arithmetic operation we want to short circuit dispatch
241 try{
242 return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs);
244 throw;
245 } catch (...) {
246 throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
247 }
248 } else {
250 fpp.save_params({t_lhs, t_rhs});
251 return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}, t_ss.conversions());
252 }
253 }
254 catch(const exception::dispatch_error &e){
255 throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, *t_ss);
256 }
257 }
258
259 private:
260 Operators::Opers m_oper;
261 mutable std::atomic_uint_fast32_t m_loc = {0};
262 };
263
264
265 template<typename T>
267 Constant_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_value)
268 : AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Constant, std::move(t_loc)),
269 m_value(std::move(t_value))
270 {
271 }
272
275 m_value(std::move(t_value))
276 {
277 }
278
280 return m_value;
281 }
282
284 };
285
286 template<typename T>
287 struct Id_AST_Node final : AST_Node_Impl<T> {
288 Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
289 AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc))
290 { }
291
293 try {
294 return t_ss.get_object(this->text, m_loc);
295 }
296 catch (std::exception &) {
297 throw exception::eval_error("Can not find object: " + this->text);
298 }
299 }
300
301 private:
302 mutable std::atomic_uint_fast32_t m_loc = {0};
303 };
304
305 template<typename T>
307 Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
308 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) {
309 assert(!this->children.empty());
310 }
311
312 template<bool Save_Params>
314 {
316
317 std::vector<Boxed_Value> params;
318
319 params.reserve(this->children[1]->children.size());
320 for (const auto &child : this->children[1]->children) {
321 params.push_back(child->eval(t_ss));
322 }
323
324 if (Save_Params) {
325 fpp.save_params(params);
326 }
327
328 Boxed_Value fn(this->children[0]->eval(t_ss));
329
330 using ConstFunctionTypePtr = const dispatch::Proxy_Function_Base *;
331 try {
332 return (*t_ss->boxed_cast<ConstFunctionTypePtr>(fn))(params, t_ss.conversions());
333 }
334 catch(const exception::dispatch_error &e){
335 throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
336 }
337 catch(const exception::bad_boxed_cast &){
338 try {
339 using ConstFunctionTypeRef = const Const_Proxy_Function &;
340 Const_Proxy_Function f = t_ss->boxed_cast<ConstFunctionTypeRef>(fn);
341 // handle the case where there is only 1 function to try to call and dispatch fails on it
342 throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss);
343 } catch (const exception::bad_boxed_cast &) {
344 throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
345 }
346 }
347 catch(const exception::arity_error &e){
348 throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
349 }
350 catch(const exception::guard_error &e){
351 throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
352 }
353 catch(detail::Return_Value &rv) {
354 return rv.retval;
355 }
356 }
357
359 {
360 return do_eval_internal<true>(t_ss);
361 }
362
363 };
364
365
366 template<typename T>
368 Unused_Return_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
369 Fun_Call_AST_Node<T>(std::move(t_ast_node_text), std::move(t_loc), std::move(t_children)) { }
370
372 {
373 return this->template do_eval_internal<false>(t_ss);
374 }
375 };
376
377
378
379
380
381 template<typename T>
383 Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
384 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
385
386 };
387
388 template<typename T>
390 Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
391 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
392
393
394 static std::string get_arg_name(const AST_Node_Impl<T> &t_node) {
395 if (t_node.children.empty())
396 {
397 return t_node.text;
398 } else if (t_node.children.size() == 1) {
399 return t_node.children[0]->text;
400 } else {
401 return t_node.children[1]->text;
402 }
403 }
404
405 static std::vector<std::string> get_arg_names(const AST_Node_Impl<T> &t_node) {
406 std::vector<std::string> retval;
407
408 for (const auto &node : t_node.children)
409 {
410 retval.push_back(get_arg_name(*node));
411 }
412
413 return retval;
414 }
415
416 static std::pair<std::string, Type_Info> get_arg_type(const AST_Node_Impl<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss)
417 {
418 if (t_node.children.size() < 2)
419 {
420 return {};
421 } else {
422 return {t_node.children[0]->text, t_ss->get_type(t_node.children[0]->text, false)};
423 }
424 }
425
427 std::vector<std::pair<std::string, Type_Info>> retval;
428
429 for (const auto &child : t_node.children)
430 {
431 retval.push_back(get_arg_type(*child, t_ss));
432 }
433
434 return dispatch::Param_Types(std::move(retval));
435 }
436 };
437
438 template<typename T>
440 Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
441 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)),
442 m_oper(Operators::to_operator(this->text))
443 { assert(this->children.size() == 2); }
444
445
448 Boxed_Value rhs = this->children[1]->eval(t_ss);
449 Boxed_Value lhs = this->children[0]->eval(t_ss);
450
451 if (lhs.is_return_value()) {
452 throw exception::eval_error("Error, cannot assign to temporary value.");
453 } else if (lhs.is_const()) {
454 throw exception::eval_error("Error, cannot assign to constant value.");
455 }
456
457
458 if (m_oper != Operators::Opers::invalid && lhs.get_type_info().is_arithmetic() &&
460 {
461 try {
462 return Boxed_Number::do_oper(m_oper, lhs, rhs);
463 } catch (const std::exception &) {
464 throw exception::eval_error("Error with unsupported arithmetic assignment operation.");
465 }
466 } else if (m_oper == Operators::Opers::assign) {
467 try {
468
469 if (lhs.is_undef()) {
470 if (!this->children.empty()
471 && ((this->children[0]->identifier == AST_Node_Type::Reference)
472 || (!this->children[0]->children.empty()
473 && this->children[0]->children[0]->identifier == AST_Node_Type::Reference)
474 )
475 )
476
477 {
480 lhs.assign(rhs);
481 lhs.reset_return_value();
482 return rhs;
483 } else {
484 rhs = detail::clone_if_necessary(std::move(rhs), m_clone_loc, t_ss);
485 }
486 }
487
488 try {
489 return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
490 }
491 catch(const exception::dispatch_error &e){
492 throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss);
493 }
494 }
495 catch(const exception::dispatch_error &e){
496 throw exception::eval_error("Missing clone or copy constructor for right hand side of equation", e.parameters, e.functions, false, *t_ss);
497 }
498 }
499 else if (this->text == ":=") {
500 if (lhs.is_undef() || Boxed_Value::type_match(lhs, rhs)) {
501 lhs.assign(rhs);
502 lhs.reset_return_value();
503 } else {
504 throw exception::eval_error("Mismatched types in equation");
505 }
506 }
507 else {
508 try {
509 return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
510 } catch(const exception::dispatch_error &e){
511 throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss);
512 }
513 }
514
515 return rhs;
516 }
517
518 private:
519 Operators::Opers m_oper;
520 mutable std::atomic_uint_fast32_t m_loc = {0};
521 mutable std::atomic_uint_fast32_t m_clone_loc = {0};
522 };
523
524 template<typename T>
526 Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
527 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { }
528
530 const std::string &idname =
531 [&]()->const std::string & {
533 return this->children[0]->children[0]->text;
534 } else {
535 return this->children[0]->text;
536 }
537 }();
538
539 return t_ss->add_global_no_throw(Boxed_Value(), idname);
540
541 }
542 };
543
544
545 template<typename T>
547 Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
548 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { }
549
551 const std::string &idname = this->children[0]->text;
552
553 try {
554 Boxed_Value bv;
555 t_ss.add_object(idname, bv);
556 return bv;
557 } catch (const exception::name_conflict_error &e) {
558 throw exception::eval_error("Variable redefined '" + e.name() + "'");
559 }
560 }
561 };
562
563 template<typename T>
565 Assign_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
566 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Assign_Decl, std::move(t_loc), std::move(t_children)) { }
567
569 const std::string &idname = this->children[0]->text;
570
571 try {
572 Boxed_Value bv(detail::clone_if_necessary(this->children[1]->eval(t_ss), m_loc, t_ss));
574 t_ss.add_object(idname, bv);
575 return bv;
576 } catch (const exception::name_conflict_error &e) {
577 throw exception::eval_error("Variable redefined '" + e.name() + "'");
578 }
579 }
580 private:
581 mutable std::atomic_uint_fast32_t m_loc = {0};
582 };
583
584
585 template<typename T>
587 Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
588 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { }
589
592
593 const std::vector<Boxed_Value> params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)};
594
595 try {
596 fpp.save_params(params);
597 return t_ss->call_function("[]", m_loc, params, t_ss.conversions());
598 }
599 catch(const exception::dispatch_error &e){
600 throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss );
601 }
602 }
603
604
605 private:
606 mutable std::atomic_uint_fast32_t m_loc = {0};
607 };
608
609 template<typename T>
611 Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
612 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)),
613 m_fun_name(
615 this->children[1]->children[0]->text:this->children[1]->text) { }
616
619
620
621 Boxed_Value retval = this->children[0]->eval(t_ss);
622 std::vector<Boxed_Value> params{retval};
623
624 bool has_function_params = false;
625 if (this->children[1]->children.size() > 1) {
626 has_function_params = true;
627 for (const auto &child : this->children[1]->children[1]->children) {
628 params.push_back(child->eval(t_ss));
629 }
630 }
631
632 fpp.save_params(params);
633
634 try {
635 retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params, t_ss.conversions());
636 }
637 catch(const exception::dispatch_error &e){
638 if (e.functions.empty())
639 {
640 throw exception::eval_error("'" + m_fun_name + "' is not a function.");
641 } else {
642 throw exception::eval_error(std::string(e.what()) + " for function '" + m_fun_name + "'", e.parameters, e.functions, true, *t_ss);
643 }
644 }
645 catch(detail::Return_Value &rv) {
646 retval = std::move(rv.retval);
647 }
648
650 try {
651 retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[1]->children[1]->eval(t_ss)}, t_ss.conversions());
652 }
653 catch(const exception::dispatch_error &e){
654 throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss);
655 }
656 }
657
658 return retval;
659 }
660
661 private:
662 mutable std::atomic_uint_fast32_t m_loc = {0};
663 mutable std::atomic_uint_fast32_t m_array_loc = {0};
664 const std::string m_fun_name;
665 };
666
667
668 template<typename T>
669 struct Lambda_AST_Node final : AST_Node_Impl<T> {
670 Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
671 AST_Node_Impl<T>(t_ast_node_text,
673 std::move(t_loc),
674 std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
675 std::make_move_iterator(std::prev(t_children.end())))
676 ),
677 m_param_names(Arg_List_AST_Node<T>::get_arg_names(*this->children[1])),
678 m_this_capture(has_this_capture(this->children[0]->children)),
679 m_lambda_node(std::move(t_children.back()))
680 { }
681
683
684 const auto captures = [&]()->std::map<std::string, Boxed_Value>{
685 std::map<std::string, Boxed_Value> named_captures;
686 for (const auto &capture : this->children[0]->children) {
687 named_captures.insert(std::make_pair(capture->children[0]->text, capture->children[0]->eval(t_ss)));
688 }
689 return named_captures;
690 }();
691
692 const auto numparams = this->children[1]->children.size();
693 const auto param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[1], t_ss);
694
695 std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
696
697 return Boxed_Value(
699 [engine, lambda_node = this->m_lambda_node, param_names = this->m_param_names, captures,
700 this_capture = this->m_this_capture] (const std::vector<Boxed_Value> &t_params)
701 {
702 return detail::eval_function(engine, *lambda_node, param_names, t_params, &captures, this_capture);
703 },
704 static_cast<int>(numparams), m_lambda_node, param_types
705 )
706 );
707 }
708
709 static bool has_this_capture(const std::vector<AST_Node_Impl_Ptr<T>> &children) {
710 return std::any_of(std::begin(children), std::end(children),
711 [](const auto &child){
712 return child->children[0]->text == "this";
713 }
714 );
715 }
716
717 private:
718 const std::vector<std::string> m_param_names;
719 const bool m_this_capture = false;
720 const std::shared_ptr<AST_Node_Impl<T>> m_lambda_node;
721 };
722
723 template<typename T>
725 Scopeless_Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
726 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Scopeless_Block, std::move(t_loc), std::move(t_children)) { }
727
729 const auto num_children = this->children.size();
730 for (size_t i = 0; i < num_children-1; ++i) {
731 this->children[i]->eval(t_ss);
732 }
733 return this->children.back()->eval(t_ss);
734 }
735 };
736
737 template<typename T>
738 struct Block_AST_Node final : AST_Node_Impl<T> {
739 Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
740 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { }
741
744
745 const auto num_children = this->children.size();
746 for (size_t i = 0; i < num_children-1; ++i) {
747 this->children[i]->eval(t_ss);
748 }
749 return this->children.back()->eval(t_ss);
750 }
751 };
752
753 template<typename T>
754 struct Def_AST_Node final : AST_Node_Impl<T> {
755
756 std::shared_ptr<AST_Node_Impl<T>> m_body_node;
757 std::shared_ptr<AST_Node_Impl<T>> m_guard_node;
758
759 Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
760 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc),
761 std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
762 std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children, 1)?2:1)))
763 ),
764 // This apparent use after move is safe because we are only moving out the specific elements we need
765 // on each operation.
766 m_body_node(get_body_node(std::move(t_children))),
767 m_guard_node(get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))
768
769 { }
770
771 static std::shared_ptr<AST_Node_Impl<T>> get_guard_node(std::vector<AST_Node_Impl_Ptr<T>> &&vec, bool has_guard)
772 {
773 if (has_guard) {
774 return std::move(*std::prev(vec.end(), 2));
775 } else {
776 return {};
777 }
778 }
779
780 static std::shared_ptr<AST_Node_Impl<T>> get_body_node(std::vector<AST_Node_Impl_Ptr<T>> &&vec)
781 {
782 return std::move(vec.back());
783 }
784
785 static bool has_guard(const std::vector<AST_Node_Impl_Ptr<T>> &t_children, const std::size_t offset)
786 {
787 if ((t_children.size() > 2 + offset) && (t_children[1+offset]->identifier == AST_Node_Type::Arg_List)) {
788 if (t_children.size() > 3 + offset) {
789 return true;
790 }
791 }
792 else {
793 if (t_children.size() > 2 + offset) {
794 return true;
795 }
796 }
797 return false;
798 }
799
801 std::vector<std::string> t_param_names;
802 size_t numparams = 0;
803
804 dispatch::Param_Types param_types;
805
806 if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
807 numparams = this->children[1]->children.size();
808 t_param_names = Arg_List_AST_Node<T>::get_arg_names(*this->children[1]);
809 param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[1], t_ss);
810 }
811
812 std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
813 std::shared_ptr<dispatch::Proxy_Function_Base> guard;
814 if (m_guard_node) {
816 [engine, guardnode = m_guard_node, t_param_names](const std::vector<Boxed_Value> &t_params)
817 {
818 return detail::eval_function(engine, *guardnode, t_param_names, t_params);
819 },
820 static_cast<int>(numparams), m_guard_node);
821 }
822
823 try {
824 const std::string & l_function_name = this->children[0]->text;
825 t_ss->add(
827 [engine, func_node = m_body_node, t_param_names](const std::vector<Boxed_Value> &t_params)
828 {
829 return detail::eval_function(engine, *func_node, t_param_names, t_params);
830 },
831 static_cast<int>(numparams), m_body_node,
832 param_types, guard), l_function_name);
833 } catch (const exception::name_conflict_error &e) {
834 throw exception::eval_error("Function redefined '" + e.name() + "'");
835 }
836 return void_var();
837 }
838
839 };
840
841 template<typename T>
842 struct While_AST_Node final : AST_Node_Impl<T> {
843 While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
844 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { }
845
848
849 try {
850 while (this->get_scoped_bool_condition(*this->children[0], t_ss)) {
851 try {
852 this->children[1]->eval(t_ss);
853 } catch (detail::Continue_Loop &) {
854 // we got a continue exception, which means all of the remaining
855 // loop implementation is skipped and we just need to continue to
856 // the next condition test
857 }
858 }
859 } catch (detail::Break_Loop &) {
860 // loop was broken intentionally
861 }
862
863 return void_var();
864 }
865 };
866
867 template<typename T>
868 struct Class_AST_Node final : AST_Node_Impl<T> {
869 Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
870 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { }
871
874
876 // put class name in current scope so it can be looked up by the attrs and methods
877 t_ss.add_object("_current_class_name", const_var(this->children[0]->text));
878
879 this->children[1]->eval(t_ss);
880
881 return void_var();
882 }
883 };
884
885
886 template<typename T>
887 struct If_AST_Node final : AST_Node_Impl<T> {
888 If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
889 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children))
890 {
891 assert(this->children.size() == 3);
892 }
893
895 if (this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)) {
896 return this->children[1]->eval(t_ss);
897 } else {
898 return this->children[2]->eval(t_ss);
899 }
900 }
901 };
902
903 template<typename T>
905 Ranged_For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
906 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Ranged_For, std::move(t_loc), std::move(t_children))
907 { assert(this->children.size() == 3); }
908
910 const auto get_function = [&t_ss](const std::string &t_name, auto &t_hint){
911 uint_fast32_t hint = t_hint;
912 auto funs = t_ss->get_function(t_name, hint);
913 if (funs.first != hint) { t_hint = uint_fast32_t(funs.first); }
914 return std::move(funs.second);
915 };
916
917 const auto call_function = [&t_ss](const auto &t_funcs, const Boxed_Value &t_param) {
918 return dispatch::dispatch(*t_funcs, {t_param}, t_ss.conversions());
919 };
920
921
922 const std::string &loop_var_name = this->children[0]->text;
923 Boxed_Value range_expression_result = this->children[1]->eval(t_ss);
924
925
926 const auto do_loop = [&loop_var_name, &t_ss, this](const auto &ranged_thing){
927 try {
928 for (auto &&loop_var : ranged_thing) {
929 // This scope push and pop might not be the best thing for perf
930 // but we know it's 100% correct
933 if (!std::is_same<std::decay_t<decltype(loop_var)>, Boxed_Value>::value) {
934 t_ss.add_get_object(loop_var_name, Boxed_Value(std::ref(loop_var)));
935 } else {
936 t_ss.add_get_object(loop_var_name, Boxed_Value(loop_var));
937 }
938 try {
939 this->children[2]->eval(t_ss);
940 } catch (detail::Continue_Loop &) {
941 }
942 }
943 } catch (detail::Break_Loop &) {
944 // loop broken
945 }
946 return void_var();
947 };
948
949 if (range_expression_result.get_type_info().bare_equal_type_info(typeid(std::vector<Boxed_Value>))) {
950 return do_loop(boxed_cast<const std::vector<Boxed_Value> &>(range_expression_result));
951 } else if (range_expression_result.get_type_info().bare_equal_type_info(typeid(std::map<std::string, Boxed_Value>))) {
952 return do_loop(boxed_cast<const std::map<std::string, Boxed_Value> &>(range_expression_result));
953 } else {
954 const auto range_funcs = get_function("range", m_range_loc);
955 const auto empty_funcs = get_function("empty", m_empty_loc);
956 const auto front_funcs = get_function("front", m_front_loc);
957 const auto pop_front_funcs = get_function("pop_front", m_pop_front_loc);
958
959 try {
960 const auto range_obj = call_function(range_funcs, range_expression_result);
961 while (!boxed_cast<bool>(call_function(empty_funcs, range_obj))) {
963 t_ss.add_get_object(loop_var_name, call_function(front_funcs, range_obj));
964 try {
965 this->children[2]->eval(t_ss);
966 } catch (detail::Continue_Loop &) {
967 }
968 call_function(pop_front_funcs, range_obj);
969 }
970 } catch (detail::Break_Loop &) {
971 // loop broken
972 }
973 return void_var();
974 }
975
976 }
977
978 private:
979 mutable std::atomic_uint_fast32_t m_range_loc = {0};
980 mutable std::atomic_uint_fast32_t m_empty_loc = {0};
981 mutable std::atomic_uint_fast32_t m_front_loc = {0};
982 mutable std::atomic_uint_fast32_t m_pop_front_loc = {0};
983 };
984
985
986 template<typename T>
987 struct For_AST_Node final : AST_Node_Impl<T> {
988 For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
989 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::For, std::move(t_loc), std::move(t_children))
990 { assert(this->children.size() == 4); }
991
994
995 try {
996 for (
997 this->children[0]->eval(t_ss);
998 this->get_scoped_bool_condition(*this->children[1], t_ss);
999 this->children[2]->eval(t_ss)
1000 ) {
1001 try {
1002 // Body of Loop
1003 this->children[3]->eval(t_ss);
1004 } catch (detail::Continue_Loop &) {
1005 // we got a continue exception, which means all of the remaining
1006 // loop implementation is skipped and we just need to continue to
1007 // the next iteration step
1008 }
1009 }
1010 } catch (detail::Break_Loop &) {
1011 // loop broken
1012 }
1013
1014 return void_var();
1015 }
1016
1017 };
1018
1019 template<typename T>
1020 struct Switch_AST_Node final : AST_Node_Impl<T> {
1021 Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1022 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { }
1023
1025 bool breaking = false;
1026 size_t currentCase = 1;
1027 bool hasMatched = false;
1028
1030
1031 Boxed_Value match_value(this->children[0]->eval(t_ss));
1032
1033 while (!breaking && (currentCase < this->children.size())) {
1034 try {
1035 if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
1036 //This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
1037 try {
1038 if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}, t_ss.conversions()))) {
1039 this->children[currentCase]->eval(t_ss);
1040 hasMatched = true;
1041 }
1042 }
1043 catch (const exception::bad_boxed_cast &) {
1044 throw exception::eval_error("Internal error: case guard evaluation not boolean");
1045 }
1046 }
1047 else if (this->children[currentCase]->identifier == AST_Node_Type::Default) {
1048 this->children[currentCase]->eval(t_ss);
1049 hasMatched = true;
1050 }
1051 }
1052 catch (detail::Break_Loop &) {
1053 breaking = true;
1054 }
1055 ++currentCase;
1056 }
1057 return void_var();
1058 }
1059
1060 mutable std::atomic_uint_fast32_t m_loc = {0};
1061 };
1062
1063 template<typename T>
1064 struct Case_AST_Node final : AST_Node_Impl<T> {
1065 Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1066 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children))
1067 { assert(this->children.size() == 2); /* how many children does it have? */ }
1068
1071
1072 this->children[1]->eval(t_ss);
1073
1074 return void_var();
1075 }
1076 };
1077
1078 template<typename T>
1080 Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1081 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children))
1082 { assert(this->children.size() == 1); }
1083
1086
1087 this->children[0]->eval(t_ss);
1088
1089 return void_var();
1090 }
1091 };
1092
1093
1094 template<typename T>
1096 Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1097 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { }
1098
1100 try {
1101 std::vector<Boxed_Value> vec;
1102 if (!this->children.empty()) {
1103 vec.reserve(this->children[0]->children.size());
1104 for (const auto &child : this->children[0]->children) {
1105 vec.push_back(detail::clone_if_necessary(child->eval(t_ss), m_loc, t_ss));
1106 }
1107 }
1108 return const_var(std::move(vec));
1109 }
1110 catch (const exception::dispatch_error &) {
1111 throw exception::eval_error("Can not find appropriate 'clone' or copy constructor for vector elements");
1112 }
1113 }
1114
1115 private:
1116 mutable std::atomic_uint_fast32_t m_loc = {0};
1117 };
1118
1119 template<typename T>
1121 Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1122 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { }
1123
1125 {
1126 try {
1127 std::map<std::string, Boxed_Value> retval;
1128
1129 for (const auto &child : this->children[0]->children) {
1130 retval.insert(std::make_pair(t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss)),
1131 detail::clone_if_necessary(child->children[1]->eval(t_ss), m_loc, t_ss)));
1132 }
1133
1134 return const_var(std::move(retval));
1135 }
1136 catch (const exception::dispatch_error &e) {
1137 throw exception::eval_error("Can not find appropriate copy constructor or 'clone' while inserting into Map.", e.parameters, e.functions, false, *t_ss);
1138 }
1139 }
1140
1141 private:
1142 mutable std::atomic_uint_fast32_t m_loc = {0};
1143 };
1144
1145 template<typename T>
1146 struct Return_AST_Node final : AST_Node_Impl<T> {
1147 Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1148 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { }
1149
1151 if (!this->children.empty()) {
1152 throw detail::Return_Value{this->children[0]->eval(t_ss)};
1153 }
1154 else {
1156 }
1157 }
1158 };
1159
1160 template<typename T>
1161 struct File_AST_Node final : AST_Node_Impl<T> {
1162 File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1163 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { }
1164
1166 try {
1167 const auto num_children = this->children.size();
1168
1169 if (num_children > 0) {
1170 for (size_t i = 0; i < num_children-1; ++i) {
1171 this->children[i]->eval(t_ss);
1172 }
1173 return this->children.back()->eval(t_ss);
1174 } else {
1175 return void_var();
1176 }
1177 } catch (const detail::Continue_Loop &) {
1178 throw exception::eval_error("Unexpected `continue` statement outside of a loop");
1179 } catch (const detail::Break_Loop &) {
1180 throw exception::eval_error("Unexpected `break` statement outside of a loop");
1181 }
1182 }
1183 };
1184
1185 template<typename T>
1187 Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1188 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children))
1189 { assert(this->children.size() == 1); }
1190
1192 Boxed_Value bv;
1193 t_ss.add_object(this->children[0]->text, bv);
1194 return bv;
1195 }
1196 };
1197
1198 template<typename T>
1199 struct Prefix_AST_Node final : AST_Node_Impl<T> {
1200 Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1201 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)),
1202 m_oper(Operators::to_operator(this->text, true))
1203 { }
1204
1206 Boxed_Value bv(this->children[0]->eval(t_ss));
1207
1208 try {
1209 // short circuit arithmetic operations
1211 {
1213 {
1214 throw exception::eval_error("Error with prefix operator evaluation: cannot modify constant value.");
1215 }
1216 return Boxed_Number::do_oper(m_oper, bv);
1217 } else {
1219 fpp.save_params({bv});
1220 return t_ss->call_function(this->text, m_loc, {std::move(bv)}, t_ss.conversions());
1221 }
1222 } catch (const exception::dispatch_error &e) {
1223 throw exception::eval_error("Error with prefix operator evaluation: '" + this->text + "'", e.parameters, e.functions, false, *t_ss);
1224 }
1225 }
1226
1227 private:
1229 mutable std::atomic_uint_fast32_t m_loc = {0};
1230 };
1231
1232 template<typename T>
1233 struct Break_AST_Node final : AST_Node_Impl<T> {
1234 Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1235 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { }
1236
1240 };
1241
1242 template<typename T>
1244 Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1245 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { }
1246
1250 };
1251
1252 template<typename T>
1253 struct Noop_AST_Node final : AST_Node_Impl<T> {
1257
1259 // It's a no-op, that evaluates to "void"
1260 return val;
1261 }
1262
1264 };
1265
1266 template<typename T>
1268 Map_Pair_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1269 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Map_Pair, std::move(t_loc), std::move(t_children)) { }
1270 };
1271
1272 template<typename T>
1274 Value_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1275 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Value_Range, std::move(t_loc), std::move(t_children)) { }
1276 };
1277
1278 template<typename T>
1280 Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1281 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { }
1282
1284 try {
1285 auto oper1 = this->children[0]->children[0]->children[0]->eval(t_ss);
1286 auto oper2 = this->children[0]->children[0]->children[1]->eval(t_ss);
1287 return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions());
1288 }
1289 catch (const exception::dispatch_error &e) {
1290 throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss);
1291 }
1292 }
1293
1294 private:
1295 mutable std::atomic_uint_fast32_t m_loc = {0};
1296 };
1297
1298 template<typename T>
1299 struct Try_AST_Node final : AST_Node_Impl<T> {
1300 Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1301 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { }
1302
1304 {
1305 Boxed_Value retval;
1306
1307 size_t end_point = this->children.size();
1308 if (this->children.back()->identifier == AST_Node_Type::Finally) {
1309 assert(end_point > 0);
1310 end_point = this->children.size() - 1;
1311 }
1312 for (size_t i = 1; i < end_point; ++i) {
1314 auto &catch_block = *this->children[i];
1315
1316 if (catch_block.children.size() == 1) {
1317 //No variable capture, no guards
1318 retval = catch_block.children[0]->eval(t_ss);
1319 break;
1320 } else if (catch_block.children.size() == 2 || catch_block.children.size() == 3) {
1321 const auto name = Arg_List_AST_Node<T>::get_arg_name(*catch_block.children[0]);
1322
1324 std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node<T>::get_arg_type(*catch_block.children[0], t_ss)}
1325 ).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()).first)
1326 {
1327 t_ss.add_object(name, t_except);
1328
1329 if (catch_block.children.size() == 2) {
1330 //Variable capture, no guards
1331 retval = catch_block.children[1]->eval(t_ss);
1332 break;
1333 }
1334 else if (catch_block.children.size() == 3) {
1335 //Variable capture, guards
1336
1337 bool guard = false;
1338 try {
1339 guard = boxed_cast<bool>(catch_block.children[1]->eval(t_ss));
1340 } catch (const exception::bad_boxed_cast &) {
1341 if (this->children.back()->identifier == AST_Node_Type::Finally) {
1342 this->children.back()->children[0]->eval(t_ss);
1343 }
1344 throw exception::eval_error("Guard condition not boolean");
1345 }
1346 if (guard) {
1347 retval = catch_block.children[2]->eval(t_ss);
1348 break;
1349 }
1350 }
1351 }
1352 }
1353 else {
1354 if (this->children.back()->identifier == AST_Node_Type::Finally) {
1355 this->children.back()->children[0]->eval(t_ss);
1356 }
1357 throw exception::eval_error("Internal error: catch block size unrecognized");
1358 }
1359 }
1360
1361 return retval;
1362 }
1363
1365 Boxed_Value retval;
1366
1368
1369
1370 try {
1371 retval = this->children[0]->eval(t_ss);
1372 }
1373 catch (const exception::eval_error &e) {
1374 retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
1375 }
1376 catch (const std::runtime_error &e) {
1377 retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
1378 }
1379 catch (const std::out_of_range &e) {
1380 retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
1381 }
1382 catch (const std::exception &e) {
1383 retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
1384 }
1385 catch (Boxed_Value &e) {
1386 retval = handle_exception(t_ss, e);
1387 }
1388 catch (...) {
1389 if (this->children.back()->identifier == AST_Node_Type::Finally) {
1390 this->children.back()->children[0]->eval(t_ss);
1391 }
1392 throw;
1393 }
1394
1395
1396 if (this->children.back()->identifier == AST_Node_Type::Finally) {
1397 retval = this->children.back()->children[0]->eval(t_ss);
1398 }
1399
1400 return retval;
1401 }
1402
1403 };
1404
1405 template<typename T>
1406 struct Catch_AST_Node final : AST_Node_Impl<T> {
1407 Catch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1408 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Catch, std::move(t_loc), std::move(t_children)) { }
1409 };
1410
1411 template<typename T>
1413 Finally_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1414 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Finally, std::move(t_loc), std::move(t_children)) { }
1415 };
1416
1417 template<typename T>
1418 struct Method_AST_Node final : AST_Node_Impl<T> {
1419 std::shared_ptr<AST_Node_Impl<T>> m_body_node;
1420 std::shared_ptr<AST_Node_Impl<T>> m_guard_node;
1421
1422 Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1423 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc),
1424 std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
1425 std::make_move_iterator(std::prev(t_children.end(), Def_AST_Node<T>::has_guard(t_children, 1)?2:1)))
1426 ),
1427 m_body_node(Def_AST_Node<T>::get_body_node(std::move(t_children))),
1428 m_guard_node(Def_AST_Node<T>::get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))
1429 {
1430 }
1431
1433
1434 AST_Node_Impl_Ptr<T> guardnode;
1435
1436 const std::string & class_name = this->children[0]->text;
1437
1438 //The first param of a method is always the implied this ptr.
1439 std::vector<std::string> t_param_names{"this"};
1440 dispatch::Param_Types param_types;
1441
1442 if ((this->children.size() > 2)
1443 && (this->children[2]->identifier == AST_Node_Type::Arg_List)) {
1444 auto args = Arg_List_AST_Node<T>::get_arg_names(*this->children[2]);
1445 t_param_names.insert(t_param_names.end(), args.begin(), args.end());
1446 param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[2], t_ss);
1447 }
1448
1449 const size_t numparams = t_param_names.size();
1450
1451 std::shared_ptr<dispatch::Proxy_Function_Base> guard;
1452 std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
1453 if (m_guard_node) {
1455 [engine, t_param_names, guardnode = m_guard_node](const std::vector<Boxed_Value> &t_params) {
1456 return chaiscript::eval::detail::eval_function(engine, *guardnode, t_param_names, t_params);
1457 },
1458 static_cast<int>(numparams), m_guard_node);
1459 }
1460
1461 try {
1462 const std::string & function_name = this->children[1]->text;
1463
1464 if (function_name == class_name) {
1465 param_types.push_front(class_name, Type_Info());
1466
1467 t_ss->add(
1468 std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name,
1470 [engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
1471 return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
1472 },
1473 static_cast<int>(numparams), m_body_node, param_types, guard
1474 )
1475 ),
1476 function_name);
1477
1478 } else {
1479 // if the type is unknown, then this generates a function that looks up the type
1480 // at runtime. Defining the type first before this is called is better
1481 auto type = t_ss->get_type(class_name, false);
1482 param_types.push_front(class_name, type);
1483
1484 t_ss->add(
1485 std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
1487 [engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
1488 return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
1489 },
1490 static_cast<int>(numparams), m_body_node, param_types, guard), type),
1491 function_name);
1492 }
1493 } catch (const exception::name_conflict_error &e) {
1494 throw exception::eval_error("Method redefined '" + e.name() + "'");
1495 }
1496 return void_var();
1497 }
1498
1499 };
1500
1501 template<typename T>
1503 Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1504 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { }
1505
1507 {
1508 std::string class_name = this->children[0]->text;
1509
1510 try {
1511 std::string attr_name = this->children[1]->text;
1512
1513 t_ss->add(
1514 std::make_shared<dispatch::detail::Dynamic_Object_Function>(
1515 std::move(class_name),
1516 fun([attr_name](dispatch::Dynamic_Object &t_obj) {
1517 return t_obj.get_attr(attr_name);
1518 }),
1519 true
1520
1521 ), this->children[1]->text);
1522 } catch (const exception::name_conflict_error &e) {
1523 throw exception::eval_error("Attribute redefined '" + e.name() + "'");
1524 }
1525 return void_var();
1526 }
1527
1528 };
1529
1530
1531 template<typename T>
1533 Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1534 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Logical_And, std::move(t_loc), std::move(t_children))
1535 { assert(this->children.size() == 2); }
1536
1538 {
1539 return const_var(this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)
1540 && this->get_bool_condition(this->children[1]->eval(t_ss), t_ss));
1541 }
1542
1543 };
1544
1545 template<typename T>
1547 Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
1548 AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children))
1549 { assert(this->children.size() == 2); }
1550
1552 {
1553 return const_var(this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)
1554 || this->get_bool_condition(this->children[1]->eval(t_ss), t_ss));
1555 }
1556 };
1557 }
1558
1559
1560}
1561#endif /* CHAISCRIPT_EVAL_HPP_ */
1562
Env e
Definition Common.cc:2
bool has_guard() const
Returns true if the function has a guard to it. Always returns false for a conglomerate function.
Definition GameApi_pl.cc:23060
Definition Math.hh:178
Definition Web.hh:23
static Boxed_Value clone(const Boxed_Value &t_bv)
Definition boxed_number.hpp:524
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
Definition boxed_number.hpp:893
A wrapper for holding any valid C++ type. All types in ChaiScript are Boxed_Value objects.
Definition boxed_value.hpp:28
const void * get_const_ptr() const noexcept
Definition boxed_value.hpp:316
bool is_const() const noexcept
Definition boxed_value.hpp:235
Boxed_Value assign(const Boxed_Value &rhs)
Definition boxed_value.hpp:218
bool is_undef() const noexcept
return true if the object is uninitialized
Definition boxed_value.hpp:230
const Type_Info & get_type_info() const noexcept
Definition boxed_value.hpp:224
void reset_return_value() const noexcept
Definition boxed_value.hpp:301
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept
Definition boxed_value.hpp:356
bool is_return_value() const noexcept
Definition boxed_value.hpp:296
Compile time deduced information about a type.
Definition type_info.hpp:34
constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
Definition type_info.hpp:81
constexpr bool is_arithmetic() const noexcept
Definition type_info.hpp:89
Definition dispatchkit.hpp:438
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector< Boxed_Value > &params, bool t_has_params, const Type_Conversions_State &t_conversions)
Definition dispatchkit.hpp:959
decltype(auto) boxed_cast(const Boxed_Value &bv) const
casts an object while applying any Dynamic_Conversion available
Definition dispatchkit.hpp:462
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector< Boxed_Value > &params, const Type_Conversions_State &t_conversions) const
Definition dispatchkit.hpp:1079
std::pair< size_t, std::shared_ptr< std::vector< Proxy_Function > > > get_function(const std::string &t_name, const size_t t_hint) const
Return a function by name.
Definition dispatchkit.hpp:779
const StackData & get_stack_data() const
Definition dispatchkit.hpp:1274
Type_Info get_type(const std::string &name, bool t_throw=true) const
Returns the type info for a named type.
Definition dispatchkit.hpp:722
void add(const Type_Conversion &d)
Add a new conversion for upcasting to a base class.
Definition dispatchkit.hpp:469
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
Adds a new global (non-const) shared object, between all the threads.
Definition dispatchkit.hpp:569
Definition dispatchkit.hpp:1513
Stack_Holder & stack_holder() const
Definition dispatchkit.hpp:1530
Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const
Definition dispatchkit.hpp:1550
void add_object(const std::string &t_name, Boxed_Value obj) const
Definition dispatchkit.hpp:1546
const Type_Conversions_State & conversions() const
Definition dispatchkit.hpp:1534
Boxed_Value & add_get_object(const std::string &t_name, Boxed_Value obj) const
Definition dispatchkit.hpp:1542
Definition dynamic_object.hpp:44
const Boxed_Value & get_attr(const std::string &t_attr_name) const
Definition dynamic_object.hpp:78
Definition proxy_functions.hpp:52
void push_front(std::string t_name, Type_Info t_ti)
Definition proxy_functions.hpp:67
std::pair< bool, bool > match(const std::vector< Boxed_Value > &vals, const Type_Conversions_State &t_conversions) const
Definition proxy_functions.hpp:117
Definition proxy_functions.hpp:196
Thrown in the event that a Boxed_Value cannot be cast to the desired type.
Definition bad_boxed_cast.hpp:34
Exception thrown in the case that a method dispatch fails because no matching function was found.
Definition proxy_functions.hpp:814
Exception thrown if a function's guard fails.
Definition proxy_functions.hpp:327
Exception thrown in the case that an object name is invalid because it already exists in current cont...
Definition dispatchkit.hpp:110
iVBORw0KGgoAAAANSUhEUgAAANcAAAB5CAMAAACdtUQZAAAA51BMVEX</div ></div >< div style="padding: 0px 0px; width: 1324px;">< div style="height: 400px; width: 1324px;"></div >< div itemscope itemtype="https: </div><div itemscope itemtype="https:</div >< div itemscope itemtype="https: </div></div><p><div style="padding:0px 0px;width:1324px;"><div></div><div itemscope itemtype="https:< ul >< li >< b > Application name
8AkrcAgqgAs9wqQ0ey2tkAo8gAuuQfeI4hPUH09fXHy8z4+fng4uNKXF/Lz9BzfoAcgpkQMTUAKjAbOT4Qr9AXhJ8Rl7ktMCwTosA...
Definition meshpage.php:1610
n< br > font size
Definition meshpage.php:3536
Definition catch.hpp:90
Proxy_Function make_dynamic_proxy_function(Callable &&c, Arg &&... a)
Definition proxy_functions.hpp:504
Boxed_Value dispatch(const Funcs &funcs, const std::vector< Boxed_Value > &plist, const Type_Conversions_State &t_conversions)
Definition proxy_functions.hpp:936
Definition chaiscript_common.hpp:649
Boxed_Value clone_if_necessary(Boxed_Value incoming, std::atomic_uint_fast32_t &t_loc, const chaiscript::detail::Dispatch_State &t_ss)
Definition chaiscript_eval.hpp:92
Classes and functions that are part of the runtime eval system.
Definition chaiscript_common.hpp:647
typename std::unique_ptr< AST_Node_Impl< T > > AST_Node_Impl_Ptr
Definition chaiscript_eval.hpp:50
Classes which may be thrown during error cases when ChaiScript is executing.
Definition bad_boxed_cast.hpp:27
Namespace chaiscript contains every API call that the average user will be concerned with.
std::shared_ptr< const dispatch::Proxy_Function_Base > Const_Proxy_Function
Const version of Proxy_Function. Points to a const Proxy_Function. This is how most registered functi...
Definition proxy_functions.hpp:321
Boxed_Value void_var()
Definition boxed_value.hpp:466
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions=nullptr)
Function for extracting a value stored in a Boxed_Value object.
Definition boxed_cast.hpp:76
Proxy_Function fun(const T &t)
Creates a new Proxy_Function object from a free function, member function or data member.
Definition register_function.hpp:43
AST_Node_Type
Types of AST nodes available to the parser and eval.
Definition chaiscript_common.hpp:65
@ Lambda
Definition chaiscript_common.hpp:67
@ Case
Definition chaiscript_common.hpp:69
@ Assign_Decl
Definition chaiscript_common.hpp:65
@ Array_Call
Definition chaiscript_common.hpp:66
@ Dot_Access
Definition chaiscript_common.hpp:66
@ Map_Pair
Definition chaiscript_common.hpp:67
@ Noop
Definition chaiscript_common.hpp:69
@ Var_Decl
Definition chaiscript_common.hpp:65
@ For
Definition chaiscript_common.hpp:67
@ While
Definition chaiscript_common.hpp:67
@ Id
Definition chaiscript_common.hpp:65
@ Scopeless_Block
Definition chaiscript_common.hpp:67
@ Global_Decl
Definition chaiscript_common.hpp:69
@ Method
Definition chaiscript_common.hpp:68
@ Compiled
Definition chaiscript_common.hpp:69
@ Logical_And
Definition chaiscript_common.hpp:69
@ Finally
Definition chaiscript_common.hpp:68
@ Reference
Definition chaiscript_common.hpp:69
@ Value_Range
Definition chaiscript_common.hpp:67
@ Binary
Definition chaiscript_common.hpp:69
@ Prefix
Definition chaiscript_common.hpp:67
@ Inline_Array
Definition chaiscript_common.hpp:67
@ If
Definition chaiscript_common.hpp:67
@ Default
Definition chaiscript_common.hpp:69
@ Arg_List
Definition chaiscript_common.hpp:65
@ Logical_Or
Definition chaiscript_common.hpp:69
@ Ranged_For
Definition chaiscript_common.hpp:67
@ Return
Definition chaiscript_common.hpp:67
@ Continue
Definition chaiscript_common.hpp:67
@ Switch
Definition chaiscript_common.hpp:69
@ Inline_Map
Definition chaiscript_common.hpp:67
@ Fun_Call
Definition chaiscript_common.hpp:65
@ Constant
Definition chaiscript_common.hpp:69
@ Def
Definition chaiscript_common.hpp:67
@ Break
Definition chaiscript_common.hpp:67
@ Try
Definition chaiscript_common.hpp:68
@ Attr_Decl
Definition chaiscript_common.hpp:68
@ Inline_Range
Definition chaiscript_common.hpp:68
Boxed_Value const_var(const T &t)
Takes an object and returns an immutable Boxed_Value. If the object is a std::reference or pointer ty...
Definition boxed_value.hpp:461
STL namespace.
double f(const std::string &, double, bool) noexcept
Definition profile_cpp_calls_2.cpp:4
Definition parser.cc:9
Definition GameApi.h:42
AST_Node(AST_Node &&)=default
const std::string text
Definition chaiscript_common.hpp:500
const AST_Node_Type identifier
Definition chaiscript_common.hpp:499
const File_Position & end() const
Definition chaiscript_common.hpp:511
Parse_Location location
Definition chaiscript_common.hpp:501
std::string pretty_print() const
Definition chaiscript_common.hpp:515
static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss)
Definition chaiscript_common.hpp:546
Definition chaiscript_algebraic.hpp:21
Opers
Definition chaiscript_algebraic.hpp:23
@ pre_increment
Definition chaiscript_algebraic.hpp:27
@ pre_decrement
Definition chaiscript_algebraic.hpp:27
@ bitwise_and
Definition chaiscript_algebraic.hpp:33
@ assign
Definition chaiscript_algebraic.hpp:27
@ invalid
Definition chaiscript_algebraic.hpp:36
Definition chaiscript_common.hpp:101
Definition chaiscript_eval.hpp:112
static bool get_scoped_bool_condition(const AST_Node_Impl< T > &node, const chaiscript::detail::Dispatch_State &t_ss)
Definition chaiscript_eval.hpp:120
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const final
Definition chaiscript_eval.hpp:136
std::vector< AST_Node_Impl_Ptr< T > > children
Definition chaiscript_eval.hpp:147
AST_Node_Impl(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children=std::vector< AST_Node_Impl_Ptr< T > >())
Definition chaiscript_eval.hpp:113
std::vector< std::reference_wrapper< AST_Node > > get_children() const final
Definition chaiscript_eval.hpp:126
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const
Definition chaiscript_eval.hpp:150
Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:383
Definition chaiscript_eval.hpp:389
static std::pair< std::string, Type_Info > get_arg_type(const AST_Node_Impl< T > &t_node, const chaiscript::detail::Dispatch_State &t_ss)
Definition chaiscript_eval.hpp:416
static std::string get_arg_name(const AST_Node_Impl< T > &t_node)
Definition chaiscript_eval.hpp:394
Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:390
static dispatch::Param_Types get_arg_types(const AST_Node_Impl< T > &t_node, const chaiscript::detail::Dispatch_State &t_ss)
Definition chaiscript_eval.hpp:426
static std::vector< std::string > get_arg_names(const AST_Node_Impl< T > &t_node)
Definition chaiscript_eval.hpp:405
Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:587
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:590
Assign_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:565
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:568
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1506
Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1503
Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:222
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:227
Boxed_Value do_oper(const chaiscript::detail::Dispatch_State &t_ss, Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) const
Definition chaiscript_eval.hpp:234
Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:739
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:742
Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1234
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override
Definition chaiscript_eval.hpp:1237
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1069
Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1065
Catch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1407
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:872
Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:869
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:166
std::function< Boxed_Value(const std::vector< AST_Node_Impl_Ptr< T > > &, const chaiscript::detail::Dispatch_State &t_ss)> m_func
Definition chaiscript_eval.hpp:170
AST_Node_Impl_Ptr< T > m_original_node
Definition chaiscript_eval.hpp:171
Compiled_AST_Node(AST_Node_Impl_Ptr< T > t_original_node, std::vector< AST_Node_Impl_Ptr< T > > t_children, std::function< Boxed_Value(const std::vector< AST_Node_Impl_Ptr< T > > &, const chaiscript::detail::Dispatch_State &t_ss)> t_func)
Definition chaiscript_eval.hpp:159
Constant_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_value)
Definition chaiscript_eval.hpp:267
Boxed_Value m_value
Definition chaiscript_eval.hpp:283
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override
Definition chaiscript_eval.hpp:279
Constant_AST_Node(Boxed_Value t_value)
Definition chaiscript_eval.hpp:273
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override
Definition chaiscript_eval.hpp:1247
Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1244
Definition chaiscript_eval.hpp:754
Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:759
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:800
static std::shared_ptr< AST_Node_Impl< T > > get_guard_node(std::vector< AST_Node_Impl_Ptr< T > > &&vec, bool has_guard)
Definition chaiscript_eval.hpp:771
std::shared_ptr< AST_Node_Impl< T > > m_body_node
Definition chaiscript_eval.hpp:756
std::shared_ptr< AST_Node_Impl< T > > m_guard_node
Definition chaiscript_eval.hpp:757
static bool has_guard(const std::vector< AST_Node_Impl_Ptr< T > > &t_children, const std::size_t offset)
Definition chaiscript_eval.hpp:785
static std::shared_ptr< AST_Node_Impl< T > > get_body_node(std::vector< AST_Node_Impl_Ptr< T > > &&vec)
Definition chaiscript_eval.hpp:780
Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1080
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1084
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:617
Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:611
Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:440
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:446
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1165
File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1162
Finally_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1413
Fold_Right_Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children, Boxed_Value t_rhs)
Definition chaiscript_eval.hpp:177
Boxed_Value do_oper(const chaiscript::detail::Dispatch_State &t_ss, const std::string &t_oper_string, const Boxed_Value &t_lhs) const
Definition chaiscript_eval.hpp:188
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:183
For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:988
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:992
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:358
Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:307
Boxed_Value do_eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const
Definition chaiscript_eval.hpp:313
Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:526
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:529
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:292
Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc)
Definition chaiscript_eval.hpp:288
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:894
If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:888
Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1096
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1099
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1124
Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1121
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1283
Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1280
Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:670
static bool has_this_capture(const std::vector< AST_Node_Impl_Ptr< T > > &children)
Definition chaiscript_eval.hpp:709
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:682
Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1533
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1537
Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1547
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1551
Map_Pair_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1268
Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1422
std::shared_ptr< AST_Node_Impl< T > > m_body_node
Definition chaiscript_eval.hpp:1419
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1432
std::shared_ptr< AST_Node_Impl< T > > m_guard_node
Definition chaiscript_eval.hpp:1420
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override
Definition chaiscript_eval.hpp:1258
Boxed_Value val
Definition chaiscript_eval.hpp:1263
Noop_AST_Node()
Definition chaiscript_eval.hpp:1254
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1205
Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1200
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:909
Ranged_For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:905
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1191
Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1187
Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1147
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1150
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:728
Scopeless_Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:725
std::atomic_uint_fast32_t m_loc
Definition chaiscript_eval.hpp:1060
Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1021
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1024
Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1300
Boxed_Value handle_exception(const chaiscript::detail::Dispatch_State &t_ss, const Boxed_Value &t_except) const
Definition chaiscript_eval.hpp:1303
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:1364
Unused_Return_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:368
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:371
Value_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:1274
Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:547
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:550
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
Definition chaiscript_eval.hpp:846
While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector< AST_Node_Impl_Ptr< T > > t_children)
Definition chaiscript_eval.hpp:843
Special type indicating a call to 'break'.
Definition chaiscript_common.hpp:657
Special type indicating a call to 'continue'.
Definition chaiscript_common.hpp:663
Creates a new function call and pops it on destruction.
Definition chaiscript_common.hpp:694
void save_params(const std::vector< Boxed_Value > &t_params)
Definition chaiscript_common.hpp:711
Special type for returned values.
Definition chaiscript_common.hpp:651
Boxed_Value retval
Definition chaiscript_common.hpp:652
Creates a new scope then pops it on destruction.
Definition chaiscript_common.hpp:670
Creates a new scope then pops it on destruction.
Definition chaiscript_common.hpp:728
Definition boxed_number.hpp:33
Definition proxy_functions_detail.hpp:42
Errors generated during parsing or evaluation.
Definition chaiscript_common.hpp:168
std::vector< AST_Node_Trace > call_stack
Definition chaiscript_common.hpp:173