diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 05f0e84..1fb4240 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ 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) { @@ -246,7 +246,7 @@ 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 753389d..e4d6031 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -141,11 +141,59 @@ namespace chaiscript AST_Node_Impl_Ptr m_original_node; }; + + template + struct Fold_Right_Binary_Operator_AST_Node : AST_Node_Impl { + Fold_Right_Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector> t_children, Boxed_Value t_rhs) : + AST_Node_Impl(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), + m_oper(Operators::to_operator(t_oper)), + m_rhs(std::move(t_rhs)), + m_loc(0) + { } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + return do_oper(t_ss, this->text, this->children[0]->eval(t_ss)); + } + + protected: + Boxed_Value do_oper(const chaiscript::detail::Dispatch_State &t_ss, + const std::string &t_oper_string, const Boxed_Value &t_lhs) const + { + try { + if (t_lhs.get_type_info().is_arithmetic()) + { + // If it's an arithmetic operation we want to short circuit dispatch + try{ + return Boxed_Number::do_oper(m_oper, t_lhs, m_rhs); + } catch (const chaiscript::exception::arithmetic_error &) { + throw; + } catch (...) { + throw exception::eval_error("Error with numeric operator calling: " + t_oper_string); + } + } else { + chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); + fpp.save_params({t_lhs, m_rhs}); + return t_ss->call_function(t_oper_string, m_loc, {t_lhs, m_rhs}, t_ss.conversions()); + } + } + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, *t_ss); + } + } + + private: + Operators::Opers m_oper; + Boxed_Value m_rhs; + mutable std::atomic_uint_fast32_t m_loc; + }; + + 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)) + m_oper(Operators::to_operator(t_oper)), + m_loc(0) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index dd3bb1f..2ff4ad0 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -131,6 +131,34 @@ namespace chaiscript { } }; + struct Partial_Fold { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { + + // Fold right side + if (node->identifier == AST_Node_Type::Binary + && node->children.size() == 2 + && node->children[0]->identifier != AST_Node_Type::Constant + && node->children[1]->identifier == AST_Node_Type::Constant) + { + try { + const auto &oper = node->text; + const auto parsed = Operators::to_operator(oper); + if (parsed != Operators::Opers::invalid) { + const auto rhs = std::dynamic_pointer_cast>(node->children[1])->m_value; + if (rhs.get_type_info().is_arithmetic()) { + return chaiscript::make_shared, eval::Fold_Right_Binary_Operator_AST_Node>(node->text, node->location, node->children, rhs); + } + } + } catch (const std::exception &) { + //failure to fold, that's OK + } + } + + return node; + } + }; + struct Constant_Fold { template auto optimize(const eval::AST_Node_Impl_Ptr &node) {