diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 49a3aa7..7c59366 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -97,21 +97,6 @@ namespace chaiscript throw exception::bad_boxed_cast("&= only valid for integer types"); } - /// \brief Performs an assign difference (-=) on the given object with the given Boxed_Numeric - /// \param[in,out] p1 object to difference assign to - /// \param[in] r Boxed_Numeric to assign from - /// \returns Reference to p1, to support normal C assignment semantics - template - P1 &assign_difference_pod(P1 &p1, Boxed_Numeric r) - { - if (r.isfloat) - { - return p1 -= P1(r.d); - } else { - return p1 -= P1(r.i); - } - } - /// \brief Performs an assign shift left (<<=) on the given object with the given Boxed_Numeric /// \param[in,out] p1 object to assign shift left to /// \param[in] r Boxed_Numeric to assign from @@ -128,36 +113,6 @@ namespace chaiscript } - /// \brief Performs an assign product (*=) on the given object with the given Boxed_Numeric - /// \param[in,out] p1 object to assign product to - /// \param[in] r Boxed_Numeric to assign from - /// \returns Reference to p1, to support normal C assignment semantics - template - P1 &assign_product_pod(P1 &p1, Boxed_Numeric r) - { - if (r.isfloat) - { - return p1 *= P1(r.d); - } else { - return p1 *= P1(r.i); - } - } - - /// \brief Performs an assign quotient (/=) on the given object with the given Boxed_Numeric - /// \param[in,out] p1 object to assign quotient to - /// \param[in] r Boxed_Numeric to assign from - /// \returns Reference to p1, to support normal C assignment semantics - template - P1 &assign_quotient_pod(P1 &p1, Boxed_Numeric r) - { - if (r.isfloat) - { - return p1 /= P1(r.d); - } else { - return p1 /= P1(r.i); - } - } - /// \brief Performs an assign remainder (%=) on the given object with the given Boxed_Numeric /// \param[in,out] p1 object to assign remainder to /// \param[in] r Boxed_Numeric to assign from @@ -189,20 +144,6 @@ namespace chaiscript throw exception::bad_boxed_cast(">>= only valid for integer types"); } - /// \brief Performs an assign sum (+=) on the given object with the given Boxed_Numeric - /// \param[in,out] p1 object to sum assign to - /// \param[in] r Boxed_Numeric to assign from - /// \returns Reference to p1, to support normal C assignment semantics - template - P1 &assign_sum_pod(P1 &p1, Boxed_Numeric r) - { - if (r.isfloat) - { - return p1 += P1(r.d); - } else { - return p1 += P1(r.i); - } - } } @@ -234,27 +175,27 @@ namespace chaiscript operators::assign_bitwise_and(m); operators::assign_xor(m); operators::assign_bitwise_or(m); - operators::assign_difference(m); +// operators::assign_difference(m); operators::assign_left_shift(m); - operators::assign_product(m); - operators::assign_quotient(m); - operators::assign_remainder(m); +// operators::assign_product(m); +// operators::assign_quotient(m); +// operators::assign_remainder(m); operators::assign_right_shift(m); - operators::assign_sum(m); +// operators::assign_sum(m); - operators::prefix_decrement(m); - operators::prefix_increment(m); - operators::addition(m); +// operators::prefix_decrement(m); +// operators::prefix_increment(m); +// operators::addition(m); operators::unary_plus(m); - operators::subtraction(m); +// operators::subtraction(m); operators::unary_minus(m); operators::bitwise_and(m); operators::bitwise_compliment(m); operators::bitwise_xor(m); operators::bitwise_or(m); - operators::division(m); +// operators::division(m); operators::left_shift(m); - operators::multiplication(m); +// operators::multiplication(m); operators::remainder(m); operators::right_shift(m); return m; @@ -268,17 +209,17 @@ namespace chaiscript template ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module())) { - operators::assign_difference(m); - operators::assign_product(m); - operators::assign_quotient(m); - operators::assign_sum(m); +// operators::assign_difference(m); +// operators::assign_product(m); +// operators::assign_quotient(m); +// operators::assign_sum(m); - operators::addition(m); +// operators::addition(m); operators::unary_plus(m); - operators::subtraction(m); +// operators::subtraction(m); operators::unary_minus(m); - operators::division(m); - operators::multiplication(m); +// operators::division(m); +// operators::multiplication(m); return m; } @@ -365,10 +306,10 @@ namespace chaiscript oper_assign_pod(m); construct_pod(name, m); - m->add(fun(&detail::assign_sum_pod), "+="); - m->add(fun(&detail::assign_difference_pod), "-="); - m->add(fun(&detail::assign_product_pod), "*="); - m->add(fun(&detail::assign_quotient_pod), "/="); +// m->add(fun(&detail::assign_sum_pod), "+="); +// m->add(fun(&detail::assign_difference_pod), "-="); +// m->add(fun(&detail::assign_product_pod), "*="); +// m->add(fun(&detail::assign_quotient_pod), "/="); m->add(fun(&to_string), "to_string"); m->add(fun(&parse_string), "to_" + name); @@ -495,6 +436,12 @@ namespace chaiscript m->add(fun(&operators::multiplication), "*"); m->add(fun(&operators::remainder), "%"); m->add(fun(&operators::right_shift), ">>"); + m->add(fun(&Boxed_Numeric::operator*=), "*="); + m->add(fun(&Boxed_Numeric::operator/=), "/="); + m->add(fun(&Boxed_Numeric::operator+=), "+="); + m->add(fun(&Boxed_Numeric::operator-=), "-="); + m->add(fun(&Boxed_Numeric::operator--), "--"); + m->add(fun(&Boxed_Numeric::operator++), "++"); } /** diff --git a/include/chaiscript/dispatchkit/boxed_numeric.hpp b/include/chaiscript/dispatchkit/boxed_numeric.hpp index 3dd826a..1c40640 100644 --- a/include/chaiscript/dispatchkit/boxed_numeric.hpp +++ b/include/chaiscript/dispatchkit/boxed_numeric.hpp @@ -20,17 +20,200 @@ namespace chaiscript /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values class Boxed_Numeric { + private: + template + struct choose_const + { + typedef T& type; + }; + + template + struct choose_const + { + typedef const T& type; + }; + + template + struct lhs_type + { + typedef typename choose_const::type type; + }; + + struct equals + { + static const bool lhs_const = true; + template + static bool go(const T &t, const U &u) { return t == u; } + }; + + struct add + { + static const bool lhs_const = true; + template + static Boxed_Value go(const T &t, const U &u) { return const_var(t + u); } + }; + + struct subtract + { + static const bool lhs_const = true; + template + static Boxed_Value go(const T &t, const U &u) { return const_var(t - u); } + }; + + struct multiply + { + static const bool lhs_const = true; + template + static Boxed_Value go(const T &t, const U &u) { return const_var(t * u); } + }; + + struct divide + { + static const bool lhs_const = true; + template + static Boxed_Value go(const T &t, const U &u) { return const_var(t / u); } + }; + + struct assign_product + { + static const bool lhs_const = false; + template + static Boxed_Value go(T &t, const U &u) { return var(&(t *= u)); } + }; + + struct assign_quotient + { + static const bool lhs_const = false; + template + static Boxed_Value go(T &t, const U &u) { return var(&(t /= u)); } + }; + + struct assign_sum + { + static const bool lhs_const = false; + template + static Boxed_Value go(T &t, const U &u) { return var(&(t += u)); } + }; + + struct assign_difference + { + static const bool lhs_const = false; + template + static Boxed_Value go(T &t, const U &u) { return var(&(t -= u)); } + }; + + struct pre_increment + { + static const bool lhs_const = false; + template + static Boxed_Value go(T &t, const U) { return var(&++t); } + }; + + struct pre_decrement + { + static const bool lhs_const = false; + + template + static Boxed_Value go(boost::reference_wrapper, const U) { std::cout<< "why where?"<< std::endl; throw boost::bad_any_cast(); } + + template + static Boxed_Value go(T &t, const U) { return var(&--t); } + }; + + template + static Ret oper_lhs(L l, const Boxed_Numeric &r) + { + const Type_Info &inp_ = r.bv.get_type_info(); + + if (inp_ == typeid(double)) + { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(float)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(bool)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(char)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(int)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(unsigned int)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(long)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(unsigned long)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(boost::int8_t)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(boost::int16_t)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(boost::int32_t)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(boost::int64_t)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(boost::uint8_t)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(boost::uint16_t)) { + return O::go(l, boxed_cast(r.bv)); + } else if (inp_ == typeid(boost::uint32_t)) { + return O::go(l, boxed_cast(r.bv)); + } else { + throw boost::bad_any_cast(); + } + } + + template + static Ret oper(const Boxed_Numeric &l, const Boxed_Numeric &r) + { + const Type_Info &inp_ = l.bv.get_type_info(); + + if (inp_ == typeid(double)) + { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(float)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(bool)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(char)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(int)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(unsigned int)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(long)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(unsigned long)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(boost::int8_t)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(boost::int16_t)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(boost::int32_t)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(boost::int64_t)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(boost::uint8_t)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(boost::uint16_t)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else if (inp_ == typeid(boost::uint32_t)) { + return oper_lhs(boxed_cast::type>(l.bv), r); + } else { + throw boost::bad_any_cast(); + } + }; + + public: Boxed_Numeric(const Boxed_Value &v) - : d(0), i(0), isfloat(false) + : bv(v), d(0), i(0), isfloat(false) { - if (v.get_type_info().is_undef()) + const Type_Info &inp_ = v.get_type_info(); + + if (!inp_.is_arithmetic()) { throw boost::bad_any_cast(); } - const Type_Info &inp_ = v.get_type_info(); - if (inp_ == typeid(double)) { d = boxed_cast(v); @@ -71,7 +254,7 @@ namespace chaiscript bool operator==(const Boxed_Numeric &r) const { - return ((isfloat)?d:i) == ((r.isfloat)?r.d:r.i); + return oper(*this, r); } bool operator<(const Boxed_Numeric &r) const @@ -99,24 +282,24 @@ namespace chaiscript return ((isfloat)?d:i) != ((r.isfloat)?r.d:r.i); } + Boxed_Value operator--() const + { + return oper(*this, var(0)); + } + + Boxed_Value operator++() const + { + return oper(*this, var(0)); + } + Boxed_Value operator+(const Boxed_Numeric &r) const { - if (!isfloat && !r.isfloat) - { - return smart_size(i + r.i); - } - - return Boxed_Value(((isfloat)?d:i) + ((r.isfloat)?r.d:r.i)); + return oper(*this, r); } Boxed_Value operator-(const Boxed_Numeric &r) const { - if (!isfloat && !r.isfloat) - { - return smart_size(i - r.i); - } - - return Boxed_Value(((isfloat)?d:i) - ((r.isfloat)?r.d:r.i)); + return oper(*this, r); } Boxed_Value operator&(const Boxed_Numeric &r) const @@ -149,14 +332,26 @@ namespace chaiscript throw exception::bad_boxed_cast("| only valid for integer types"); } + Boxed_Value operator*=(const Boxed_Numeric &r) const + { + return oper(*this, r); + } + Boxed_Value operator/=(const Boxed_Numeric &r) const + { + return oper(*this, r); + } + Boxed_Value operator+=(const Boxed_Numeric &r) const + { + return oper(*this, r); + } + Boxed_Value operator-=(const Boxed_Numeric &r) const + { + return oper(*this, r); + } + Boxed_Value operator/(const Boxed_Numeric &r) const { - if (!isfloat && !r.isfloat) - { - return smart_size(i / r.i); - } - - return Boxed_Value(((isfloat)?d:i) / ((r.isfloat)?r.d:r.i)); + return oper(*this, r); } Boxed_Value operator<<(const Boxed_Numeric &r) const @@ -172,12 +367,7 @@ namespace chaiscript Boxed_Value operator*(const Boxed_Numeric &r) const { - if (!isfloat && !r.isfloat) - { - return smart_size(i * r.i); - } - - return Boxed_Value(((isfloat)?d:i) * ((r.isfloat)?r.d:r.i)); + return oper(*this, r); } @@ -213,6 +403,7 @@ namespace chaiscript } + Boxed_Value bv; double d; boost::int64_t i; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 605fbb6..acbdbad 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 @@ -36,9 +37,9 @@ namespace chaiscript { public: Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, - const std::type_info *t_ti, const std::type_info *t_bareti) + bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti) : m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), - m_is_void(t_is_void), + m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic), m_type_info(t_ti), m_bare_type_info(t_bareti), m_is_undef(false) { @@ -46,7 +47,7 @@ namespace chaiscript Type_Info() : m_is_const(false), m_is_reference(false), m_is_pointer(false), - m_is_void(false), m_type_info(0), m_bare_type_info(0), + m_is_void(false), m_is_arithmetic(false), m_type_info(0), m_bare_type_info(0), m_is_undef(true) { } @@ -54,7 +55,8 @@ namespace chaiscript Type_Info(const Type_Info &ti) : m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference), m_is_pointer(ti.m_is_pointer), - m_is_void(ti.m_is_void), m_type_info(ti.m_type_info), + m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic), + m_type_info(ti.m_type_info), m_bare_type_info(ti.m_bare_type_info), m_is_undef(ti.m_is_undef) { @@ -66,6 +68,7 @@ namespace chaiscript m_is_reference = ti.m_is_reference; m_is_pointer = ti.m_is_pointer; m_is_void = ti.m_is_void; + m_is_arithmetic = ti.m_is_arithmetic; m_type_info = ti.m_type_info; m_bare_type_info = ti.m_bare_type_info; m_is_undef = ti.m_is_undef; @@ -97,6 +100,7 @@ namespace chaiscript bool is_const() const { return m_is_const; } bool is_reference() const { return m_is_reference; } bool is_void() const { return m_is_void; } + bool is_arithmetic() const { return m_is_arithmetic; } bool is_undef() const { return m_is_undef || m_bare_type_info == 0; } bool is_pointer() const { return m_is_pointer; } @@ -125,6 +129,7 @@ namespace chaiscript bool m_is_reference; bool m_is_pointer; bool m_is_void; + bool m_is_arithmetic; const std::type_info *m_type_info; const std::type_info *m_bare_type_info; bool m_is_undef; @@ -144,6 +149,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, &typeid(T), &typeid(typename Bare_Type::type)); } @@ -158,6 +164,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, &typeid(boost::shared_ptr ), &typeid(typename Bare_Type::type)); } @@ -172,6 +179,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, &typeid(const boost::shared_ptr &), &typeid(typename Bare_Type::type)); } @@ -186,6 +194,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, &typeid(boost::reference_wrapper ), &typeid(typename Bare_Type::type)); } @@ -200,6 +209,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, &typeid(const boost::reference_wrapper &), &typeid(typename Bare_Type::type)); }