diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 7196ef1..8eee132 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -61,48 +61,57 @@ namespace chaiscript * The struct that doubles as both a parser ast_node and an AST node */ struct AST_Node { - std::string text; - int identifier; - boost::shared_ptr filename; - File_Position start, end; - std::vector children; - AST_NodePtr annotation; + public: + const std::string text; + const int identifier; + boost::shared_ptr filename; + File_Position start, end; + std::vector children; + AST_NodePtr annotation; - AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr &t_fname, - int t_start_line, int t_start_col, int t_end_line, int t_end_col) : - text(t_ast_node_text), identifier(t_id), filename(t_fname), - start(t_start_line, t_start_col), end(t_end_line, t_end_col) - { - } + /** + * Prints the contents of an AST node, including its children, recursively + */ + std::string to_string(std::string t_prepend = "") { + std::ostringstream oss; - AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr &t_fname) : - text(t_ast_node_text), identifier(t_id), filename(t_fname) {} - - virtual ~AST_Node() {} - - /** - * Prints the contents of an AST node, including its children, recursively - */ - std::string to_string(std::string t_prepend = "") { - std::ostringstream oss; - - oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " - << this->text << " : " << this->start.line << ", " << this->start.column << std::endl; - - for (unsigned int j = 0; j < this->children.size(); ++j) { - oss << this->children[j]->to_string(t_prepend + " "); + oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " + << this->text << " : " << this->start.line << ", " << this->start.column << std::endl; + + for (unsigned int j = 0; j < this->children.size(); ++j) { + oss << this->children[j]->to_string(t_prepend + " "); + } + return oss.str(); } - return oss.str(); - } - std::string internal_to_string() { - return to_string(); - } + std::string internal_to_string() { + return to_string(); + } + + virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &) + { + Boxed_Value bv; + throw std::runtime_error("Undispatched ast_node (internal error)"); + } + + void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child) + { + std::replace(children.begin(), children.end(), t_child, t_new_child); + } + + protected: + AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr &t_fname, + int t_start_line, int t_start_col, int t_end_line, int t_end_col) : + text(t_ast_node_text), identifier(t_id), filename(t_fname), + start(t_start_line, t_start_col), end(t_end_line, t_end_col) + { + } + + AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr &t_fname) : + text(t_ast_node_text), identifier(t_id), filename(t_fname) {} + + virtual ~AST_Node() {} - virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &) { - Boxed_Value bv; - throw std::runtime_error("Undispatched ast_node (internal error)"); - } }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 23fa43b..d918016 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -89,23 +89,30 @@ namespace chaiscript struct Int_AST_Node : public AST_Node { public: Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(int(atoi(this->text.c_str())))) { } virtual ~Int_AST_Node() {} virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ - return const_var(int(atoi(this->text.c_str()))); + return m_value; } + private: + Boxed_Value m_value; + }; struct Float_AST_Node : public AST_Node { public: Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), + m_value(const_var(double(atof(this->text.c_str())))) { } virtual ~Float_AST_Node() {} virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ - return const_var(double(atof(this->text.c_str()))); + return m_value; } + private: + Boxed_Value m_value; + }; struct Id_AST_Node : public AST_Node { @@ -472,7 +479,7 @@ namespace chaiscript } catch(const exception::dispatch_error &e){ t_ss.set_stack(prev_stack); - throw exception::eval_error(std::string(e.what())); + throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name); } catch(detail::Return_Value &rv) { t_ss.set_stack(prev_stack); @@ -510,23 +517,30 @@ namespace chaiscript struct Quoted_String_AST_Node : public AST_Node { public: Quoted_String_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Quoted_String, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), + m_value(const_var(this->text)) { } virtual ~Quoted_String_AST_Node() {} - virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ - return const_var(this->text); + virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &) { + return m_value; } + private: + Boxed_Value m_value; + }; struct Single_Quoted_String_AST_Node : public AST_Node { public: Single_Quoted_String_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Single_Quoted_String, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), + m_value(const_var(char(this->text[0]))) { } virtual ~Single_Quoted_String_AST_Node() {} virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ - return const_var(char(this->text[0])); + return m_value; } + private: + Boxed_Value m_value; }; struct Lambda_AST_Node : public AST_Node { @@ -656,7 +670,7 @@ namespace chaiscript While_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::While, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~While_AST_Node() {} - virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ + virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss) { bool cond; t_ss.new_scope(); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 1a574d6..985cf22 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1312,7 +1312,12 @@ namespace chaiscript has_matches = false; if (Keyword("else", true)) { if (Keyword("if")) { - m_match_stack.back()->text = "else if"; + AST_NodePtr back(m_match_stack.back()); + m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if", back->identifier)); + m_match_stack.back()->start = back->start; + m_match_stack.back()->end = back->end; + m_match_stack.back()->children = back->children; + m_match_stack.back()->annotation = back->annotation; if (!Char('(')) { throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_line, m_col), *m_filename); } diff --git a/src/reflection.cpp b/src/reflection.cpp index aca21d9..ee8d152 100644 --- a/src/reflection.cpp +++ b/src/reflection.cpp @@ -62,7 +62,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect CHAISCRIPT_CLASS( m, chaiscript::AST_Node, - (chaiscript::AST_Node (const std::string &, int, const boost::shared_ptr &)), + , ((text)) ((identifier)) ((filename)) @@ -70,6 +70,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect ((end)) ((internal_to_string)) ((children)) + ((replace_child)) ); CHAISCRIPT_CLASS( m, diff --git a/unittests/reflection_test.chai b/unittests/reflection_test.chai index 7841f23..88b39cc 100644 --- a/unittests/reflection_test.chai +++ b/unittests/reflection_test.chai @@ -8,7 +8,11 @@ assert_equal(eval(a), 7) var childs := a.children.front().children var node := childs[0] -node.text = "9" +var parser2 := ChaiScript_Parser() +parser2.parse("9", "INPUT") + + +a.children.front().replace_child(childs[0], parser2.ast()) assert_equal(eval(a), 13) assert_equal(node.filename, "INPUT")