// This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com // This is an open source non-commercial project. Dear PVS-Studio, please check it. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ #define CHAISCRIPT_BOXED_NUMERIC_HPP_ #include #include #include #include "../language/chaiscript_algebraic.hpp" #include "any.hpp" #include "boxed_cast.hpp" #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" #include "type_info.hpp" namespace chaiscript { class Type_Conversions; } // namespace chaiscript namespace chaiscript { namespace exception { struct arithmetic_error : std::runtime_error { explicit arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {} arithmetic_error(const arithmetic_error &) = default; ~arithmetic_error() noexcept override = default; }; } } namespace chaiscript { // Due to the nature of generating every possible arithmetic operation, there // are going to be warnings generated on every platform regarding size and sign, // this is OK, so we're disabling size/and sign type warnings #ifdef CHAISCRIPT_MSVC #pragma warning(push) #pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242) #endif #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wfloat-equal" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wfloat-conversion" #endif /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values class Boxed_Number { private: enum class Common_Types { t_int32, t_double, t_uint8, t_int8, t_uint16, t_int16, t_uint32, t_uint64, t_int64, t_float, t_long_double }; template static inline void check_divide_by_zero(T t, typename std::enable_if::value>::type* = nullptr) { #ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO if (t == 0) { throw chaiscript::exception::arithmetic_error("divide by zero"); } #endif } template static inline void check_divide_by_zero(T, typename std::enable_if::value>::type* = nullptr) { } static constexpr Common_Types get_common_type(size_t t_size, bool t_signed) { return (t_size == 1 && t_signed)?(Common_Types::t_int8) :(t_size == 1)?(Common_Types::t_uint8) :(t_size == 2 && t_signed)?(Common_Types::t_int16) :(t_size == 2)?(Common_Types::t_uint16) :(t_size == 4 && t_signed)?(Common_Types::t_int32) :(t_size == 4)?(Common_Types::t_uint32) :(t_size == 8 && t_signed)?(Common_Types::t_int64) :(Common_Types::t_uint64); } static Common_Types get_common_type(const Boxed_Value &t_bv) { const Type_Info &inp_ = t_bv.get_type_info(); if (inp_ == typeid(int)) { return get_common_type(sizeof(int), true); } else if (inp_ == typeid(double)) { return Common_Types::t_double; } else if (inp_ == typeid(long double)) { return Common_Types::t_long_double; } else if (inp_ == typeid(float)) { return Common_Types::t_float; } else if (inp_ == typeid(char)) { return get_common_type(sizeof(char), std::is_signed::value); } else if (inp_ == typeid(unsigned char)) { return get_common_type(sizeof(unsigned char), false); } else if (inp_ == typeid(unsigned int)) { return get_common_type(sizeof(unsigned int), false); } else if (inp_ == typeid(long)) { return get_common_type(sizeof(long), true); } else if (inp_ == typeid(long long)) { return get_common_type(sizeof(long long), true); } else if (inp_ == typeid(unsigned long)) { return get_common_type(sizeof(unsigned long), false); } else if (inp_ == typeid(unsigned long long)) { return get_common_type(sizeof(unsigned long long), false); } else if (inp_ == typeid(std::int8_t)) { return Common_Types::t_int8; } else if (inp_ == typeid(std::int16_t)) { return Common_Types::t_int16; } else if (inp_ == typeid(std::int32_t)) { return Common_Types::t_int32; } else if (inp_ == typeid(std::int64_t)) { return Common_Types::t_int64; } else if (inp_ == typeid(std::uint8_t)) { return Common_Types::t_uint8; } else if (inp_ == typeid(std::uint16_t)) { return Common_Types::t_uint16; } else if (inp_ == typeid(std::uint32_t)) { return Common_Types::t_uint32; } else if (inp_ == typeid(std::uint64_t)) { return Common_Types::t_uint64; } else if (inp_ == typeid(wchar_t)) { return get_common_type(sizeof(wchar_t), std::is_signed::value); } else if (inp_ == typeid(char16_t)) { return get_common_type(sizeof(char16_t), std::is_signed::value); } else if (inp_ == typeid(char32_t)) { return get_common_type(sizeof(char32_t), std::is_signed::value); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { case Operators::Opers::equals: return const_var(t == u); case Operators::Opers::less_than: return const_var(t < u); case Operators::Opers::greater_than: return const_var(t > u); case Operators::Opers::less_than_equal: return const_var(t <= u); case Operators::Opers::greater_than_equal: return const_var(t >= u); case Operators::Opers::not_equal: return const_var(t != u); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value unary_go(Operators::Opers t_oper, T &t, const Boxed_Value &t_lhs) { switch (t_oper) { case Operators::Opers::pre_increment: ++t; break; case Operators::Opers::pre_decrement: --t; break; default: throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; } template static Boxed_Value binary_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) { switch (t_oper) { case Operators::Opers::assign: t = u; break; case Operators::Opers::assign_product: t *= u; break; case Operators::Opers::assign_sum: t += u; break; case Operators::Opers::assign_quotient: check_divide_by_zero(u); t /= u; break; case Operators::Opers::assign_difference: t -= u; break; default: throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; } template static Boxed_Value binary_int_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) { switch (t_oper) { case Operators::Opers::assign_bitwise_and: t &= u; break; case Operators::Opers::assign_bitwise_or: t |= u; break; case Operators::Opers::assign_shift_left: t <<= u; break; case Operators::Opers::assign_shift_right: t >>= u; break; case Operators::Opers::assign_remainder: check_divide_by_zero(u); t %= u; break; case Operators::Opers::assign_bitwise_xor: t ^= u; break; default: throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; } template static Boxed_Value const_unary_int_go(Operators::Opers t_oper, const T &t) { switch (t_oper) { case Operators::Opers::bitwise_complement: return const_var(~t); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { case Operators::Opers::shift_left: return const_var(t << u); case Operators::Opers::shift_right: return const_var(t >> u); case Operators::Opers::remainder: check_divide_by_zero(u); return const_var(t % u); case Operators::Opers::bitwise_and: return const_var(t & u); case Operators::Opers::bitwise_or: return const_var(t | u); case Operators::Opers::bitwise_xor: return const_var(t ^ u); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value const_unary_go(Operators::Opers t_oper, const T &t) { switch (t_oper) { case Operators::Opers::unary_minus: return const_var(-t); case Operators::Opers::unary_plus: return const_var(+t); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value const_binary_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { case Operators::Opers::sum: return const_var(t + u); case Operators::Opers::quotient: check_divide_by_zero(u); return const_var(t / u); case Operators::Opers::product: return const_var(t * u); case Operators::Opers::difference: return const_var(t - u); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) -> typename std::enable_if::value && !std::is_floating_point::value, Boxed_Value>::type { typedef typename std::common_type::type common_type; if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag) { return boolean_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::Opers::non_const_int_flag && t_oper < Operators::Opers::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_int_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) { return const_binary_int_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::Opers::const_flag) { return const_binary_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) -> typename std::enable_if::value || std::is_floating_point::value, Boxed_Value>::type { typedef typename std::common_type::type common_type; if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag) { return boolean_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::Opers::const_flag) { return const_binary_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } } // Unary template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs) -> typename std::enable_if::value, Boxed_Value>::type { if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return unary_go(t_oper, *static_cast(t_lhs.get_ptr()), t_lhs); } else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) { return const_unary_int_go(t_oper, *static_cast(t_lhs.get_const_ptr())); } else if (t_oper > Operators::Opers::const_flag) { return const_unary_go(t_oper, *static_cast(t_lhs.get_const_ptr())); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs) -> typename std::enable_if::value, Boxed_Value>::type { if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return unary_go(t_oper, *static_cast(t_lhs.get_ptr()), t_lhs); } else if (t_oper > Operators::Opers::const_flag) { return const_unary_go(t_oper, *static_cast(t_lhs.get_const_ptr())); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template inline static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { switch (get_common_type(t_rhs)) { case Common_Types::t_int32: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint8: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_int8: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint16: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_int16: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint32: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint64: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_int64: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_double: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_float: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_long_double: return go(t_oper, t_lhs, t_rhs); } throw chaiscript::detail::exception::bad_any_cast(); } inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) { switch (get_common_type(t_lhs)) { case Common_Types::t_int32: return go(t_oper, t_lhs); case Common_Types::t_uint8: return go(t_oper, t_lhs); case Common_Types::t_int8: return go(t_oper, t_lhs); case Common_Types::t_uint16: return go(t_oper, t_lhs); case Common_Types::t_int16: return go(t_oper, t_lhs); case Common_Types::t_uint32: return go(t_oper, t_lhs); case Common_Types::t_uint64: return go(t_oper, t_lhs); case Common_Types::t_int64: return go(t_oper, t_lhs); case Common_Types::t_double: return go(t_oper, t_lhs); case Common_Types::t_float: return go(t_oper, t_lhs); case Common_Types::t_long_double: return go(t_oper, t_lhs); } throw chaiscript::detail::exception::bad_any_cast(); } inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { switch (get_common_type(t_lhs)) { case Common_Types::t_int32: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint8: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_int8: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint16: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_int16: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint32: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint64: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_int64: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_double: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_float: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_long_double: return oper_rhs(t_oper, t_lhs, t_rhs); } throw chaiscript::detail::exception::bad_any_cast(); } template static inline Target get_as_aux(const Boxed_Value &t_bv) { return static_cast(*static_cast(t_bv.get_const_ptr())); } template static std::string to_string_aux(const Boxed_Value &v) { std::ostringstream oss; oss << *static_cast(v.get_const_ptr()); return oss.str(); } public: Boxed_Number() : bv(Boxed_Value(0)) { } explicit Boxed_Number(Boxed_Value v) : bv(std::move(v)) { validate_boxed_number(bv); } Boxed_Number(const Boxed_Number &) = default; Boxed_Number(Boxed_Number &&) = default; Boxed_Number& operator=(Boxed_Number &&) = default; template explicit Boxed_Number(T t) : bv(Boxed_Value(t)) { validate_boxed_number(bv); } static bool is_floating_point(const Boxed_Value &t_bv) { const Type_Info &inp_ = t_bv.get_type_info(); if (inp_ == typeid(double)) { return true; } else if (inp_ == typeid(long double)) { return true; } else if (inp_ == typeid(float)) { return true; } else { return false; } } Boxed_Number get_as(const Type_Info &inp_) const { if (inp_.bare_equal_type_info(typeid(int))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(double))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(float))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(long double))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned char))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(wchar_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char16_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char32_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned int))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(long long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned long long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int8_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int16_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int32_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int64_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint8_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint16_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint32_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint64_t))) { return Boxed_Number(get_as()); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template static void check_type() { #ifdef CHAISCRIPT_MSVC // MSVC complains about this being redundant / tautologica l #pragma warning(push) #pragma warning(disable : 4127 6287) #endif if (sizeof(Source) != sizeof(Target) || std::is_signed() != std::is_signed() || std::is_floating_point() != std::is_floating_point()) { throw chaiscript::detail::exception::bad_any_cast(); } #ifdef CHAISCRIPT_MSVC #pragma warning(pop) #endif } template Target get_as_checked() const { switch (get_common_type(bv)) { case Common_Types::t_int32: check_type(); return get_as_aux(bv); case Common_Types::t_uint8: check_type(); return get_as_aux(bv); case Common_Types::t_int8: check_type(); return get_as_aux(bv); case Common_Types::t_uint16: check_type(); return get_as_aux(bv); case Common_Types::t_int16: check_type(); return get_as_aux(bv); case Common_Types::t_uint32: check_type(); return get_as_aux(bv); case Common_Types::t_uint64: check_type(); return get_as_aux(bv); case Common_Types::t_int64: check_type(); return get_as_aux(bv); case Common_Types::t_double: check_type(); return get_as_aux(bv); case Common_Types::t_float: check_type(); return get_as_aux(bv); case Common_Types::t_long_double: check_type(); return get_as_aux(bv); } throw chaiscript::detail::exception::bad_any_cast(); } template Target get_as() const { switch (get_common_type(bv)) { case Common_Types::t_int32: return get_as_aux(bv); case Common_Types::t_uint8: return get_as_aux(bv); case Common_Types::t_int8: return get_as_aux(bv); case Common_Types::t_uint16: return get_as_aux(bv); case Common_Types::t_int16: return get_as_aux(bv); case Common_Types::t_uint32: return get_as_aux(bv); case Common_Types::t_uint64: return get_as_aux(bv); case Common_Types::t_int64: return get_as_aux(bv); case Common_Types::t_double: return get_as_aux(bv); case Common_Types::t_float: return get_as_aux(bv); case Common_Types::t_long_double: return get_as_aux(bv); } throw chaiscript::detail::exception::bad_any_cast(); } std::string to_string() const { switch (get_common_type(bv)) { case Common_Types::t_int32: return std::to_string(get_as()); case Common_Types::t_uint8: return std::to_string(get_as()); case Common_Types::t_int8: return std::to_string(get_as()); case Common_Types::t_uint16: return std::to_string(get_as()); case Common_Types::t_int16: return std::to_string(get_as()); case Common_Types::t_uint32: return std::to_string(get_as()); case Common_Types::t_uint64: return std::to_string(get_as()); case Common_Types::t_int64: return std::to_string(get_as()); case Common_Types::t_double: return to_string_aux(bv); case Common_Types::t_float: return to_string_aux(bv); case Common_Types::t_long_double: return to_string_aux(bv); } throw chaiscript::detail::exception::bad_any_cast(); } static void validate_boxed_number(const Boxed_Value &v) { const Type_Info &inp_ = v.get_type_info(); if (inp_ == typeid(bool)) { throw chaiscript::detail::exception::bad_any_cast(); } if (!inp_.is_arithmetic()) { throw chaiscript::detail::exception::bad_any_cast(); } } static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv)); } static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv)); } static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv)); } static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv)); } static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv)); } static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv)); } static Boxed_Number pre_decrement(Boxed_Number t_lhs) { return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv)); } static Boxed_Number pre_increment(Boxed_Number t_lhs) { return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv)); } static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number unary_plus(const Boxed_Number &t_lhs) { return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv)); } static const Boxed_Number unary_minus(const Boxed_Number &t_lhs) { return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv)); } static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs) { return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0))); } static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv)); } static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.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); } Boxed_Value bv; }; namespace detail { /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper { static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *) { return Boxed_Number(ob); } }; /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper : Cast_Helper { }; /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper : Cast_Helper { }; } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif #ifdef CHAISCRIPT_MSVC #pragma warning(pop) #endif } #endif