diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 0d7e8a3..c689ad8 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -580,7 +580,8 @@ namespace chaiscript {fun(&AST_Node::to_string), "to_string"}, {fun([](const chaiscript::AST_Node &t_node) -> std::vector { std::vector retval; - std::transform(t_node.children.begin(), t_node.children.end(), + const auto children = t_node.get_children(); + std::transform(children.begin(), children.end(), std::back_inserter(retval), &chaiscript::var &>); return retval; diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index a5c46e4..80bbf36 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -37,6 +37,9 @@ class Boxed_Number; } // namespace chaiscript namespace chaiscript { + namespace parser { + class ChaiScript_Parser_Base; + } namespace dispatch { class Dynamic_Proxy_Function; class Proxy_Function_Base; @@ -45,6 +48,7 @@ struct Placeholder_Object; } // namespace chaiscript + /// \namespace chaiscript::dispatch /// \brief Classes and functions specific to the runtime dispatch side of ChaiScript. Some items may be of use to the end user. @@ -411,8 +415,10 @@ namespace chaiscript "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"}; }; - Dispatch_Engine() - : m_stack_holder(this) + Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser) + : m_stack_holder(this), + m_parser(parser) + { } @@ -1231,6 +1237,11 @@ namespace chaiscript return m_stack_holder->stacks.back(); } + parser::ChaiScript_Parser_Base &get_parser() + { + return m_parser.get(); + } + private: const std::vector> &get_boxed_functions_int() const @@ -1456,6 +1467,7 @@ namespace chaiscript Type_Conversions m_conversions; chaiscript::detail::threading::Thread_Storage m_stack_holder; + std::reference_wrapper m_parser; mutable std::atomic_uint_fast32_t m_method_missing_loc; diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 073e286..2f06f21 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -465,7 +465,6 @@ namespace chaiscript const AST_Node_Type identifier; const std::string text; Parse_Location location; - std::vector children; const std::string &filename() const { return *location.filename; @@ -485,13 +484,16 @@ namespace chaiscript oss << text; - for (auto & elem : this->children) { + for (auto & elem : this->get_children()) { oss << elem->pretty_print() << ' '; } return oss.str(); } + virtual std::vector get_children() const = 0; + virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0; + /// Prints the contents of an AST node, including its children, recursively std::string to_string(const std::string &t_prepend = "") const { @@ -500,21 +502,12 @@ namespace chaiscript oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n'; - for (auto & elem : this->children) { + for (auto & elem : this->get_children()) { oss << elem->to_string(t_prepend + " "); } return oss.str(); } - Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const - { - try { - return eval_internal(t_e); - } catch (exception::eval_error &ee) { - ee.call_stack.push_back(shared_from_this()); - throw; - } - } static bool get_bool_condition(const Boxed_Value &t_bv) { try { @@ -534,21 +527,39 @@ namespace chaiscript protected: - AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc, - std::vector t_children = std::vector()) : - identifier(t_id), text(std::move(t_ast_node_text)), - location(std::move(t_loc)), - children(std::move(t_children)) + AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc) + : identifier(t_id), text(std::move(t_ast_node_text)), + location(std::move(t_loc)) { } - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const - { - throw std::runtime_error("Undispatched ast_node (internal error)"); - } }; + namespace parser { + class ChaiScript_Parser_Base + { + public: + virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0; + virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; + virtual void *get_tracer_ptr() = 0; + virtual ~ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default; + ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete; + ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete; + + template + T &get_tracer() + { + // to do type check this somehow? + return static_cast(*get_tracer_ptr()); + } + + protected: + ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; + }; + } namespace eval { diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 2f26dca..05f0e84 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -70,10 +70,10 @@ namespace chaiscript std::vector m_module_paths; std::vector m_use_paths; - chaiscript::detail::Dispatch_Engine m_engine; - std::unique_ptr m_parser; + chaiscript::detail::Dispatch_Engine m_engine; + /// Evaluates the given string in by parsing it and running the results through the evaluator Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false) { @@ -219,7 +219,9 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()), + m_engine(*m_parser) + { if (m_module_paths.empty()) { @@ -244,7 +246,8 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()), + m_engine(*m_parser) { if (m_module_paths.empty()) { diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index d02e328..0464e4d 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -41,10 +41,15 @@ namespace chaiscript /// \brief Classes and functions that are part of the runtime eval system namespace eval { + template struct AST_Node_Impl; + + template using AST_Node_Impl_Ptr = typename std::shared_ptr>; + namespace detail { /// Helper function that will set up the scope around a function call, including handling the named function parameters - static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr) { + template + static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr) { chaiscript::detail::Dispatch_State state(t_ss); const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{ @@ -81,32 +86,72 @@ namespace chaiscript } } - struct Compiled_AST_Node : AST_Node { - Compiled_AST_Node(AST_NodePtr t_original_node, std::vector t_children, - std::function &, const chaiscript::detail::Dispatch_State &t_ss)> t_func) : - AST_Node(t_original_node->text, AST_Node_Type::Compiled, t_original_node->location, std::move(t_children)), + + + template + struct AST_Node_Impl : AST_Node + { + AST_Node_Impl(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc, + std::vector> t_children = std::vector>()) + : AST_Node(std::move(t_ast_node_text), std::move(t_id), std::move(t_loc)), + children(std::move(t_children)) + { + } + + + std::vector get_children() const final { + return {children.begin(), children.end()}; + } + + Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const final + { + try { + T::trace(t_e, this); + return eval_internal(t_e); + } catch (exception::eval_error &ee) { + ee.call_stack.push_back(shared_from_this()); + throw; + } + } + + std::vector> children; + + protected: + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const + { + throw std::runtime_error("Undispatched ast_node (internal error)"); + } + }; + + + template + struct Compiled_AST_Node : AST_Node_Impl { + Compiled_AST_Node(AST_Node_Impl_Ptr t_original_node, std::vector> t_children, + std::function> &, const chaiscript::detail::Dispatch_State &t_ss)> t_func) : + AST_Node_Impl(t_original_node->text, AST_Node_Type::Compiled, t_original_node->location, std::move(t_children)), m_func(std::move(t_func)), m_original_node(std::move(t_original_node)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - return m_func(children, t_ss); + return m_func(this->children, t_ss); } - std::function &, const chaiscript::detail::Dispatch_State &t_ss)> m_func; - AST_NodePtr m_original_node; + std::function> &, const chaiscript::detail::Dispatch_State &t_ss)> m_func; + AST_Node_Impl_Ptr m_original_node; }; - struct Binary_Operator_AST_Node : AST_Node { - Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector t_children) : - AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), + template + struct Binary_Operator_AST_Node : AST_Node_Impl { + Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), m_oper(Operators::to_operator(t_oper)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { auto lhs = this->children[0]->eval(t_ss); auto rhs = this->children[1]->eval(t_ss); - return do_oper(t_ss, m_oper, text, lhs, rhs); + return do_oper(t_ss, m_oper, this->text, lhs, rhs); } protected: @@ -141,10 +186,10 @@ namespace chaiscript }; - - struct Constant_AST_Node final : AST_Node { + template + struct Constant_AST_Node final : AST_Node_Impl { Constant_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_value) - : AST_Node(t_ast_node_text, AST_Node_Type::Constant, std::move(t_loc)), + : AST_Node_Impl(t_ast_node_text, AST_Node_Type::Constant, std::move(t_loc)), m_value(std::move(t_value)) { } @@ -156,9 +201,10 @@ namespace chaiscript Boxed_Value m_value; }; - struct Id_AST_Node final : AST_Node { + template + struct Id_AST_Node final : AST_Node_Impl { Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) : - AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)), + AST_Node_Impl(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)), m_loc(0) { } @@ -177,9 +223,10 @@ namespace chaiscript - struct Fun_Call_AST_Node final : AST_Node { - Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { } + template + struct Fun_Call_AST_Node final : AST_Node_Impl { + Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -227,18 +274,20 @@ namespace chaiscript - struct Arg_AST_Node final : AST_Node { - Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } + template + struct Arg_AST_Node final : AST_Node_Impl { + Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } }; - struct Arg_List_AST_Node final : AST_Node { - Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } + template + struct Arg_List_AST_Node final : AST_Node_Impl { + Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } - static std::string get_arg_name(const AST_NodePtr &t_node) { + static std::string get_arg_name(const AST_Node_Impl_Ptr &t_node) { if (t_node->children.empty()) { return t_node->text; @@ -249,7 +298,7 @@ namespace chaiscript } } - static std::vector get_arg_names(const AST_NodePtr &t_node) { + static std::vector get_arg_names(const AST_Node_Impl_Ptr &t_node) { std::vector retval; for (const auto &node : t_node->children) @@ -260,7 +309,7 @@ namespace chaiscript return retval; } - static std::pair get_arg_type(const AST_NodePtr &t_node, const chaiscript::detail::Dispatch_State &t_ss) + static std::pair get_arg_type(const AST_Node_Impl_Ptr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { if (t_node->children.size() < 2) { @@ -270,7 +319,7 @@ namespace chaiscript } } - static dispatch::Param_Types get_arg_types(const AST_NodePtr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { + static dispatch::Param_Types get_arg_types(const AST_Node_Impl_Ptr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { std::vector> retval; for (const auto &child : t_node->children) @@ -282,10 +331,11 @@ namespace chaiscript } }; - struct Equation_AST_Node final : AST_Node { - Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)), - m_oper(Operators::to_operator(text)) + template + struct Equation_AST_Node final : AST_Node_Impl { + Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)), + m_oper(Operators::to_operator(this->text)) { assert(children.size() == 2); } @@ -368,17 +418,18 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_clone_loc; }; - struct Global_Decl_AST_Node final : AST_Node { - Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { } + template + struct Global_Decl_AST_Node final : AST_Node_Impl { + Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const std::string &idname = [&]()->const std::string & { - if (children[0]->identifier == AST_Node_Type::Reference) { - return children[0]->children[0]->text; + if (this->children[0]->identifier == AST_Node_Type::Reference) { + return this->children[0]->children[0]->text; } else { - return children[0]->text; + return this->children[0]->text; } }(); @@ -393,9 +444,10 @@ namespace chaiscript }; - struct Var_Decl_AST_Node final : AST_Node { - Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { } + template + struct Var_Decl_AST_Node final : AST_Node_Impl { + Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const std::string &idname = this->children[0]->text; @@ -414,14 +466,15 @@ namespace chaiscript }; - struct Array_Call_AST_Node final : AST_Node { - Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { } + template + struct Array_Call_AST_Node final : AST_Node_Impl { + Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - const std::vector params{children[0]->eval(t_ss), children[1]->eval(t_ss)}; + const std::vector params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)}; try { fpp.save_params(params); @@ -437,24 +490,25 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Dot_Access_AST_Node final : AST_Node { - Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)), + template + struct Dot_Access_AST_Node final : AST_Node_Impl { + Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)), m_fun_name( - ((children[1]->identifier == AST_Node_Type::Fun_Call) || (children[1]->identifier == AST_Node_Type::Array_Call))? - children[1]->children[0]->text:children[1]->text) { } + ((this->children[1]->identifier == AST_Node_Type::Fun_Call) || (this->children[1]->identifier == AST_Node_Type::Array_Call))? + this->children[1]->children[0]->text:this->children[1]->text) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - Boxed_Value retval = children[0]->eval(t_ss); + Boxed_Value retval = this->children[0]->eval(t_ss); std::vector params{retval}; bool has_function_params = false; - if (children[1]->children.size() > 1) { + if (this->children[1]->children.size() > 1) { has_function_params = true; - for (const auto &child : children[1]->children[1]->children) { + for (const auto &child : this->children[1]->children[1]->children) { params.push_back(child->eval(t_ss)); } } @@ -495,23 +549,24 @@ namespace chaiscript }; - struct Lambda_AST_Node final : AST_Node { - Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)), - m_param_names(Arg_List_AST_Node::get_arg_names(children[1])) { } + template + struct Lambda_AST_Node final : AST_Node_Impl { + Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)), + m_param_names(Arg_List_AST_Node::get_arg_names(this->children[1])) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const auto captures = [&]()->std::map{ std::map named_captures; - for (const auto &capture : children[0]->children) { + for (const auto &capture : this->children[0]->children) { named_captures.insert(std::make_pair(capture->children[0]->text, capture->children[0]->eval(t_ss))); } return named_captures; }(); const auto numparams = this->children[1]->children.size(); - const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); + const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); const auto &lambda_node = this->children.back(); std::reference_wrapper engine(*t_ss); @@ -532,36 +587,38 @@ namespace chaiscript }; - struct Block_AST_Node final : AST_Node { - Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { } + template + struct Block_AST_Node final : AST_Node_Impl { + Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - const auto num_children = children.size(); + const auto num_children = this->children.size(); for (size_t i = 0; i < num_children-1; ++i) { - children[i]->eval(t_ss); + this->children[i]->eval(t_ss); } - return children.back()->eval(t_ss); + return this->children.back()->eval(t_ss); } }; - struct Def_AST_Node final : AST_Node { - Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { } + template + struct Def_AST_Node final : AST_Node_Impl { + Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ std::vector t_param_names; size_t numparams = 0; - AST_NodePtr guardnode; + AST_Node_Impl_Ptr guardnode; dispatch::Param_Types param_types; if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { numparams = this->children[1]->children.size(); - t_param_names = Arg_List_AST_Node::get_arg_names(this->children[1]); - param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); + t_param_names = Arg_List_AST_Node::get_arg_names(this->children[1]); + param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); if (this->children.size() > 3) { guardnode = this->children[2]; @@ -609,15 +666,16 @@ namespace chaiscript }; - struct While_AST_Node final : AST_Node { - While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { } + template + struct While_AST_Node final : AST_Node_Impl { + While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { - while (get_bool_condition(this->children[0]->eval(t_ss))) { + while (this->get_bool_condition(this->children[0]->eval(t_ss))) { try { this->children[1]->eval(t_ss); } catch (detail::Continue_Loop &) { @@ -634,51 +692,54 @@ namespace chaiscript } }; - struct Class_AST_Node final : AST_Node { - Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { } + template + struct Class_AST_Node final : AST_Node_Impl { + Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); /// \todo do this better // put class name in current scope so it can be looked up by the attrs and methods - t_ss.add_object("_current_class_name", const_var(children[0]->text)); + t_ss.add_object("_current_class_name", const_var(this->children[0]->text)); - children[1]->eval(t_ss); + this->children[1]->eval(t_ss); return void_var(); } }; - struct Ternary_Cond_AST_Node final : AST_Node { - Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Ternary_Cond, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 3); } + template + struct Ternary_Cond_AST_Node final : AST_Node_Impl { + Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Ternary_Cond, std::move(t_loc), std::move(t_children)) + { assert(this->children.size() == 3); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - if (get_bool_condition(children[0]->eval(t_ss))) { - return children[1]->eval(t_ss); + if (this->get_bool_condition(this->children[0]->eval(t_ss))) { + return this->children[1]->eval(t_ss); } else { - return children[2]->eval(t_ss); + return this->children[2]->eval(t_ss); } } }; - struct If_AST_Node final : AST_Node { - If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) + template + struct If_AST_Node final : AST_Node_Impl { + If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { - assert(children.size() == 2 || children.size() == 3); + assert(this->children.size() == 2 || this->children.size() == 3); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - if (get_bool_condition(children[0]->eval(t_ss))) { - return children[1]->eval(t_ss); + if (this->get_bool_condition(this->children[0]->eval(t_ss))) { + return this->children[1]->eval(t_ss); } else { - if (children.size() == 3) { - return children[2]->eval(t_ss); + if (this->children.size() == 3) { + return this->children[2]->eval(t_ss); } else { return void_var(); } @@ -686,23 +747,24 @@ namespace chaiscript } }; - struct For_AST_Node final : AST_Node { - For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::For, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 4); } + template + struct For_AST_Node final : AST_Node_Impl { + For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::For, std::move(t_loc), std::move(t_children)) + { assert(this->children.size() == 4); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { for ( - children[0]->eval(t_ss); - get_bool_condition(children[1]->eval(t_ss)); - children[2]->eval(t_ss) + this->children[0]->eval(t_ss); + this->get_bool_condition(this->children[1]->eval(t_ss)); + this->children[2]->eval(t_ss) ) { try { // Body of Loop - children[3]->eval(t_ss); + this->children[3]->eval(t_ss); } catch (detail::Continue_Loop &) { // we got a continue exception, which means all of the remaining // loop implementation is skipped and we just need to continue to @@ -718,9 +780,10 @@ namespace chaiscript }; - struct Switch_AST_Node final : AST_Node { - Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { } + template + struct Switch_AST_Node final : AST_Node_Impl { + Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { bool breaking = false; @@ -761,45 +824,48 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Case_AST_Node final : AST_Node { - Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children)) + template + struct Case_AST_Node final : AST_Node_Impl { + Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children)) { assert(children.size() == 2); /* how many children does it have? */ } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - children[1]->eval(t_ss); + this->children[1]->eval(t_ss); return void_var(); } }; - struct Default_AST_Node final : AST_Node { - Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children)) + template + struct Default_AST_Node final : AST_Node_Impl { + Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - children[0]->eval(t_ss); + this->children[0]->eval(t_ss); return void_var(); } }; - struct Inline_Array_AST_Node final : AST_Node { - Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { } + template + struct Inline_Array_AST_Node final : AST_Node_Impl { + Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { std::vector vec; - if (!children.empty()) { - vec.reserve(children[0]->children.size()); - for (const auto &child : children[0]->children) { + if (!this->children.empty()) { + vec.reserve(this->children[0]->children.size()); + for (const auto &child : this->children[0]->children) { auto obj = child->eval(t_ss); if (!obj.is_return_value()) { vec.push_back(t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions())); @@ -819,15 +885,16 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Inline_Map_AST_Node final : AST_Node { - Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { } + template + struct Inline_Map_AST_Node final : AST_Node_Impl { + Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { std::map retval; - for (const auto &child : children[0]->children) { + for (const auto &child : this->children[0]->children) { auto obj = child->children[1]->eval(t_ss); if (!obj.is_return_value()) { obj = t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions()); @@ -847,13 +914,14 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Return_AST_Node final : AST_Node { - Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { } + template + struct Return_AST_Node final : AST_Node_Impl { + Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ if (!this->children.empty()) { - throw detail::Return_Value(children[0]->eval(t_ss)); + throw detail::Return_Value(this->children[0]->eval(t_ss)); } else { throw detail::Return_Value(void_var()); @@ -861,19 +929,20 @@ namespace chaiscript } }; - struct File_AST_Node final : AST_Node { - File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { } + template + struct File_AST_Node final : AST_Node_Impl { + File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { - const auto num_children = children.size(); + const auto num_children = this->children.size(); if (num_children > 0) { for (size_t i = 0; i < num_children-1; ++i) { - children[i]->eval(t_ss); + this->children[i]->eval(t_ss); } - return children.back()->eval(t_ss); + return this->children.back()->eval(t_ss); } else { return void_var(); } @@ -885,9 +954,10 @@ namespace chaiscript } }; - struct Reference_AST_Node final : AST_Node { - Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children)) + template + struct Reference_AST_Node final : AST_Node_Impl { + Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ @@ -902,14 +972,15 @@ namespace chaiscript } }; - struct Prefix_AST_Node final : AST_Node { - Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)), - m_oper(Operators::to_operator(text, true)) + template + struct Prefix_AST_Node final : AST_Node_Impl { + Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)), + m_oper(Operators::to_operator(this->text, true)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ - Boxed_Value bv(children[0]->eval(t_ss)); + Boxed_Value bv(this->children[0]->eval(t_ss)); try { // short circuit arithmetic operations @@ -919,10 +990,10 @@ namespace chaiscript } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); fpp.save_params({bv}); - return t_ss->call_function(text, m_loc, {std::move(bv)}, t_ss.conversions()); + return t_ss->call_function(this->text, m_loc, {std::move(bv)}, t_ss.conversions()); } } catch (const exception::dispatch_error &e) { - throw exception::eval_error("Error with prefix operator evaluation: '" + text + "'", e.parameters, e.functions, false, *t_ss); + throw exception::eval_error("Error with prefix operator evaluation: '" + this->text + "'", e.parameters, e.functions, false, *t_ss); } } @@ -931,27 +1002,30 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Break_AST_Node final : AST_Node { - Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { } + template + struct Break_AST_Node final : AST_Node_Impl { + Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Break_Loop(); } }; - struct Continue_AST_Node final : AST_Node { - Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { } + template + struct Continue_AST_Node final : AST_Node_Impl { + Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Continue_Loop(); } }; - struct Noop_AST_Node final : public AST_Node { + template + struct Noop_AST_Node final : AST_Node_Impl { Noop_AST_Node() : - AST_Node("", AST_Node_Type::Noop, Parse_Location()) + AST_Node_Impl("", AST_Node_Type::Noop, Parse_Location()) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ @@ -961,24 +1035,27 @@ namespace chaiscript } }; - struct Map_Pair_AST_Node final : AST_Node { - Map_Pair_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Map_Pair, std::move(t_loc), std::move(t_children)) { } + template + struct Map_Pair_AST_Node final : AST_Node_Impl { + Map_Pair_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Map_Pair, std::move(t_loc), std::move(t_children)) { } }; - struct Value_Range_AST_Node final : AST_Node { - Value_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Value_Range, std::move(t_loc), std::move(t_children)) { } + template + struct Value_Range_AST_Node final : AST_Node_Impl { + Value_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Value_Range, std::move(t_loc), std::move(t_children)) { } }; - struct Inline_Range_AST_Node final : AST_Node { - Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { } + template + struct Inline_Range_AST_Node final : AST_Node_Impl { + Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { - auto oper1 = children[0]->children[0]->children[0]->eval(t_ss); - auto oper2 = children[0]->children[0]->children[1]->eval(t_ss); + auto oper1 = this->children[0]->children[0]->children[0]->eval(t_ss); + auto oper2 = this->children[0]->children[0]->children[1]->eval(t_ss); return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions()); } catch (const exception::dispatch_error &e) { @@ -990,9 +1067,10 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Try_AST_Node final : AST_Node { - Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { } + template + struct Try_AST_Node final : AST_Node_Impl { + Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { } Boxed_Value handle_exception(const chaiscript::detail::Dispatch_State &t_ss, const Boxed_Value &t_except) const { @@ -1005,17 +1083,17 @@ namespace chaiscript } for (size_t i = 1; i < end_point; ++i) { chaiscript::eval::detail::Scope_Push_Pop catch_scope(t_ss); - AST_NodePtr catch_block = this->children[i]; + AST_Node_Impl_Ptr catch_block = this->children[i]; if (catch_block->children.size() == 1) { //No variable capture, no guards retval = catch_block->children[0]->eval(t_ss); break; } else if (catch_block->children.size() == 2 || catch_block->children.size() == 3) { - const auto name = Arg_List_AST_Node::get_arg_name(catch_block->children[0]); + const auto name = Arg_List_AST_Node::get_arg_name(catch_block->children[0]); if (dispatch::Param_Types( - std::vector>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} + std::vector>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} ).match(std::vector{t_except}, t_ss.conversions())) { t_ss.add_object(name, t_except); @@ -1099,23 +1177,26 @@ namespace chaiscript }; - struct Catch_AST_Node final : AST_Node { - Catch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Catch, std::move(t_loc), std::move(t_children)) { } + template + struct Catch_AST_Node final : AST_Node_Impl { + Catch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Catch, std::move(t_loc), std::move(t_children)) { } }; - struct Finally_AST_Node final : AST_Node { - Finally_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Finally, std::move(t_loc), std::move(t_children)) { } + template + struct Finally_AST_Node final : AST_Node_Impl { + Finally_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Finally, std::move(t_loc), std::move(t_children)) { } }; - struct Method_AST_Node final : AST_Node { - Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { } + template + struct Method_AST_Node final : AST_Node_Impl { + Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ - AST_NodePtr guardnode; + AST_Node_Impl_Ptr guardnode; const auto d = t_ss->get_parent_locals(); const auto itr = d.find("_current_class_name"); @@ -1126,20 +1207,21 @@ namespace chaiscript std::vector t_param_names{"this"}; dispatch::Param_Types param_types; - if ((children.size() > static_cast(3 + class_offset)) && (children[static_cast(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { - auto args = Arg_List_AST_Node::get_arg_names(children[static_cast(2 + class_offset)]); + if ((this->children.size() > static_cast(3 + class_offset)) + && (this->children[static_cast(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { + auto args = Arg_List_AST_Node::get_arg_names(this->children[static_cast(2 + class_offset)]); t_param_names.insert(t_param_names.end(), args.begin(), args.end()); - param_types = Arg_List_AST_Node::get_arg_types(children[static_cast(2 + class_offset)], t_ss); + param_types = Arg_List_AST_Node::get_arg_types(this->children[static_cast(2 + class_offset)], t_ss); - if (children.size() > static_cast(4 + class_offset)) { - guardnode = children[static_cast(3 + class_offset)]; + if (this->children.size() > static_cast(4 + class_offset)) { + guardnode = this->children[static_cast(3 + class_offset)]; } } else { //no parameters - if (children.size() > static_cast(3 + class_offset)) { - guardnode = children[static_cast(2 + class_offset)]; + if (this->children.size() > static_cast(3 + class_offset)) { + guardnode = this->children[static_cast(2 + class_offset)]; } } @@ -1156,8 +1238,8 @@ namespace chaiscript } try { - const std::string & function_name = children[static_cast(1 + class_offset)]->text; - auto node = children.back(); + const std::string & function_name = this->children[static_cast(1 + class_offset)]->text; + auto node = this->children.back(); if (function_name == class_name) { param_types.push_front(class_name, Type_Info()); @@ -1198,9 +1280,10 @@ namespace chaiscript }; - struct Attr_Decl_AST_Node final : AST_Node { - Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { } + template + struct Attr_Decl_AST_Node final : AST_Node_Impl { + Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -1234,28 +1317,30 @@ namespace chaiscript }; - struct Logical_And_AST_Node final : AST_Node { - Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_And, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 2); } + template + struct Logical_And_AST_Node final : AST_Node_Impl { + Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Logical_And, std::move(t_loc), std::move(t_children)) + { assert(this->children.size() == 2); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - return const_var(get_bool_condition(children[0]->eval(t_ss)) - && get_bool_condition(children[1]->eval(t_ss))); + return const_var(this->get_bool_condition(this->children[0]->eval(t_ss)) + && this->get_bool_condition(this->children[1]->eval(t_ss))); } }; - struct Logical_Or_AST_Node final : AST_Node { - Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 2); } + template + struct Logical_Or_AST_Node final : AST_Node_Impl { + Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children)) + { assert(this->children.size() == 2); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - return const_var(get_bool_condition(children[0]->eval(t_ss)) - || get_bool_condition(children[1]->eval(t_ss))); + return const_var(this->get_bool_condition(this->children[0]->eval(t_ss)) + || this->get_bool_condition(this->children[1]->eval(t_ss))); } }; } diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 370c3c4..ccf8978 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -22,39 +22,41 @@ namespace chaiscript { { } - AST_NodePtr optimize(AST_NodePtr p) { + template + auto optimize(eval::AST_Node_Impl_Ptr p) { (void)std::initializer_list{ (p = T::optimize(p), 0)... }; return p; } }; template - auto child_at(const T &node, const size_t offset) { + auto child_at(const eval::AST_Node_Impl_Ptr &node, const size_t offset) { if (node->identifier == AST_Node_Type::Compiled) { - return dynamic_cast(*node).m_original_node->children[offset]; + return dynamic_cast&>(*node).m_original_node->children[offset]; } else { return node->children[offset]; } } template - auto child_count(const T &node) { + auto child_count(const eval::AST_Node_Impl_Ptr &node) { if (node->identifier == AST_Node_Type::Compiled) { - return dynamic_cast(*node).m_original_node->children.size(); + return dynamic_cast&>(*node).m_original_node->children.size(); } else { return node->children.size(); } } - template - AST_NodePtr make_compiled_node(const AST_NodePtr &original_node, std::vector children, T callable) + template + auto make_compiled_node(const eval::AST_Node_Impl_Ptr &original_node, std::vector> children, Callable callable) { - return chaiscript::make_shared(original_node, std::move(children), std::move(callable)); + return chaiscript::make_shared, eval::Compiled_AST_Node>(original_node, std::move(children), std::move(callable)); } struct Return { - AST_NodePtr optimize(const AST_NodePtr &p) + template + auto optimize(const eval::AST_Node_Impl_Ptr &p) { if (p->identifier == AST_Node_Type::Def && !p->children.empty()) @@ -95,7 +97,8 @@ namespace chaiscript { } struct Block { - AST_NodePtr optimize(const AST_NodePtr &node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { if (node->identifier == AST_Node_Type::Block && node->children.size() == 1 && !contains_var_decl_in_scope(node)) @@ -108,12 +111,13 @@ namespace chaiscript { }; struct If { - AST_NodePtr optimize(const AST_NodePtr &node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { if ((node->identifier == AST_Node_Type::If || node->identifier == AST_Node_Type::Ternary_Cond) && node->children.size() >= 2 && node->children[0]->identifier == AST_Node_Type::Constant) { - const auto condition = std::dynamic_pointer_cast(node->children[0])->m_value; + const auto condition = std::dynamic_pointer_cast>(node->children[0])->m_value; if (condition.get_type_info().bare_equal_type_info(typeid(bool))) { if (boxed_cast(condition)) { return node->children[1]; @@ -128,7 +132,8 @@ namespace chaiscript { }; struct Constant_Fold { - AST_NodePtr optimize(const AST_NodePtr &node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2 @@ -139,12 +144,12 @@ namespace chaiscript { const auto oper = node->text; const auto parsed = Operators::to_operator(oper); if (parsed != Operators::Opers::invalid) { - const auto lhs = std::dynamic_pointer_cast(node->children[0])->m_value; - const auto rhs = std::dynamic_pointer_cast(node->children[1])->m_value; + const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; + const auto rhs = std::dynamic_pointer_cast>(node->children[1])->m_value; if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) { const auto val = Boxed_Number::do_oper(parsed, lhs, rhs); const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text; - return chaiscript::make_shared(std::move(match), node->location, std::move(val)); + return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); } } } catch (const std::exception &) { @@ -157,7 +162,8 @@ namespace chaiscript { }; struct For_Loop { - AST_NodePtr optimize(const AST_NodePtr &for_node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &for_node) { if (for_node->identifier != AST_Node_Type::For) { return for_node; @@ -183,8 +189,8 @@ namespace chaiscript { && child_at(prefix_node, 0)->identifier == AST_Node_Type::Id && child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text) { - const Boxed_Value &begin = std::dynamic_pointer_cast(child_at(eq_node, 1))->m_value; - const Boxed_Value &end = std::dynamic_pointer_cast(child_at(binary_node, 1))->m_value; + const Boxed_Value &begin = std::dynamic_pointer_cast>(child_at(eq_node, 1))->m_value; + const Boxed_Value &end = std::dynamic_pointer_cast>(child_at(binary_node, 1))->m_value; const std::string &id = child_at(prefix_node, 0)->text; if (begin.get_type_info().bare_equal(user_type()) @@ -196,7 +202,7 @@ namespace chaiscript { const auto body = child_at(for_node, 3); return make_compiled_node(for_node, {body}, - [id, start_int, end_int](const std::vector &children, const chaiscript::detail::Dispatch_State &t_ss) { + [id, start_int, end_int](const std::vector> &children, const chaiscript::detail::Dispatch_State &t_ss) { assert(children.size() == 1); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index f8cb549..bba9b6a 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -21,6 +21,7 @@ #include "../dispatchkit/boxed_value.hpp" #include "chaiscript_common.hpp" #include "chaiscript_optimizer.hpp" +#include "chaiscript_tracer.hpp" #if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min) #define CHAISCRIPT_PUSHED_MIN_MAX @@ -57,23 +58,12 @@ namespace chaiscript }; } - class ChaiScript_Parser_Base - { - public: - virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0; - virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; - virtual ~ChaiScript_Parser_Base() = default; - ChaiScript_Parser_Base() = default; - ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default; - ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete; - ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete; - protected: - ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; - }; - - template - class ChaiScript_Parser : public ChaiScript_Parser_Base { + template + class ChaiScript_Parser final : public ChaiScript_Parser_Base { + void *get_tracer_ptr() { + return &m_tracer; + } static std::array, detail::max_alphabet> build_alphabet() { @@ -190,7 +180,7 @@ namespace chaiscript const std::array &m_operators = create_operators(); std::shared_ptr m_filename; - std::vector m_match_stack; + std::vector> m_match_stack; struct Position @@ -293,11 +283,13 @@ namespace chaiscript Position m_position; + Tracer m_tracer; Optimizer m_optimizer; public: - explicit ChaiScript_Parser(Optimizer optimizer=Optimizer()) - : m_optimizer(std::move(optimizer)) + explicit ChaiScript_Parser(Tracer tracer = Tracer(), Optimizer optimizer=Optimizer()) + : m_tracer(std::move(tracer)), + m_optimizer(std::move(optimizer)) { m_match_stack.reserve(2); } @@ -314,8 +306,8 @@ namespace chaiscript /// Prints the parsed ast_nodes as a tree void debug_print(AST_NodePtr t, std::string prepend = "") const override { std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start().line << ", " << t->start().column << '\n'; - for (unsigned int j = 0; j < t->children.size(); ++j) { - debug_print(t->children[j], prepend + " "); + for (const auto &node : t->get_children()) { + debug_print(node, prepend + " "); } } @@ -347,7 +339,7 @@ namespace chaiscript } }(); - std::vector new_children; + std::vector> new_children; if (is_deep) { new_children.assign(std::make_move_iterator(m_match_stack.begin() + static_cast(t_match_start)), @@ -358,7 +350,7 @@ namespace chaiscript /// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position m_match_stack.push_back( m_optimizer.optimize( - chaiscript::make_shared( + chaiscript::make_shared, NodeType>( std::move(t_text), std::move(filepos), std::move(new_children))) @@ -669,9 +661,9 @@ namespace chaiscript } template - std::shared_ptr make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param) + std::shared_ptr> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param) { - return chaiscript::make_shared(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward(param)...); + return chaiscript::make_shared, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward(param)...); } /// Reads a number from the input, detecting if it's an integer or floating point @@ -687,20 +679,20 @@ namespace chaiscript if (Hex_()) { auto match = Position::str(start, m_position); auto bv = buildInt(16, match, true); - m_match_stack.emplace_back(make_node(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.emplace_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); return true; } if (Binary_()) { auto match = Position::str(start, m_position); auto bv = buildInt(2, match, true); - m_match_stack.push_back(make_node(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); return true; } if (Float_()) { auto match = Position::str(start, m_position); auto bv = buildFloat(match); - m_match_stack.push_back(make_node(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); return true; } else { @@ -708,11 +700,11 @@ namespace chaiscript auto match = Position::str(start, m_position); if (!match.empty() && (match[0] == '0')) { auto bv = buildInt(8, match, false); - m_match_stack.push_back(make_node(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); } else if (!match.empty()) { auto bv = buildInt(10, match, false); - m_match_stack.push_back(make_node(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); } else { return false; } @@ -773,20 +765,20 @@ namespace chaiscript const auto text = Position::str(start, m_position); if (text == "true") { - m_match_stack.push_back(make_node(text, start.line, start.col, const_var(true))); + m_match_stack.push_back(make_node>(text, start.line, start.col, const_var(true))); } else if (text == "false") { - m_match_stack.push_back(make_node(text, start.line, start.col, const_var(false))); + m_match_stack.push_back(make_node>(text, start.line, start.col, const_var(false))); } else if (text == "Infinity") { - m_match_stack.push_back(make_node(text, start.line, start.col, + m_match_stack.push_back(make_node>(text, start.line, start.col, const_var(std::numeric_limits::infinity()))); } else if (text == "NaN") { - m_match_stack.push_back(make_node(text, start.line, start.col, + m_match_stack.push_back(make_node>(text, start.line, start.col, const_var(std::numeric_limits::quiet_NaN()))); } else if (text == "_") { - m_match_stack.push_back(make_node(text, start.line, start.col, + m_match_stack.push_back(make_node>(text, start.line, start.col, Boxed_Value(std::make_shared()))); } else { - m_match_stack.push_back(make_node( + m_match_stack.push_back(make_node>( [&]()->std::string{ if (*start == '`') { // 'escaped' literal, like an operator name @@ -820,7 +812,7 @@ namespace chaiscript Id(); } - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } @@ -1020,11 +1012,11 @@ namespace chaiscript if (*s == '{') { //We've found an interpolation point - m_match_stack.push_back(make_node(match, start.line, start.col, const_var(match))); + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(match))); if (cparser.is_interpolated) { //If we've seen previous interpolation, add on instead of making a new one - build_match(prev_stack_top, "+"); + build_match>(prev_stack_top, "+"); } //We've finished with the part of the string up to this point, so clear it @@ -1044,19 +1036,19 @@ namespace chaiscript const auto tostr_stack_top = m_match_stack.size(); - m_match_stack.push_back(make_node("to_string", start.line, start.col)); + m_match_stack.push_back(make_node>("to_string", start.line, start.col)); const auto ev_stack_top = m_match_stack.size(); try { - m_match_stack.push_back(parse(eval_match, "instr eval")); + m_match_stack.push_back(parse_instr_eval(eval_match)); } catch (const exception::eval_error &e) { throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename); } - build_match(ev_stack_top); - build_match(tostr_stack_top); - build_match(prev_stack_top, "+"); + build_match>(ev_stack_top); + build_match>(tostr_stack_top); + build_match>(prev_stack_top, "+"); } else { throw exception::eval_error("Unclosed in-string eval", File_Position(start.line, start.col), *m_filename); } @@ -1073,10 +1065,10 @@ namespace chaiscript return cparser.is_interpolated; }(); - m_match_stack.push_back(make_node(match, start.line, start.col, const_var(match))); + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(match))); if (is_interpolated) { - build_match(prev_stack_top, "+"); + build_match>(prev_stack_top, "+"); } return true; @@ -1138,7 +1130,7 @@ namespace chaiscript throw exception::eval_error("Single-quoted strings must be 1 character long", File_Position(m_position.line, m_position.col), *m_filename); } - m_match_stack.push_back(make_node(match, start.line, start.col, const_var(char(match.at(0))))); + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(char(match.at(0))))); return true; } else { @@ -1291,7 +1283,7 @@ namespace chaiscript } } } - build_match(prev_stack_top); + build_match>(prev_stack_top); SkipWS(true); @@ -1316,7 +1308,7 @@ namespace chaiscript } } } - build_match(prev_stack_top); + build_match>(prev_stack_top); SkipWS(true); @@ -1342,7 +1334,7 @@ namespace chaiscript } } - build_match(prev_stack_top); + build_match>(prev_stack_top); SkipWS(true); @@ -1358,7 +1350,7 @@ namespace chaiscript if (Value_Range()) { retval = true; - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Map_Pair()) { retval = true; while (Eol()) {} @@ -1368,7 +1360,7 @@ namespace chaiscript throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename); } } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Operator()) { retval = true; while (Eol()) {} @@ -1378,7 +1370,7 @@ namespace chaiscript throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename); } } - build_match(prev_stack_top); + build_match>(prev_stack_top); } SkipWS(true); @@ -1402,7 +1394,7 @@ namespace chaiscript } } else { // make sure we always have the same number of nodes - build_match(prev_stack_top); + build_match>(prev_stack_top); } if (Char('(')) { @@ -1421,7 +1413,7 @@ namespace chaiscript throw exception::eval_error("Incomplete anonymous function", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1472,9 +1464,9 @@ namespace chaiscript } if (is_method || t_class_context) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { - build_match(prev_stack_top); + build_match>(prev_stack_top); } } @@ -1519,7 +1511,7 @@ namespace chaiscript if (!Block()) { throw exception::eval_error("Incomplete 'catch' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(catch_stack_top); + build_match>(catch_stack_top); has_matches = true; } } @@ -1532,10 +1524,10 @@ namespace chaiscript if (!Block()) { throw exception::eval_error("Incomplete 'finally' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(finally_stack_top); + build_match>(finally_stack_top); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1582,7 +1574,7 @@ namespace chaiscript } } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1608,7 +1600,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'class' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1638,7 +1630,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'while' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1653,7 +1645,7 @@ namespace chaiscript { throw exception::eval_error("'for' loop initial statment missing", File_Position(m_position.line, m_position.col), *m_filename); } else { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } } @@ -1663,13 +1655,13 @@ namespace chaiscript { throw exception::eval_error("'for' loop condition missing", File_Position(m_position.line, m_position.col), *m_filename); } else { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } } if (!Equation()) { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } return true; @@ -1699,7 +1691,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'for' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1729,7 +1721,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'case' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Keyword("default")) { retval = true; @@ -1739,7 +1731,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'default' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1779,7 +1771,7 @@ namespace chaiscript throw exception::eval_error("Incomplete block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { @@ -1804,10 +1796,10 @@ namespace chaiscript } if (m_match_stack.size() == prev_stack_top) { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1828,10 +1820,10 @@ namespace chaiscript } if (m_match_stack.size() == prev_stack_top) { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1843,7 +1835,7 @@ namespace chaiscript if (Keyword("return")) { Operator(); - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -1855,7 +1847,7 @@ namespace chaiscript const auto prev_stack_top = m_match_stack.size(); if (Keyword("break")) { - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -1867,7 +1859,7 @@ namespace chaiscript const auto prev_stack_top = m_match_stack.size(); if (Keyword("continue")) { - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -1896,14 +1888,14 @@ namespace chaiscript throw exception::eval_error("Incomplete function call", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); /// \todo Work around for method calls until we have a better solution if (!m_match_stack.back()->children.empty()) { if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Dot_Access) { if (m_match_stack.empty()) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); if (m_match_stack.back()->children.empty()) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); - AST_NodePtr dot_access = m_match_stack.back()->children[0]; - AST_NodePtr func_call = m_match_stack.back(); + auto dot_access = m_match_stack.back()->children[0]; + auto func_call = m_match_stack.back(); m_match_stack.pop_back(); func_call->children.erase(func_call->children.begin()); if (dot_access->children.empty()) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); @@ -1921,7 +1913,7 @@ namespace chaiscript throw exception::eval_error("Incomplete array access", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Symbol(".")) { has_more = true; @@ -1932,7 +1924,7 @@ namespace chaiscript if ( std::distance(m_match_stack.begin() + static_cast(prev_stack_top), m_match_stack.end()) != 2) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } } } @@ -1953,14 +1945,14 @@ namespace chaiscript throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Keyword("auto") || Keyword("var") ) { retval = true; if (Reference()) { // we built a reference node - continue } else if (Id()) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1972,7 +1964,7 @@ namespace chaiscript throw exception::eval_error("Incomplete global declaration", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Keyword("attr")) { retval = true; @@ -1987,7 +1979,7 @@ namespace chaiscript } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -2020,17 +2012,17 @@ namespace chaiscript } if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) { if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Map_Pair) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { - build_match(prev_stack_top); + build_match>(prev_stack_top); } } else { - build_match(prev_stack_top); + build_match>(prev_stack_top); } return true; @@ -2048,7 +2040,7 @@ namespace chaiscript throw exception::eval_error("Incomplete '&' expression", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -2069,7 +2061,7 @@ namespace chaiscript throw exception::eval_error("Incomplete prefix '" + oper + "' expression", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); return true; } } @@ -2114,7 +2106,7 @@ namespace chaiscript throw exception::eval_error("Incomplete '" + oper + "' expression", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { throw exception::eval_error("Incomplete '" + oper + "' expression", @@ -2130,14 +2122,14 @@ namespace chaiscript case(Operator_Precidence::Bitwise_Xor) : case(Operator_Precidence::Bitwise_Or) : case(Operator_Precidence::Comparison) : - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); break; case(Operator_Precidence::Logical_And) : - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); break; case(Operator_Precidence::Logical_Or) : - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); break; default: @@ -2167,7 +2159,7 @@ namespace chaiscript throw exception::eval_error("Incomplete map pair", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { m_position = prev_pos; @@ -2194,7 +2186,7 @@ namespace chaiscript throw exception::eval_error("Incomplete value range", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { m_position = prev_pos; @@ -2220,7 +2212,7 @@ namespace chaiscript throw exception::eval_error("Incomplete equation", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top, sym); + build_match>(prev_stack_top, sym); return true; } } @@ -2298,11 +2290,26 @@ namespace chaiscript AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override { - ChaiScript_Parser parser(*this); + ChaiScript_Parser parser(*this); parser.m_match_stack.clear(); return parser.parse_internal(t_input, t_fname); } + eval::AST_Node_Impl_Ptr parse_instr_eval(const std::string &t_input) + { + const auto last_position = m_position; + const auto last_filename = m_filename; + const auto last_match_stack = std::exchange(m_match_stack, decltype(m_match_stack){}); + + const auto retval = parse_internal(t_input, "instr eval"); + + m_position = std::move(last_position); + m_filename = std::move(last_filename); + m_match_stack = std::move(last_match_stack); + + return std::dynamic_pointer_cast>(retval); + } + /// Parses the given input string, tagging parsed ast_nodes with the given m_filename. AST_NodePtr parse_internal(const std::string &t_input, std::string t_fname) { m_position = Position(t_input.begin(), t_input.end()); @@ -2319,10 +2326,10 @@ namespace chaiscript if (m_position.has_more()) { throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname); } else { - build_match(0); + build_match>(0); } } else { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } return m_match_stack.front(); diff --git a/include/chaiscript/language/chaiscript_tracer.hpp b/include/chaiscript/language/chaiscript_tracer.hpp new file mode 100644 index 0000000..938b667 --- /dev/null +++ b/include/chaiscript/language/chaiscript_tracer.hpp @@ -0,0 +1,43 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +#ifndef CHAISCRIPT_TRACER_HPP_ +#define CHAISCRIPT_TRACER_HPP_ + +namespace chaiscript { + namespace eval { + + struct Noop_Tracer + { + template + static void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl *) + { + } + }; + + template + struct Tracer : T... + { + Tracer() = default; + Tracer(T ... t) + : T(std::move(t))... + { + } + + void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl> *node) { + (void)std::initializer_list{ (T::trace(ds, node), 0)... }; + } + + static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl> *node) { + ds->get_parser().get_tracer>().do_trace(ds, node); + } + }; + + } +} + +#endif +