diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 9205a83..8ce0c44 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -10,6 +10,7 @@ #include "dispatchkit.hpp" #include "dynamic_object.hpp" #include "register_function.hpp" +#include "operators.hpp" namespace chaiscript { @@ -17,141 +18,6 @@ namespace chaiscript { namespace detail { - /** - * Set of helper functions for common operators - */ - template - Ret add(P1 p1, P2 p2) - { - return p1 + p2; - } - - template - Ret subtract(P1 p1, P2 p2) - { - return p1 - p2; - } - - template - Ret divide(P1 p1, P2 p2) - { - return p1 / p2; - } - - template - Ret multiply(P1 p1, P2 p2) - { - return p1 * p2; - } - - template - Ret modulus(P1 p1, P2 p2) - { - return p1 % p2; - } - - template - Ret shift_left(P1 p1, P2 p2) - { - return p1 << p2; - } - - template - Ret shift_right(P1 p1, P2 p2) - { - return p1 >> p2; - } - - template - P1 &assign(P1 &p1, const P2 &p2) - { - return (p1 = p2); - } - - template - bool equals(P1 p1, P2 p2) - { - return p1 == p2; - } - - template - bool not_equals(P1 p1, P2 p2) - { - return p1 != p2; - } - - - template - bool less_than(P1 p1, P2 p2) - { - return p1 < p2; - } - - template - bool greater_than(P1 p1, P2 p2) - { - return p1 > p2; - } - - template - bool less_than_equals(P1 p1, P2 p2) - { - return p1 <= p2; - } - - template - bool greater_than_equals(P1 p1, P2 p2) - { - return p1 >= p2; - } - - template - P1 ×equal(P1 &p1, const P2 &p2) - { - return (p1 *= p2); - } - - template - P1 ÷sequal(P1 &p1, const P2 &p2) - { - return (p1 /= p2); - } - - template - P1 &addsequal(P1 &p1, const P2 &p2) - { - return (p1 += p2); - } - - template - P1 &subtractsequal(P1 &p1, const P2 &p2) - { - return (p1 -= p2); - } - - template - P1 &prefixincrement(P1 &p1) - { - return (++p1); - } - - template - P1 &prefixdecrement(P1 &p1) - { - return (--p1); - } - - template - P1 &prefixnegate(P1 &p1) - { - return (p1); - } - - template - P1 &prefixnot(P1 &p1) - { - return (p1); - } /* Special helpers for generating generic "POD" type operators * The POD operators are needed for general support of C++ POD @@ -162,6 +28,7 @@ namespace chaiscript template P1 &assign_pod(P1 &p1, Boxed_POD_Value v) { + if (v.m_isfloat) { return (p1 = P1(v.d)); @@ -182,7 +49,63 @@ namespace chaiscript } template - P1 ×equal_pod(P1 &p1, Boxed_POD_Value r) + P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r) + { + if (!r.m_isfloat) + { + return p1 &= P1(r.i); + } + + throw bad_boxed_cast("&= only valid for integer types"); + } + + template + P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r) + { + if (!r.m_isfloat) + { + return p1 ^= P1(r.i); + } + + throw bad_boxed_cast("^= only valid for integer types"); + } + + template + P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r) + { + if (!r.m_isfloat) + { + return p1 |= P1(r.i); + } + + throw bad_boxed_cast("&= only valid for integer types"); + } + + template + P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r) + { + if (r.m_isfloat) + { + return p1 -= P1(r.d); + } else { + return p1 -= P1(r.i); + } + } + + template + P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r) + { + if (!r.m_isfloat) + { + return p1 <<= P1(r.i); + } + + throw bad_boxed_cast("<<= only valid for integer types"); + } + + + template + P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r) { if (r.m_isfloat) { @@ -193,7 +116,7 @@ namespace chaiscript } template - P1 ÷sequal_pod(P1 &p1, Boxed_POD_Value r) + P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r) { if (r.m_isfloat) { @@ -204,7 +127,31 @@ namespace chaiscript } template - P1 &addsequal_pod(P1 &p1, Boxed_POD_Value r) + P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r) + { + if (!r.m_isfloat) + { + return p1 %= P1(r.i); + } + + throw bad_boxed_cast("%= only valid for integer types"); + } + + + template + P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r) + { + if (!r.m_isfloat) + { + return p1 >>= P1(r.i); + } + + throw bad_boxed_cast(">>= only valid for integer types"); + } + + + template + P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r) { if (r.m_isfloat) { @@ -214,223 +161,66 @@ namespace chaiscript } } - template - P1 &subtractsequal_pod(P1 &p1, Boxed_POD_Value r) - { - if (r.m_isfloat) - { - return p1 -= P1(r.d); - } else { - return p1 -= P1(r.i); - } - } } - /** - * Add canonical form of "=" for type T - */ - template - ModulePtr oper_equals(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::equals), "="); - return m; - } - - /** - * Add canonical form of "+" for type T - */ - template - ModulePtr oper_add(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::add), "+"); - return m; - } - - /** - * Add canonical form of "+=" for type T - */ - template - ModulePtr oper_add_equals(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::addsequal), "+="); - return m; - } - - /** - * Add canonical form of "-" for type T - */ - template - ModulePtr oper_subtract(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::subtract), "-"); - return m; - } - - /** - * Add canonical form of "/" for type T - */ - template - ModulePtr oper_divide(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::divide), "/"); - return m; - } - - /** - * Add canonical form of "*" for type T - */ - template - ModulePtr oper_multiply(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::multiply), "*"); - return m; - } - - /** - * Add canonical form of "!=" for type T - */ - template - ModulePtr oper_not_equals(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::not_equals), "!="); - return m; - } - - /** - * Add user defined assignment operator for T = U - */ - template - ModulePtr oper_assign_overload(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::assign), "="); - return m; - } - - - /** - * Add canonical form of "=" for type T - */ - template - ModulePtr oper_assign(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::assign), "="); - return m; - } - - - /** - * Add assignment operator for T = POD. - */ - template - ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::assign_pod), "="); - return m; - } - - - /** - * Add canonical form of "<" for type T - */ - template - ModulePtr oper_less_than(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::less_than), "<"); - return m; - } - - /** - * Add canonical form of ">" for type T - */ - template - ModulePtr oper_greater_than(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::greater_than), ">"); - return m; - } - - /** - * Add canonical form of "<=" for type T - */ - template - ModulePtr oper_less_than_equals(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::less_than_equals), "<="); - return m; - } - - /** - * Add canonical form of ">=" for type T - */ - template - ModulePtr oper_greater_than_equals(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::greater_than_equals), ">="); - return m; - } - - /** - * Add user defined comparison operators for T and R. - * Examples: T < R, T == R, etc. - */ - template - ModulePtr opers_comparison_overload(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::equals), "=="); - m->add(fun(&detail::not_equals), "!="); - m->add(fun(&detail::less_than), "<"); - m->add(fun(&detail::greater_than), ">"); - m->add(fun(&detail::less_than_equals), "<="); - m->add(fun(&detail::greater_than_equals), ">="); - return m; - } - - /** - * Add canonical forms of all comparison operators for type T - */ template ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module())) { - opers_comparison_overload(m); + operators::equal(m); + operators::greater_than(m); + operators::greater_than_equal(m); + operators::less_than(m); + operators::less_than_equal(m); + operators::not_equal(m); return m; } - /** - * Add all arithmetic operators that return a type of Ret, taking - * a lhs of T and a rhs of R, when possible. - * examples: Ret = T + R; - * ++T - * T *= R; - */ - template - ModulePtr opers_arithmetic_overload(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::add), "+"); - m->add(fun(&detail::subtract), "-"); - m->add(fun(&detail::divide), "/"); - m->add(fun(&detail::multiply), "*"); - m->add(fun(&detail::timesequal), "*="); - m->add(fun(&detail::dividesequal), "/="); - m->add(fun(&detail::subtractsequal), "-="); - m->add(fun(&detail::addsequal), "+="); - m->add(fun(&detail::prefixincrement), "++"); - m->add(fun(&detail::prefixdecrement), "--"); - m->add(fun(&detail::prefixnegate), "-"); - m->add(fun(&detail::prefixnot), "!"); - return m; - } - - /** - * Add arithmetic assign operators for POD types: - * example: POD *= T, POD /= T - */ template - ModulePtr opers_arithmetic_modify_pod(ModulePtr m = ModulePtr(new Module())) + ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&detail::timesequal_pod), "*="); - m->add(fun(&detail::dividesequal_pod), "/="); - m->add(fun(&detail::subtractsequal_pod), "-="); - m->add(fun(&detail::addsequal_pod), "+="); + operators::assign_bitwise_and(m); + operators::assign_xor(m); + operators::assign_bitwise_or(m); + operators::assign_difference(m); + operators::assign_left_shift(m); + operators::assign_product(m); + operators::assign_quotient(m); + operators::assign_remainder(m); + operators::assign_right_shift(m); + operators::assign_sum(m); + + operators::prefix_decrement(m); + operators::prefix_increment(m); + operators::addition(m); + operators::unary_plus(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::left_shift(m); + operators::multiplication(m); + operators::remainder(m); + operators::right_shift(m); + return m; + } + + 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::addition(m); + operators::unary_plus(m); + operators::subtraction(m); + operators::unary_minus(m); + operators::division(m); + operators::multiplication(m); return m; } @@ -476,16 +266,6 @@ namespace chaiscript return m; } - /** - * Add canonical forms of all arithmetic operators for type T - */ - template - ModulePtr opers_arithmetic(ModulePtr m = ModulePtr(new Module())) - { - opers_arithmetic_overload(m); - return m; - } - /** * to_string function for internal use. Uses ostream operator<< */ @@ -506,6 +286,17 @@ namespace chaiscript return boost::lexical_cast(i); } + + /** + * Add assignment operator for T = POD. + */ + template + ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module())) + { + m->add(fun(&detail::assign_pod), "="); + return m; + } + /** * Add all common functions for a POD type. All operators, and * common conversions @@ -515,16 +306,52 @@ namespace chaiscript { m->add(user_type(), name); basic_constructors(name, m); - oper_assign(m); + operators::assign(m); oper_assign_pod(m); construct_pod(name, m); - opers_arithmetic(m); - opers_arithmetic_modify_pod(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(&to_string), "to_string"); m->add(fun(&parse_string), "to_" + name); return m; } + /** + * Add all common functions for a POD type. All operators, and + * common conversions + */ + template + ModulePtr bootstrap_integer_type(const std::string &name, ModulePtr m = ModulePtr(new Module())) + { + bootstrap_pod_type(name, m); + + m->add(fun(&detail::assign_bitwise_and_pod), "&="); + m->add(fun(&detail::assign_xor_pod), "^="); + m->add(fun(&detail::assign_bitwise_or_pod), "|="); + m->add(fun(&detail::assign_left_shift_pod), "<<="); + m->add(fun(&detail::assign_remainder_pod), "%="); + m->add(fun(&detail::assign_right_shift_pod), ">>="); + + opers_integer_arithmetic(m); + return m; + } + + /** + * Add all common functions for a POD type. All operators, and + * common conversions + */ + template + ModulePtr bootstrap_float_type(const std::string &name, ModulePtr m = ModulePtr(new Module())) + { + bootstrap_pod_type(name, m); + opers_float_arithmetic(m); + return m; + } + /** * "clone" function for a shared_ptr type. This is used in the case * where you do not want to make a deep copy of an object during cloning @@ -598,28 +425,21 @@ namespace chaiscript std::cout << s << std::endl; } - /** - * Add all comparison operators for POD types - */ - static void opers_comparison_pod(ModulePtr m = ModulePtr(new Module())) - { - m->add(fun(&detail::equals), "=="); - m->add(fun(&detail::not_equals), "!="); - m->add(fun(&detail::less_than), "<"); - m->add(fun(&detail::greater_than), ">"); - m->add(fun(&detail::less_than_equals), "<="); - m->add(fun(&detail::greater_than_equals), ">="); - } - /** * Add all arithmetic operators for PODs */ static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&detail::add), "+"); - m->add(fun(&detail::subtract), "-"); - m->add(fun(&detail::divide), "/"); - m->add(fun(&detail::multiply), "*"); + m->add(fun(&operators::addition), "+"); + m->add(fun(&operators::subtraction), "-"); + m->add(fun(&operators::bitwise_and), "&"); + m->add(fun(&operators::bitwise_xor), "^"); + m->add(fun(&operators::bitwise_or), "|"); + m->add(fun(&operators::division), "/"); + m->add(fun(&operators::left_shift), "<<"); + m->add(fun(&operators::multiplication), "*"); + m->add(fun(&operators::remainder), "%"); + m->add(fun(&operators::right_shift), ">>"); } /** @@ -712,8 +532,7 @@ namespace chaiscript m->add(fun(&Boxed_Value::is_null), "is_null"); basic_constructors("bool", m); - oper_assign(m); - oper_assign(m); + operators::assign(m); m->add(fun(&to_string), "internal_to_string"); m->add(fun(&Bootstrap::bool_to_string), "internal_to_string"); @@ -721,18 +540,17 @@ namespace chaiscript m->add(fun(&throw_exception), "throw"); m->add(fun(&what), "what"); - bootstrap_pod_type("double", m); - bootstrap_pod_type("int", m); - bootstrap_pod_type("size_t", m); - bootstrap_pod_type("char", m); - bootstrap_pod_type("int64_t", m); + bootstrap_float_type("double", m); + bootstrap_integer_type("int", m); + bootstrap_integer_type("size_t", m); + bootstrap_integer_type("char", m); + bootstrap_integer_type("int64_t", m); - opers_comparison_pod(m); + operators::logical_compliment(m); + + opers_comparison(m); opers_arithmetic_pod(m); - m->add(fun(&detail::modulus), "%"); - m->add(fun(&detail::shift_left), "<<"); - m->add(fun(&detail::shift_right), ">>"); m->add(fun(&print), "print_string"); m->add(fun(&println), "println_string"); diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 53330bb..26572c0 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -147,7 +147,7 @@ namespace chaiscript ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { basic_constructors(type, m); - oper_assign(m); + operators::assign(m); return m; } @@ -392,8 +392,8 @@ namespace chaiscript ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { m->add(user_type(), type); - oper_add(m); - oper_add_equals(m); + operators::addition(m); + operators::assign_sum(m); opers_comparison(m); random_access_container_type(type, m); sequence_type(type, m); diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index beeb06d..8f33815 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -701,14 +701,44 @@ namespace chaiscript return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i)); } - Boxed_Value operator*(const Boxed_POD_Value &r) const + Boxed_Value operator-(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { - return Boxed_Value(i * r.i); + return Boxed_Value(i - r.i); } - return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i)); + return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i)); + } + + Boxed_Value operator&(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i & r.i); + } + + throw bad_boxed_cast("& only valid for integer types"); + } + + Boxed_Value operator^(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i ^ r.i); + } + + throw bad_boxed_cast("^ only valid for integer types"); + } + + Boxed_Value operator|(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i | r.i); + } + + throw bad_boxed_cast("| only valid for integer types"); } Boxed_Value operator/(const Boxed_POD_Value &r) const @@ -721,16 +751,50 @@ namespace chaiscript return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i)); } - Boxed_Value operator-(const Boxed_POD_Value &r) const + Boxed_Value operator<<(const Boxed_POD_Value &r) const { if (!m_isfloat && !r.m_isfloat) { - return Boxed_Value(i - r.i); + return Boxed_Value(i << r.i); } - return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i)); + throw bad_boxed_cast("<< only valid for integer types"); } + + Boxed_Value operator*(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i * r.i); + } + + return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i)); + } + + + Boxed_Value operator%(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i % r.i); + } + + throw bad_boxed_cast("\% only valid for integer types"); + } + + Boxed_Value operator>>(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i >> r.i); + } + + throw bad_boxed_cast(">> only valid for integer types"); + } + + + double d; boost::int64_t i; @@ -747,6 +811,20 @@ namespace chaiscript { typedef Boxed_POD_Value Result_Type; + static Result_Type cast(const Boxed_Value &ob) + { + return Boxed_POD_Value(ob); + } + }; + + /** + * Cast_Helper for converting from Boxed_Value to Boxed_POD_Value + */ + template<> + struct Cast_Helper + { + typedef Boxed_POD_Value Result_Type; + static Result_Type cast(const Boxed_Value &ob) { return Boxed_POD_Value(ob);