From 2c4d69bfc0509623876aabe7598b06fbbadbb0ea Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 1 Jun 2011 22:12:50 -0600 Subject: [PATCH] Bypass dispatch during numeric operations. 2x speedup --- .../chaiscript/dispatchkit/boxed_numeric.hpp | 171 +++++++++--------- include/chaiscript/dispatchkit/type_info.hpp | 11 +- .../chaiscript/language/chaiscript_common.hpp | 80 +++++++- .../chaiscript/language/chaiscript_eval.hpp | 70 +++++-- .../chaiscript/language/chaiscript_parser.hpp | 2 +- 5 files changed, 229 insertions(+), 105 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_numeric.hpp b/include/chaiscript/dispatchkit/boxed_numeric.hpp index b2a37ff..1bcd46b 100644 --- a/include/chaiscript/dispatchkit/boxed_numeric.hpp +++ b/include/chaiscript/dispatchkit/boxed_numeric.hpp @@ -22,9 +22,6 @@ namespace chaiscript class Boxed_Numeric { private: - - - struct boolean { #pragma GCC diagnostic ignored "-Wsign-compare" @@ -163,19 +160,19 @@ namespace chaiscript template struct Go { - static Boxed_Value go(Operators::Opers t_oper, const Boxed_Numeric &t_lhs, const Boxed_Numeric &t_rhs) + static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return boolean::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag) { - return binary::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return binary::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { - return binary_int::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return binary_int::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - return const_binary_int::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return const_binary_int::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else if (t_oper > Operators::const_flag) { - return const_binary::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return const_binary::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else { throw boost::bad_any_cast(); } @@ -185,19 +182,19 @@ namespace chaiscript template struct Go { - static Boxed_Value go(Operators::Opers t_oper, const Boxed_Numeric &t_lhs, const Boxed_Numeric &t_rhs) + static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return boolean::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag) { - return binary::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return binary::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { throw boost::bad_any_cast(); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { throw boost::bad_any_cast(); } else if (t_oper > Operators::const_flag) { - return const_binary::go(t_oper, boxed_cast(t_lhs.bv), boxed_cast(t_rhs.bv)); + return const_binary::go(t_oper, boxed_cast(t_lhs), boxed_cast(t_rhs)); } else { throw boost::bad_any_cast(); } @@ -205,12 +202,13 @@ namespace chaiscript }; template - static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Numeric &t_lhs, const Boxed_Numeric &t_rhs) + static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { - const Type_Info &inp_ = t_rhs.bv.get_type_info(); + const Type_Info &inp_ = t_rhs.get_type_info(); - if (inp_ == typeid(double)) - { + if (inp_ == typeid(int)) { + return Go::go(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(double)) { return Go::go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(float)) { return Go::go(t_oper, t_lhs, t_rhs); @@ -245,12 +243,13 @@ namespace chaiscript } } - static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Numeric &t_lhs, const Boxed_Numeric &t_rhs) + static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { - const Type_Info &inp_ = t_lhs.bv.get_type_info(); + const Type_Info &inp_ = t_lhs.get_type_info(); - if (inp_ == typeid(double)) - { + if (inp_ == typeid(int)) { + return oper_rhs(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(double)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long double)) { return oper_rhs(t_oper, t_lhs, t_rhs); @@ -258,8 +257,6 @@ namespace chaiscript return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(char)) { return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(int)) { - return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(unsigned int)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long)) { @@ -306,161 +303,171 @@ namespace chaiscript } - bool operator==(const Boxed_Numeric &r) const + bool operator==(const Boxed_Numeric &t_rhs) const { - return boxed_cast(oper(Operators::equals, *this, r)); + return boxed_cast(oper(Operators::equals, this->bv, t_rhs.bv)); } - bool operator<(const Boxed_Numeric &r) const + bool operator<(const Boxed_Numeric &t_rhs) const { - return boxed_cast(oper(Operators::less_than, *this, r)); + return boxed_cast(oper(Operators::less_than, this->bv, t_rhs.bv)); } - bool operator>(const Boxed_Numeric &r) const + bool operator>(const Boxed_Numeric &t_rhs) const { - return boxed_cast(oper(Operators::greater_than, *this, r)); + return boxed_cast(oper(Operators::greater_than, this->bv, t_rhs.bv)); } - bool operator>=(const Boxed_Numeric &r) const + bool operator>=(const Boxed_Numeric &t_rhs) const { - return boxed_cast(oper(Operators::greater_than_equal, *this, r)); + return boxed_cast(oper(Operators::greater_than_equal, this->bv, t_rhs.bv)); } - bool operator<=(const Boxed_Numeric &r) const + bool operator<=(const Boxed_Numeric &t_rhs) const { - return boxed_cast(oper(Operators::less_than_equal, *this, r)); + return boxed_cast(oper(Operators::less_than_equal, this->bv, t_rhs.bv)); } - bool operator!=(const Boxed_Numeric &r) const + bool operator!=(const Boxed_Numeric &t_rhs) const { - return boxed_cast(oper(Operators::not_equal, *this, r)); + return boxed_cast(oper(Operators::not_equal, this->bv, t_rhs.bv)); } Boxed_Value operator--() const { - return oper(Operators::pre_decrement, *this, var(0)); + return oper(Operators::pre_decrement, this->bv, var(0)); } Boxed_Value operator++() const { - return oper(Operators::pre_increment, *this, var(0)); + return oper(Operators::pre_increment, this->bv, var(0)); } - Boxed_Value operator+(const Boxed_Numeric &r) const + Boxed_Value operator+(const Boxed_Numeric &t_rhs) const { - return oper(Operators::sum, *this, r); + return oper(Operators::sum, this->bv, t_rhs.bv); } Boxed_Value operator+() const { - return oper(Operators::unary_plus, *this, Boxed_Value(0)); + return oper(Operators::unary_plus, this->bv, Boxed_Value(0)); } Boxed_Value operator-() const { - return oper(Operators::unary_minus, *this, Boxed_Value(0)); + return oper(Operators::unary_minus, this->bv, Boxed_Value(0)); } - Boxed_Value operator-(const Boxed_Numeric &r) const + Boxed_Value operator-(const Boxed_Numeric &t_rhs) const { - return oper(Operators::difference, *this, r); + return oper(Operators::difference, this->bv, t_rhs.bv); } - Boxed_Value operator&=(const Boxed_Numeric &r) const + Boxed_Value operator&=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_bitwise_and, *this, r); + return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv); } - Boxed_Value operator=(const Boxed_Numeric &r) const + Boxed_Value operator=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign, *this, r); + return oper(Operators::assign, this->bv, t_rhs.bv); } - Boxed_Value operator|=(const Boxed_Numeric &r) const + Boxed_Value operator|=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_bitwise_or, *this, r); + return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv); } - Boxed_Value operator^=(const Boxed_Numeric &r) const + Boxed_Value operator^=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_bitwise_xor, *this, r); + return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv); } - Boxed_Value operator%=(const Boxed_Numeric &r) const + Boxed_Value operator%=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_remainder, *this, r); + return oper(Operators::assign_remainder, this->bv, t_rhs.bv); } - Boxed_Value operator<<=(const Boxed_Numeric &r) const + Boxed_Value operator<<=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_shift_left, *this, r); + return oper(Operators::assign_shift_left, this->bv, t_rhs.bv); } - Boxed_Value operator>>=(const Boxed_Numeric &r) const + Boxed_Value operator>>=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_shift_right, *this, r); + return oper(Operators::assign_shift_right, this->bv, t_rhs.bv); } - Boxed_Value operator&(const Boxed_Numeric &r) const + Boxed_Value operator&(const Boxed_Numeric &t_rhs) const { - return oper(Operators::bitwise_and, *this, r); + return oper(Operators::bitwise_and, this->bv, t_rhs.bv); } Boxed_Value operator~() const { - return oper(Operators::bitwise_complement, *this, Boxed_Value(0)); + return oper(Operators::bitwise_complement, this->bv, Boxed_Value(0)); } - Boxed_Value operator^(const Boxed_Numeric &r) const + Boxed_Value operator^(const Boxed_Numeric &t_rhs) const { - return oper(Operators::bitwise_xor, *this, r); + return oper(Operators::bitwise_xor, this->bv, t_rhs.bv); } - Boxed_Value operator|(const Boxed_Numeric &r) const + Boxed_Value operator|(const Boxed_Numeric &t_rhs) const { - return oper(Operators::bitwise_or, *this, r); + return oper(Operators::bitwise_or, this->bv, t_rhs.bv); } - Boxed_Value operator*=(const Boxed_Numeric &r) const + Boxed_Value operator*=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_product, *this, r); + return oper(Operators::assign_product, this->bv, t_rhs.bv); } - Boxed_Value operator/=(const Boxed_Numeric &r) const + Boxed_Value operator/=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_quotient, *this, r); + return oper(Operators::assign_quotient, this->bv, t_rhs.bv); } - Boxed_Value operator+=(const Boxed_Numeric &r) const + Boxed_Value operator+=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_sum, *this, r); + return oper(Operators::assign_sum, this->bv, t_rhs.bv); } - Boxed_Value operator-=(const Boxed_Numeric &r) const + Boxed_Value operator-=(const Boxed_Numeric &t_rhs) const { - return oper(Operators::assign_difference, *this, r); + return oper(Operators::assign_difference, this->bv, t_rhs.bv); } - Boxed_Value operator/(const Boxed_Numeric &r) const + Boxed_Value operator/(const Boxed_Numeric &t_rhs) const { - return oper(Operators::quotient, *this, r); + return oper(Operators::quotient, this->bv, t_rhs.bv); } - Boxed_Value operator<<(const Boxed_Numeric &r) const + Boxed_Value operator<<(const Boxed_Numeric &t_rhs) const { - return oper(Operators::shift_left, *this, r); + return oper(Operators::shift_left, this->bv, t_rhs.bv); } - Boxed_Value operator*(const Boxed_Numeric &r) const + Boxed_Value operator*(const Boxed_Numeric &t_rhs) const { - return oper(Operators::product, *this, r); + return oper(Operators::product, this->bv, t_rhs.bv); } - Boxed_Value operator%(const Boxed_Numeric &r) const + Boxed_Value operator%(const Boxed_Numeric &t_rhs) const { - return oper(Operators::remainder, *this, r); + return oper(Operators::remainder, this->bv, t_rhs.bv); } - Boxed_Value operator>>(const Boxed_Numeric &r) const + Boxed_Value operator>>(const Boxed_Numeric &t_rhs) const { - return oper(Operators::shift_right, *this, r); + return oper(Operators::shift_right, this->bv, t_rhs.bv); + } + + static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + { + return oper(t_oper, t_lhs, t_rhs); + } + + static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) + { + return oper(t_oper, t_lhs, const_var(0)); } Boxed_Value bv; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index acbdbad..8bd0b9a 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -149,7 +150,7 @@ namespace chaiscript { return Type_Info(boost::is_const::type>::type>::value, boost::is_reference::value, boost::is_pointer::value, boost::is_void::value, - boost::is_arithmetic::value, + boost::is_arithmetic::value && !boost::is_same::type, bool>::value, &typeid(T), &typeid(typename Bare_Type::type)); } @@ -164,7 +165,7 @@ namespace chaiscript { return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, boost::is_void::value, - boost::is_arithmetic::value, + boost::is_arithmetic::value && !boost::is_same::type, bool>::value, &typeid(boost::shared_ptr ), &typeid(typename Bare_Type::type)); } @@ -179,7 +180,7 @@ namespace chaiscript { return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, boost::is_void::value, - boost::is_arithmetic::value, + boost::is_arithmetic::value && !boost::is_same::type, bool>::value, &typeid(const boost::shared_ptr &), &typeid(typename Bare_Type::type)); } @@ -194,7 +195,7 @@ namespace chaiscript { return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, boost::is_void::value, - boost::is_arithmetic::value, + boost::is_arithmetic::value && !boost::is_same::type, bool>::value, &typeid(boost::reference_wrapper ), &typeid(typename Bare_Type::type)); } @@ -209,7 +210,7 @@ namespace chaiscript { return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, boost::is_void::value, - boost::is_arithmetic::value, + boost::is_arithmetic::value && !boost::is_same::type, bool>::value, &typeid(const boost::reference_wrapper &), &typeid(typename Bare_Type::type)); } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 2f5bb17..79e24d6 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -29,7 +29,8 @@ namespace chaiscript const_int_flag, shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement, const_flag, - sum, quotient, product, difference, unary_plus, unary_minus + sum, quotient, product, difference, unary_plus, unary_minus, + invalid }; static const char *to_string(Opers t_oper) { @@ -45,11 +46,86 @@ namespace chaiscript "", "<<", ">>", "%", "&", "|", "^", "~", "", - "+", "/", "*", "-", "+", "-" + "+", "/", "*", "-", "+", "-", + "" }; return opers[t_oper]; } + static Opers to_operator(const std::string &t_str, bool t_is_unary = false) + { + if (t_str == "==") + { + return equals; + } else if (t_str == "<") { + return less_than; + } else if (t_str == ">") { + return greater_than; + } else if (t_str == "<=") { + return less_than_equal; + } else if (t_str == ">=") { + return greater_than_equal; + } else if (t_str == "!=") { + return not_equal; + } else if (t_str == "=") { + return assign; + } else if (t_str == "++") { + return pre_increment; + } else if (t_str == "--") { + return pre_decrement; + } else if (t_str == "*=") { + return assign_product; + } else if (t_str == "+=") { + return assign_sum; + } else if (t_str == "-=") { + return assign_difference; + } else if (t_str == "&=") { + return assign_bitwise_and; + } else if (t_str == "|=") { + return assign_bitwise_or; + } else if (t_str == "<<=") { + return assign_shift_left; + } else if (t_str == ">>=") { + return assign_shift_right; + } else if (t_str == "%=") { + return assign_remainder; + } else if (t_str == "^=") { + return assign_bitwise_xor; + } else if (t_str == "<<") { + return shift_left; + } else if (t_str == ">>") { + return shift_right; + } else if (t_str == "%") { + return remainder; + } else if (t_str == "&") { + return bitwise_and; + } else if (t_str == "|") { + return bitwise_or; + } else if (t_str == "^") { + return bitwise_xor; + } else if (t_str == "~") { + return bitwise_complement; + } else if (t_str == "+") { + if (t_is_unary) { + return unary_plus; + } else { + return sum; + } + } else if (t_str == "-") { + if (t_is_unary) { + return unary_minus; + } else { + return difference; + } + } else if (t_str == "/") { + return quotient; + } else if (t_str == "*") { + return product; + } else { + return invalid; + } + } + }; /// Types of AST nodes available to the parser and eval diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 5e59d7f..0b1a0fb 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -39,22 +39,36 @@ namespace chaiscript struct Binary_Operator_AST_Node : public AST_Node { public: Binary_Operator_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Bitwise_Xor, 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) + { } + virtual ~Binary_Operator_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ - Boxed_Value retval; - - retval = this->children[0]->eval(t_ss); + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) { + Boxed_Value retval = this->children[0]->eval(t_ss); + // Else loop through all children collecting the retval for (size_t i = 1; i < this->children.size(); i += 2) { + Boxed_Value rhs(this->children[i+1]->eval(t_ss)); + Operators::Opers oper = Operators::to_operator(children[i]->text); + try { - retval = t_ss.call_function(this->children[i]->text, retval, this->children[i+1]->eval(t_ss)); + if (oper != Operators::invalid && retval.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) + { + // If it's an arithmetic operation we want to short circuit dispatch + try{ + retval = Boxed_Numeric::do_oper(oper, retval, rhs); + } catch (...) { + throw exception::eval_error("Error with numeric operator calling: " + children[i]->text); + } + + } else { + retval = t_ss.call_function(this->children[1]->text, retval, rhs); + } } catch(const exception::dispatch_error &){ throw exception::eval_error("Can not find appropriate '" + this->children[i]->text + "'"); } } - return retval; } @@ -258,16 +272,28 @@ namespace chaiscript struct Equation_AST_Node : public AST_Node { public: Equation_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Equation, 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) + {} + virtual ~Equation_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) { Boxed_Value retval = this->children.back()->eval(t_ss); + if (this->children.size() > 1) { for (int i = static_cast(this->children.size())-3; i >= 0; i -= 2) { - if (this->children[i+1]->text == "=") { - Boxed_Value lhs = this->children[i]->eval(t_ss); + Boxed_Value lhs = this->children[i]->eval(t_ss); + Operators::Opers oper = Operators::to_operator(this->children[i+1]->text); + + if (oper != Operators::invalid && lhs.get_type_info().is_arithmetic() && retval.get_type_info().is_arithmetic()) + { + try { + retval = Boxed_Numeric::do_oper(oper, lhs, retval); + } catch (const std::exception &) { + throw exception::eval_error("Error with unsupported arithmetic assignment operation"); + } + } else if (this->children[i+1]->text == "=") { try { if (lhs.is_undef()) { retval = t_ss.call_function("clone", retval); @@ -286,7 +312,6 @@ namespace chaiscript } } else if (this->children[i+1]->text == ":=") { - Boxed_Value lhs = this->children[i]->eval(t_ss); if (lhs.is_undef() || type_match(lhs, retval)) { lhs.assign(retval); } else { @@ -295,7 +320,7 @@ namespace chaiscript } else { try { - retval = t_ss.call_function(this->children[i+1]->text, this->children[i]->eval(t_ss), retval); + retval = t_ss.call_function(this->children[i+1]->text, lhs, retval); } catch(const exception::dispatch_error &){ throw exception::eval_error("Can not find appropriate '" + this->children[i+1]->text + "'"); } @@ -304,6 +329,7 @@ namespace chaiscript } return retval; } + }; struct Var_Decl_AST_Node : public AST_Node { @@ -782,10 +808,24 @@ namespace chaiscript struct Prefix_AST_Node : public AST_Node { public: Prefix_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Prefix, 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) + { } + virtual ~Prefix_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ - return t_ss.call_function(this->children[0]->text, this->children[1]->eval(t_ss)); + Boxed_Value bv(this->children[1]->eval(t_ss)); + + Operators::Opers oper = Operators::to_operator(children[0]->text, true); + try { + if (bv.get_type_info().is_arithmetic() && oper != Operators::invalid) + { + return Boxed_Numeric::do_oper(oper, bv); + } else { + return t_ss.call_function(this->children[0]->text, bv); + } + } catch (const exception::dispatch_error &) { + throw exception::eval_error("Error with prefix operator evaluation: " + children[0]->text); + } } }; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 035e3ec..bafd4d8 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -249,7 +249,7 @@ namespace chaiscript m_match_stack.push_back(t_t); } else { - //todo: fix the fact that a successful match that captured no ast_nodes doesn't have any real start position + /// \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(t_t); } }