wrap up support for all built in C++ Arithmetic types

This commit is contained in:
Jason Turner 2011-05-29 13:48:17 +08:00
parent 1a225dca67
commit 4b90fbd07a
2 changed files with 364 additions and 351 deletions

View File

@ -21,130 +21,30 @@ namespace chaiscript
{
namespace detail
{
/// \brief Assigns a POD value from a Boxed_Numeric. Helps support operators between
/// disparate POD types.
/// \param[in,out] p1 object to assign to
/// \param[in] v Boxed_Numeric to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_pod(P1 &p1, const Boxed_Numeric &v)
{
if (v.isfloat)
{
return (p1 = P1(v.d));
} else {
return (p1 = P1(v.i));
}
}
/// \brief Constructs a new POD value object from a Boxed_Numeric
/// \param[in] v Boxed_Numeric to copy into the new object
/// \returns The newly created object.
template<typename P1>
P1 construct_pod(Boxed_Numeric v)
boost::shared_ptr<P1> construct_pod(Boxed_Numeric v)
{
if (v.isfloat)
{
return P1(v.d);
} else {
return P1(v.i);
}
boost::shared_ptr<P1> p(new P1());
Boxed_Value bv(p);
Boxed_Numeric nb(bv);
nb = v;
return p;
}
}
/// \brief Performs a bitwise and assignment (&=) on the given object with the given Boxed_Numeric
/// \param[in,out] p1 object to bitwise and assign to
/// \param[in] r Boxed_Numeric to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_Numeric r)
{
if (!r.isfloat)
{
return p1 &= P1(r.i);
}
throw exception::bad_boxed_cast("&= only valid for integer types");
}
/// \brief Performs a xor assignment (^=) on the given object with the given Boxed_Numeric
/// \param[in,out] p1 object to xor assign to
/// \param[in] r Boxed_Numeric to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_xor_pod(P1 &p1, Boxed_Numeric r)
{
if (!r.isfloat)
{
return p1 ^= P1(r.i);
}
throw exception::bad_boxed_cast("^= only valid for integer types");
}
/// \brief Performs a bitwise or assignment (|=) on the given object with the given Boxed_Numeric
/// \param[in,out] p1 object to bitwise or assign to
/// \param[in] r Boxed_Numeric to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_Numeric r)
{
if (!r.isfloat)
{
return p1 |= P1(r.i);
}
throw exception::bad_boxed_cast("&= only valid for integer types");
}
/// \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
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_left_shift_pod(P1 &p1, Boxed_Numeric r)
{
if (!r.isfloat)
{
return p1 <<= P1(r.i);
}
throw exception::bad_boxed_cast("<<= only valid for integer types");
}
/// \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
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_remainder_pod(P1 &p1, Boxed_Numeric r)
{
if (!r.isfloat)
{
return p1 %= P1(r.i);
}
throw exception::bad_boxed_cast("%= only valid for integer types");
}
/// \brief Performs an assign shift right (>>=) on the given object with the given Boxed_Numeric
/// \param[in,out] p1 object to assign shift right to
/// \param[in] r Boxed_Numeric to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_right_shift_pod(P1 &p1, Boxed_Numeric r)
{
if (!r.isfloat)
{
return p1 >>= P1(r.i);
}
throw exception::bad_boxed_cast(">>= only valid for integer types");
}
/// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const T &)>(), type);
return m;
}
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
@ -164,76 +64,6 @@ namespace chaiscript
}
/// \brief Add all arithmetic operators appropriate for integers for the templated type.
/// Used during bootstrap, also available to users.
/// \tparam T Type to create arithmetic operators for
/// \param[in,out] m module to add arithmetic operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
operators::assign_bitwise_and<T>(m);
operators::assign_xor<T>(m);
operators::assign_bitwise_or<T>(m);
// operators::assign_difference<T>(m);
operators::assign_left_shift<T>(m);
// operators::assign_product<T>(m);
// operators::assign_quotient<T>(m);
// operators::assign_remainder<T>(m);
operators::assign_right_shift<T>(m);
// operators::assign_sum<T>(m);
// operators::prefix_decrement<T>(m);
// operators::prefix_increment<T>(m);
// operators::addition<T>(m);
operators::unary_plus<T>(m);
// operators::subtraction<T>(m);
operators::unary_minus<T>(m);
operators::bitwise_and<T>(m);
operators::bitwise_compliment<T>(m);
operators::bitwise_xor<T>(m);
operators::bitwise_or<T>(m);
// operators::division<T>(m);
operators::left_shift<T>(m);
// operators::multiplication<T>(m);
operators::remainder<T>(m);
operators::right_shift<T>(m);
return m;
}
/// \brief Add all arithmetic operators appropriate for floating point numbers for the templated type.
/// Used during bootstrap, also available to users.
/// \tparam T Type to create arithmetic operators for
/// \param[in,out] m module to add arithmetic operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
// operators::assign_difference<T>(m);
// operators::assign_product<T>(m);
// operators::assign_quotient<T>(m);
// operators::assign_sum<T>(m);
// operators::addition<T>(m);
operators::unary_plus<T>(m);
// operators::subtraction<T>(m);
operators::unary_minus<T>(m);
// operators::division<T>(m);
// operators::multiplication<T>(m);
return m;
}
/// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const T &)>(), type);
return m;
}
/// \brief Adds default and copy constructors for the given type
/// \param[in] type The name of the type to add the constructors for.
@ -283,15 +113,6 @@ namespace chaiscript
}
/**
* Add assignment operator for T = POD.
*/
template<typename T>
ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::assign_pod<T>), "=");
return m;
}
/**
* Add all common functions for a POD type. All operators, and
@ -301,52 +122,14 @@ namespace chaiscript
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<T>(), name);
basic_constructors<T>(name, m);
operators::assign<T>(m);
oper_assign_pod<T>(m);
m->add(constructor<T ()>(), name);
construct_pod<T>(name, m);
// m->add(fun(&detail::assign_sum_pod<T>), "+=");
// m->add(fun(&detail::assign_difference_pod<T>), "-=");
// m->add(fun(&detail::assign_product_pod<T>), "*=");
// m->add(fun(&detail::assign_quotient_pod<T>), "/=");
m->add(fun(&to_string<T>), "to_string");
m->add(fun(&parse_string<T>), "to_" + name);
return m;
}
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T>
ModulePtr bootstrap_integer_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_pod_type<T>(name, m);
m->add(fun(&detail::assign_bitwise_and_pod<T>), "&=");
m->add(fun(&detail::assign_xor_pod<T>), "^=");
m->add(fun(&detail::assign_bitwise_or_pod<T>), "|=");
m->add(fun(&detail::assign_left_shift_pod<T>), "<<=");
m->add(fun(&detail::assign_remainder_pod<T>), "%=");
m->add(fun(&detail::assign_right_shift_pod<T>), ">>=");
opers_integer_arithmetic<T>(m);
return m;
}
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T>
ModulePtr bootstrap_float_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_pod_type<T>(name, m);
opers_float_arithmetic<T>(m);
return m;
}
/**
* "clone" function for a shared_ptr type. This is used in the case
@ -421,28 +204,48 @@ namespace chaiscript
std::cout << s << std::endl;
}
/**
* Add all arithmetic operators for PODs
*/
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&operators::addition<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "+");
m->add(fun(&operators::subtraction<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "-");
m->add(fun(&operators::bitwise_and<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "&");
m->add(fun(&operators::bitwise_xor<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "^");
m->add(fun(&operators::bitwise_or<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "|");
m->add(fun(&operators::division<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "/");
m->add(fun(&operators::left_shift<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "<<");
m->add(fun(&operators::multiplication<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "*");
m->add(fun(&operators::remainder<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), "%");
m->add(fun(&operators::right_shift<Boxed_Value, Boxed_Numeric, Boxed_Numeric>), ">>");
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>>=), ">>=");
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%), "%");
m->add(fun(&Boxed_Numeric::operator>>), ">>");
m->add(fun<Boxed_Value (Boxed_Numeric::*)(const Boxed_Numeric &) const>(&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--), "--");
m->add(fun(&Boxed_Numeric::operator++), "++");
}
m->add(fun(&Boxed_Numeric::operator/), "/");
m->add(fun(&Boxed_Numeric::operator*), "*");
m->add(fun<Boxed_Value (Boxed_Numeric::*)() const>(&Boxed_Numeric::operator+), "+");
m->add(fun<Boxed_Value (Boxed_Numeric::*)() const>(&Boxed_Numeric::operator-), "-");
m->add(fun<Boxed_Value (Boxed_Numeric::*)(const Boxed_Numeric &) const>(&Boxed_Numeric::operator+), "+");
m->add(fun<Boxed_Value (Boxed_Numeric::*)(const Boxed_Numeric &) const>(&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<=), "<=");
m->add(fun(&Boxed_Numeric::operator!=), "!=");
}
/**
* Create a bound function object. The first param is the function to bind
@ -633,15 +436,25 @@ namespace chaiscript
m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what");
bootstrap_float_type<double>("double", m);
bootstrap_integer_type<int>("int", m);
bootstrap_integer_type<size_t>("size_t", m);
bootstrap_integer_type<char>("char", m);
bootstrap_integer_type<boost::int64_t>("int64_t", m);
bootstrap_pod_type<double>("double", m);
bootstrap_pod_type<long double>("long_double", m);
bootstrap_pod_type<float>("float", m);
bootstrap_pod_type<int>("int", m);
bootstrap_pod_type<unsigned int>("unsigned_int", m);
bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<boost::int8_t>("int8_t", m);
bootstrap_pod_type<boost::int16_t>("int16_t", m);
bootstrap_pod_type<boost::int32_t>("int32_t", m);
bootstrap_pod_type<boost::int64_t>("int64_t", m);
bootstrap_pod_type<boost::uint8_t>("uint8_t", m);
bootstrap_pod_type<boost::uint16_t>("uint16_t", m);
bootstrap_pod_type<boost::uint32_t>("uint32_t", m);
bootstrap_pod_type<boost::uint64_t>("uint64_t", m);
operators::logical_compliment<bool>(m);
opers_comparison<Boxed_Numeric>(m);
opers_arithmetic_pod(m);

View File

@ -42,10 +42,51 @@ namespace chaiscript
struct equals
{
static const bool lhs_const = true;
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static bool go(const T &t, const U &u) { return t == u; }
};
struct less_than
{
static const bool lhs_const = true;
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static bool go(const T &t, const U &u) { return t < u; }
};
struct greater_than
{
static const bool lhs_const = true;
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static bool go(const T &t, const U &u) { return t > u; }
};
struct greater_than_equal
{
static const bool lhs_const = true;
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static bool go(const T &t, const U &u) { return t >= u; }
};
struct less_than_equal
{
static const bool lhs_const = true;
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static bool go(const T &t, const U &u) { return t <= u; }
};
struct not_equal
{
static const bool lhs_const = true;
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static bool go(const T &t, const U &u) { return t != u; }
};
struct add
{
static const bool lhs_const = true;
@ -95,6 +136,13 @@ namespace chaiscript
static Boxed_Value go(T &t, const U &u) { return var(&(t += u)); }
};
struct assign
{
static const bool lhs_const = false;
template<typename T, typename U>
static Boxed_Value go(T &t, const U &u) { return var(&(t.get() = u.get())); }
};
struct assign_difference
{
static const bool lhs_const = false;
@ -102,6 +150,49 @@ namespace chaiscript
static Boxed_Value go(T &t, const U &u) { return var(&(t -= u)); }
};
struct assign_bitwise_and
{
static const bool lhs_const = false;
template<typename T, typename U>
static Boxed_Value go(T &t, const U &u) { return var(&(t &= u)); }
};
struct assign_bitwise_or
{
static const bool lhs_const = false;
template<typename T, typename U>
static Boxed_Value go(T &t, const U &u) { return var(&(t |= u)); }
};
struct assign_bitwise_xor
{
static const bool lhs_const = false;
template<typename T, typename U>
static Boxed_Value go(T &t, const U &u) { return var(&(t ^= u)); }
};
struct assign_remainder
{
static const bool lhs_const = false;
template<typename T, typename U>
static Boxed_Value go(T &t, const U &u) { return var(&(t %= u)); }
};
struct assign_bitshift_left
{
static const bool lhs_const = false;
template<typename T, typename U>
static Boxed_Value go(T &t, const U &u) { return var(&(t <<= u)); }
};
struct assign_bitshift_right
{
static const bool lhs_const = false;
template<typename T, typename U>
static Boxed_Value go(T &t, const U &u) { return var(&(t >>= u)); }
};
struct pre_increment
{
static const bool lhs_const = false;
@ -109,6 +200,69 @@ namespace chaiscript
static Boxed_Value go(T &t, const U) { return var(&++t); }
};
struct unary_plus
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U) { return const_var(+t); }
};
struct bitwise_complement
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U) { return const_var(~t); }
};
struct unary_minus
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U) { return const_var(-t); }
};
struct bitwise_and
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U &u) { return const_var(t & u); }
};
struct bitwise_xor
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U &u) { return const_var(t ^ u); }
};
struct bitwise_or
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U &u) { return const_var(t | u); }
};
struct remainder
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U &u) { return const_var(t % u); }
};
struct left_shift
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U &u) { return const_var(t << u); }
};
struct right_shift
{
static const bool lhs_const = true;
template<typename T, typename U>
static Boxed_Value go(const T &t, const U &u) { return const_var(t >> u); }
};
struct pre_decrement
{
static const bool lhs_const = false;
@ -130,12 +284,12 @@ namespace chaiscript
return O::go(l, boxed_cast<const double &>(r.bv));
} else if (inp_ == typeid(float)) {
return O::go(l, boxed_cast<const float&>(r.bv));
} else if (inp_ == typeid(long double)) {
return O::go(l, boxed_cast<const long double&>(r.bv));
} else if (inp_ == typeid(bool)) {
return O::go(l, boxed_cast<const bool&>(r.bv));
} else if (inp_ == typeid(char)) {
return O::go(l, boxed_cast<const char&>(r.bv));
} else if (inp_ == typeid(int)) {
return O::go(l, boxed_cast<const int&>(r.bv));
} else if (inp_ == typeid(unsigned int)) {
return O::go(l, boxed_cast<const unsigned int&>(r.bv));
} else if (inp_ == typeid(long)) {
@ -156,6 +310,8 @@ namespace chaiscript
return O::go(l, boxed_cast<const boost::uint16_t &>(r.bv));
} else if (inp_ == typeid(boost::uint32_t)) {
return O::go(l, boxed_cast<const boost::uint32_t &>(r.bv));
} else if (inp_ == typeid(boost::uint64_t)) {
return O::go(l, boxed_cast<const boost::uint64_t &>(r.bv));
} else {
throw boost::bad_any_cast();
}
@ -169,6 +325,8 @@ namespace chaiscript
if (inp_ == typeid(double))
{
return oper_lhs<Ret, O>(boxed_cast<typename lhs_type<O, double>::type>(l.bv), r);
} else if (inp_ == typeid(long double)) {
return oper_lhs<Ret, O>(boxed_cast<typename lhs_type<O, long double>::type>(l.bv), r);
} else if (inp_ == typeid(float)) {
return oper_lhs<Ret, O>(boxed_cast<typename lhs_type<O, float>::type>(l.bv), r);
} else if (inp_ == typeid(bool)) {
@ -197,15 +355,91 @@ namespace chaiscript
return oper_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::uint16_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::uint32_t)) {
return oper_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::uint32_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::uint64_t)) {
return oper_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::uint64_t>::type>(l.bv), r);
} else {
throw boost::bad_any_cast();
}
}
template<typename Ret, typename O, typename L>
static Ret oper_int_lhs(L l, const Boxed_Numeric &r)
{
const Type_Info &inp_ = r.bv.get_type_info();
if (inp_ == typeid(bool)) {
return O::go(l, boxed_cast<const bool&>(r.bv));
} else if (inp_ == typeid(char)) {
return O::go(l, boxed_cast<const char&>(r.bv));
} else if (inp_ == typeid(unsigned int)) {
return O::go(l, boxed_cast<const unsigned int&>(r.bv));
} else if (inp_ == typeid(long)) {
return O::go(l, boxed_cast<const long&>(r.bv));
} else if (inp_ == typeid(unsigned long)) {
return O::go(l, boxed_cast<const unsigned long&>(r.bv));
} else if (inp_ == typeid(boost::int8_t)) {
return O::go(l, boxed_cast<const boost::int8_t &>(r.bv));
} else if (inp_ == typeid(boost::int16_t)) {
return O::go(l, boxed_cast<const boost::int16_t &>(r.bv));
} else if (inp_ == typeid(boost::int32_t)) {
return O::go(l, boxed_cast<const boost::int32_t &>(r.bv));
} else if (inp_ == typeid(boost::int64_t)) {
return O::go(l, boxed_cast<const boost::int64_t &>(r.bv));
} else if (inp_ == typeid(boost::uint8_t)) {
return O::go(l, boxed_cast<const boost::uint8_t &>(r.bv));
} else if (inp_ == typeid(boost::uint16_t)) {
return O::go(l, boxed_cast<const boost::uint16_t &>(r.bv));
} else if (inp_ == typeid(boost::uint32_t)) {
return O::go(l, boxed_cast<const boost::uint32_t &>(r.bv));
} else if (inp_ == typeid(boost::uint64_t)) {
return O::go(l, boxed_cast<const boost::uint64_t &>(r.bv));
} else {
throw boost::bad_any_cast();
}
}
template<typename Ret, typename O>
static Ret oper_int(const Boxed_Numeric &l, const Boxed_Numeric &r)
{
const Type_Info &inp_ = l.bv.get_type_info();
if (inp_ == typeid(bool)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, bool>::type>(l.bv), r);
} else if (inp_ == typeid(char)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, char>::type>(l.bv), r);
} else if (inp_ == typeid(int)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, int>::type>(l.bv), r);
} else if (inp_ == typeid(unsigned int)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, unsigned int>::type>(l.bv), r);
} else if (inp_ == typeid(long)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, long>::type>(l.bv), r);
} else if (inp_ == typeid(unsigned long)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, unsigned long>::type>(l.bv), r);
} else if (inp_ == typeid(boost::int8_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::int8_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::int16_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::int32_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::int32_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::int32_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::int64_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::int64_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::uint8_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::uint8_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::uint16_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::uint16_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::uint32_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::uint32_t>::type>(l.bv), r);
} else if (inp_ == typeid(boost::uint64_t)) {
return oper_int_lhs<Ret, O>(boxed_cast<typename lhs_type<O, boost::uint64_t>::type>(l.bv), r);
} else {
throw boost::bad_any_cast();
}
};
public:
Boxed_Numeric(const Boxed_Value &v)
: bv(v), d(0), i(0), isfloat(false)
: bv(v)
{
const Type_Info &inp_ = v.get_type_info();
@ -213,45 +447,9 @@ namespace chaiscript
{
throw boost::bad_any_cast();
}
if (inp_ == typeid(double))
{
d = boxed_cast<double>(v);
isfloat = true;
} else if (inp_ == typeid(float)) {
d = boxed_cast<float>(v);
isfloat = true;
} else if (inp_ == typeid(bool)) {
i = boxed_cast<bool>(v);
} else if (inp_ == typeid(char)) {
i = boxed_cast<char>(v);
} else if (inp_ == typeid(int)) {
i = boxed_cast<int>(v);
} else if (inp_ == typeid(unsigned int)) {
i = boxed_cast<unsigned int>(v);
} else if (inp_ == typeid(long)) {
i = boxed_cast<long>(v);
} else if (inp_ == typeid(unsigned long)) {
i = boxed_cast<unsigned long>(v);
} else if (inp_ == typeid(boost::int8_t)) {
i = boxed_cast<boost::int8_t>(v);
} else if (inp_ == typeid(boost::int16_t)) {
i = boxed_cast<boost::int16_t>(v);
} else if (inp_ == typeid(boost::int32_t)) {
i = boxed_cast<boost::int32_t>(v);
} else if (inp_ == typeid(boost::int64_t)) {
i = boxed_cast<boost::int64_t>(v);
} else if (inp_ == typeid(boost::uint8_t)) {
i = boxed_cast<boost::uint8_t>(v);
} else if (inp_ == typeid(boost::uint16_t)) {
i = boxed_cast<boost::uint16_t>(v);
} else if (inp_ == typeid(boost::uint32_t)) {
i = boxed_cast<boost::uint32_t>(v);
} else {
throw boost::bad_any_cast();
}
}
bool operator==(const Boxed_Numeric &r) const
{
return oper<bool, equals>(*this, r);
@ -259,27 +457,27 @@ namespace chaiscript
bool operator<(const Boxed_Numeric &r) const
{
return ((isfloat)?d:i) < ((r.isfloat)?r.d:r.i);
return oper<bool, less_than>(*this, r);
}
bool operator>(const Boxed_Numeric &r) const
{
return ((isfloat)?d:i) > ((r.isfloat)?r.d:r.i);
return oper<bool, greater_than>(*this, r);
}
bool operator>=(const Boxed_Numeric &r) const
{
return ((isfloat)?d:i) >= ((r.isfloat)?r.d:r.i);
return oper<bool, greater_than_equal>(*this, r);
}
bool operator<=(const Boxed_Numeric &r) const
{
return ((isfloat)?d:i) <= ((r.isfloat)?r.d:r.i);
return oper<bool, less_than_equal>(*this, r);
}
bool operator!=(const Boxed_Numeric &r) const
{
return ((isfloat)?d:i) != ((r.isfloat)?r.d:r.i);
return oper<bool, not_equal>(*this, r);
}
Boxed_Value operator--() const
@ -297,39 +495,74 @@ namespace chaiscript
return oper<Boxed_Value, add>(*this, r);
}
Boxed_Value operator+() const
{
return oper<Boxed_Value, unary_plus>(*this, Boxed_Value(0));
}
Boxed_Value operator-() const
{
return oper<Boxed_Value, unary_minus>(*this, Boxed_Value(0));
}
Boxed_Value operator-(const Boxed_Numeric &r) const
{
return oper<Boxed_Value, subtract>(*this, r);
}
Boxed_Value operator&=(const Boxed_Numeric &r) const
{
return oper_int<Boxed_Value, assign_bitwise_and>(*this, r);
}
Boxed_Value operator=(const Boxed_Numeric &r) const
{
return oper<Boxed_Value, assign>(*this, r);
}
Boxed_Value operator|=(const Boxed_Numeric &r) const
{
return oper_int<Boxed_Value, assign_bitwise_or>(*this, r);
}
Boxed_Value operator^=(const Boxed_Numeric &r) const
{
return oper_int<Boxed_Value, assign_bitwise_xor>(*this, r);
}
Boxed_Value operator%=(const Boxed_Numeric &r) const
{
return oper_int<Boxed_Value, assign_remainder>(*this, r);
}
Boxed_Value operator<<=(const Boxed_Numeric &r) const
{
return oper_int<Boxed_Value, assign_bitshift_left>(*this, r);
}
Boxed_Value operator>>=(const Boxed_Numeric &r) const
{
return oper_int<Boxed_Value, assign_bitshift_right>(*this, r);
}
Boxed_Value operator&(const Boxed_Numeric &r) const
{
if (!isfloat && !r.isfloat)
{
return Boxed_Value(i & r.i);
}
return oper_int<Boxed_Value, bitwise_and>(*this, r);
}
throw exception::bad_boxed_cast("& only valid for integer types");
Boxed_Value operator~() const
{
return oper_int<Boxed_Value, bitwise_complement>(*this, Boxed_Value(0));
}
Boxed_Value operator^(const Boxed_Numeric &r) const
{
if (!isfloat && !r.isfloat)
{
return Boxed_Value(i ^ r.i);
}
throw exception::bad_boxed_cast("^ only valid for integer types");
return oper_int<Boxed_Value, bitwise_xor>(*this, r);
}
Boxed_Value operator|(const Boxed_Numeric &r) const
{
if (!isfloat && !r.isfloat)
{
return Boxed_Value(i | r.i);
}
throw exception::bad_boxed_cast("| only valid for integer types");
return oper_int<Boxed_Value, bitwise_or>(*this, r);
}
Boxed_Value operator*=(const Boxed_Numeric &r) const
@ -356,58 +589,25 @@ namespace chaiscript
Boxed_Value operator<<(const Boxed_Numeric &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i << r.i);
}
throw exception::bad_boxed_cast("<< only valid for integer types");
return oper_int<Boxed_Value, left_shift>(*this, r);
}
Boxed_Value operator*(const Boxed_Numeric &r) const
{
return oper<Boxed_Value, multiply>(*this, r);
}
Boxed_Value operator%(const Boxed_Numeric &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i % r.i);
}
throw exception::bad_boxed_cast("% only valid for integer types");
return oper_int<Boxed_Value, remainder>(*this, r);
}
Boxed_Value operator>>(const Boxed_Numeric &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i >> r.i);
}
throw exception::bad_boxed_cast(">> only valid for integer types");
return oper_int<Boxed_Value, right_shift>(*this, r);
}
Boxed_Value smart_size(boost::int64_t t_i) const
{
if (t_i < boost::integer_traits<int>::const_min
|| t_i > boost::integer_traits<int>::const_max)
{
return Boxed_Value(t_i);
} else {
return Boxed_Value(static_cast<int>(t_i));
}
}
Boxed_Value bv;
double d;
boost::int64_t i;
bool isfloat;
};
namespace detail