diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index b157cac2..b1e16688 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -62,7 +62,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval - enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl, + enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl, Assign_Decl, Array_Call, Dot_Access, Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range, Inline_Range, Try, Catch, Finally, Method, Attr_Decl, @@ -77,7 +77,7 @@ namespace chaiscript { /// Helper lookup to get the name of each node type inline const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { - static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", + static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl", "Array_Call", "Dot_Access", "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl", diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 508f4d3a..e0933b71 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -555,6 +555,27 @@ namespace chaiscript } }; + template + struct Assign_Decl_AST_Node final : AST_Node_Impl { + Assign_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::Assign_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; + + try { + Boxed_Value bv(detail::clone_if_necessary(this->children[1]->eval(t_ss), m_loc, t_ss)); + bv.reset_return_value(); + t_ss.add_object(idname, bv); + return bv; + } catch (const exception::name_conflict_error &e) { + throw exception::eval_error("Variable redefined '" + e.name() + "'"); + } + } + private: + mutable std::atomic_uint_fast32_t m_loc = {0}; + }; + template struct Array_Call_AST_Node final : AST_Node_Impl { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 675d092c..55a19c58 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -97,7 +97,7 @@ namespace chaiscript { template bool contains_var_decl_in_scope(const eval::AST_Node_Impl &node) { - if (node.identifier == AST_Node_Type::Var_Decl) { + if (node.identifier == AST_Node_Type::Var_Decl || node.identifier == AST_Node_Type::Assign_Decl) { return true; } @@ -208,6 +208,27 @@ namespace chaiscript { } }; + struct Assign_Decl { + template + auto optimize(eval::AST_Node_Impl_Ptr node) { + if ((node->identifier == AST_Node_Type::Equation) + && node->text == "=" + && node->children.size() == 2 + && node->children[0]->identifier == AST_Node_Type::Var_Decl + ) + { + std::vector> new_children; + new_children.push_back(std::move(node->children[0]->children[0])); + new_children.push_back(std::move(node->children[1])); + return chaiscript::make_unique, eval::Assign_Decl_AST_Node>(node->text, + node->location, std::move(new_children) ); + } + + return node; + } + }; + + struct If { template auto optimize(eval::AST_Node_Impl_Ptr node) { @@ -440,7 +461,7 @@ namespace chaiscript { }; typedef Optimizer Optimizer_Default; + optimizer::If, optimizer::Return, optimizer::Dead_Code, optimizer::Block, optimizer::For_Loop, optimizer::Assign_Decl> Optimizer_Default; } }