From 2b735d1b3acb6c346f55beb9125324b0b37fe997 Mon Sep 17 00:00:00 2001 From: superfunc Date: Sat, 21 Oct 2017 15:14:27 -0700 Subject: [PATCH 1/5] Fix link in readme --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 8bf4deec..8323a128 100644 --- a/readme.md +++ b/readme.md @@ -25,7 +25,7 @@ Release under the BSD license, see "license.txt" for details. Introduction ============ -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/ChaiScript/ChaiScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Gitter](https://badges.gitter.im/JoinChat.svg)](https://gitter.im/ChaiScript/ChaiScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ChaiScript is one of the only embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development From 79d985d6ffdde4a42e40e07a2ad72f97788be78a Mon Sep 17 00:00:00 2001 From: Glen Fraser Date: Tue, 24 Oct 2017 20:10:50 +0200 Subject: [PATCH 2/5] Fix JSON parsing for floats with negative exponents - also add unit tests to cover some broken (now fixed) cases. --- include/chaiscript/utility/json.hpp | 7 ++++--- unittests/json_14.chai | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 unittests/json_14.chai diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 693f19da..838bd5b9 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -568,6 +568,7 @@ struct JSONParser { char c = '\0'; bool isDouble = false; bool isNegative = false; + bool isExpNegative = false; long exp = 0; if( offset < str.size() && str.at(offset) == '-' ) { isNegative = true; @@ -587,7 +588,7 @@ struct JSONParser { if( offset < str.size() && (c == 'E' || c == 'e' )) { c = str.at(offset++); if( c == '-' ) { - exp_str += '-'; + isExpNegative = true; } else if( c == '+' ) { // do nothing } else { @@ -603,9 +604,9 @@ struct JSONParser { } else { break; -} + } } - exp = chaiscript::parse_num( exp_str ); + exp = chaiscript::parse_num( exp_str ) * (isExpNegative?-1:1); } else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) { throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'"); diff --git a/unittests/json_14.chai b/unittests/json_14.chai new file mode 100644 index 00000000..e6490a1d --- /dev/null +++ b/unittests/json_14.chai @@ -0,0 +1,5 @@ +assert_equal(from_json("9.9e-02"), 9.9e-02) +assert_equal(from_json("-13.57e+3"), -13570.0) +assert_equal(from_json("1E-01"), 0.1) +assert_equal(from_json("-314159e-5"), -3.14159) +assert_equal(from_json("5e+04"), 50000) From 784c3a9720fbb148fd45adfc2919ed54937c3fea Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Nov 2017 07:12:17 -0700 Subject: [PATCH 3/5] Add slow test for creating variables References #356 --- performance_tests/create_variables.chai | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 performance_tests/create_variables.chai diff --git a/performance_tests/create_variables.chai b/performance_tests/create_variables.chai new file mode 100644 index 00000000..e63e1a46 --- /dev/null +++ b/performance_tests/create_variables.chai @@ -0,0 +1,11 @@ +def var_test(int n) +{ + for (var i = 0; i < n; ++i) { + var j = 0 + } +} + +var n = 500000 +var_test(n) // takes 2.6 s + + From 50a2773081131cbb15e8d43e2b5aebdf18975fbf Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Nov 2017 09:01:17 -0700 Subject: [PATCH 4/5] Reduce cost of cloning common built in types Re: #356 --- .../chaiscript/dispatchkit/boxed_number.hpp | 4 ++ .../chaiscript/language/chaiscript_eval.hpp | 39 ++++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 8f1e871f..dafc1234 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -521,6 +521,10 @@ namespace chaiscript validate_boxed_number(bv); } + static Boxed_Value clone(const Boxed_Value &t_bv) { + return Boxed_Number(t_bv).get_as(t_bv.get_type_info()).bv; + } + static bool is_floating_point(const Boxed_Value &t_bv) { const Type_Info &inp_ = t_bv.get_type_info(); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index a9819440..508f4d3a 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -88,6 +88,23 @@ namespace chaiscript return std::move(rv.retval); } } + + inline Boxed_Value clone_if_necessary(Boxed_Value incoming, std::atomic_uint_fast32_t &t_loc, const chaiscript::detail::Dispatch_State &t_ss) + { + if (!incoming.is_return_value()) + { + if (incoming.get_type_info().is_arithmetic()) { + return Boxed_Number::clone(incoming); + } else if (incoming.get_type_info().bare_equal_type_info(typeid(bool))) { + return Boxed_Value(*static_cast(incoming.get_const_ptr())); + } else { + return t_ss->call_function("clone", t_loc, {incoming}, t_ss.conversions()); + } + } else { + incoming.reset_return_value(); + return incoming; + } + } } template @@ -459,11 +476,7 @@ namespace chaiscript lhs.reset_return_value(); return rhs; } else { - if (!rhs.is_return_value()) - { - rhs = t_ss->call_function("clone", m_clone_loc, {rhs}, t_ss.conversions()); - } - rhs.reset_return_value(); + rhs = detail::clone_if_necessary(std::move(rhs), m_clone_loc, t_ss); } } @@ -1056,12 +1069,7 @@ namespace chaiscript 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())); - } else { - vec.push_back(std::move(obj)); - } + vec.push_back(detail::clone_if_necessary(child->eval(t_ss), m_loc, t_ss)); } } return const_var(std::move(vec)); @@ -1086,12 +1094,8 @@ namespace chaiscript std::map retval; 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()); - } - - retval[t_ss->boxed_cast(child->children[0]->eval(t_ss))] = std::move(obj); + retval.insert(std::make_pair(t_ss->boxed_cast(child->children[0]->eval(t_ss)), + detail::clone_if_necessary(child->children[1]->eval(t_ss), m_loc, t_ss))); } return const_var(std::move(retval)); @@ -1450,7 +1454,6 @@ namespace chaiscript function_name); } } catch (const exception::name_conflict_error &e) { - std::cout << "Method!!" << std::endl; throw exception::eval_error("Method redefined '" + e.name() + "'"); } return void_var(); From 830766393895501fc0da6212f5b13e2d367ed9bc Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Nov 2017 10:26:58 -0700 Subject: [PATCH 5/5] Look for and optimize decl assignments Re: #356 --- .../chaiscript/language/chaiscript_common.hpp | 4 +-- .../chaiscript/language/chaiscript_eval.hpp | 21 ++++++++++++++++ .../language/chaiscript_optimizer.hpp | 25 +++++++++++++++++-- 3 files changed, 46 insertions(+), 4 deletions(-) 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; } }