@@ -948,7 +948,7 @@ namespace pythonic
948948 }
949949 if (tag_ == TypeTag::STRING || other.tag_ == TypeTag::STRING )
950950 {
951- throw pythonic::PythonicTypeError (" cannot multiply two strings" );
951+ throw pythonic::PythonicTypeError (" operator* not supported for strings. Cannot perform ' " + type () + " * " + other. type () + " '. " );
952952 }
953953
954954 // Check if any input is floating point
@@ -1006,7 +1006,7 @@ namespace pythonic
10061006 {
10071007 if (tag_ == TypeTag::STRING || other.tag_ == TypeTag::STRING )
10081008 {
1009- throw pythonic::PythonicTypeError (" cannot divide strings" );
1009+ throw pythonic::PythonicTypeError (" operator/ not supported for strings. Cannot perform ' " + type () + " / " + other. type () + " '. " );
10101010 }
10111011
10121012 long double divisor = other.toLongDouble ();
@@ -1032,7 +1032,7 @@ namespace pythonic
10321032 {
10331033 if (tag_ == TypeTag::STRING || other.tag_ == TypeTag::STRING )
10341034 {
1035- throw pythonic::PythonicTypeError (" cannot perform modulo on strings" );
1035+ throw pythonic::PythonicTypeError (" operator% not supported for strings. Cannot perform ' " + type () + " % " + other. type () + " '. " );
10361036 }
10371037
10381038 long double divisor = other.toLongDouble ();
@@ -2260,7 +2260,9 @@ namespace pythonic
22602260 }
22612261 }
22622262 // Mixed types - use type promotion (handles numeric + numeric, string + anything, etc.)
2263- return addPromoted (other);
2263+ if ((is_string () || isNumeric ()) && (other.is_string () || other.isNumeric ()))
2264+ return addPromoted (other);
2265+ throw pythonic::PythonicTypeError (" operator+ not supported for these types. Cannot perform '" + type () + " + " + other.type () + " '." );
22642266 }
22652267
22662268 // Unary plus: returns a copy (Python semantics)
@@ -2341,6 +2343,55 @@ namespace pythonic
23412343 }
23422344 return var (std::move (result));
23432345 }
2346+ case TypeTag::ORDEREDSET :
2347+ {
2348+ // Both are ordered sets, use merge-like difference
2349+ const auto &a = var_get<OrderedSet>();
2350+ const auto &b = other.var_get <OrderedSet>();
2351+ OrderedSet result;
2352+ auto it_a = a.begin ();
2353+ auto it_b = b.begin ();
2354+ while (it_a != a.end () && it_b != b.end ())
2355+ {
2356+ if (*it_a < *it_b)
2357+ {
2358+ result.insert (*it_a);
2359+ ++it_a;
2360+ }
2361+ else if (*it_b < *it_a)
2362+ {
2363+ ++it_b;
2364+ }
2365+ else
2366+ {
2367+ // Equal, skip
2368+ ++it_a;
2369+ ++it_b;
2370+ }
2371+ }
2372+ // Insert remaining elements from a
2373+ while (it_a != a.end ())
2374+ {
2375+ result.insert (*it_a);
2376+ ++it_a;
2377+ }
2378+ return var (std::move (result));
2379+ }
2380+ case TypeTag::ORDEREDDICT :
2381+ {
2382+ // Both are ordered dicts, remove keys in b from a, preserve order
2383+ const auto &a = var_get<OrderedDict>();
2384+ const auto &b = other.var_get <OrderedDict>();
2385+ OrderedDict result;
2386+ for (const auto &kv : a)
2387+ {
2388+ if (b.find (kv.first ) == b.end ())
2389+ {
2390+ result.insert (kv);
2391+ }
2392+ }
2393+ return var (std::move (result));
2394+ }
23442395 case TypeTag::LIST :
23452396 {
23462397 const auto &a = var_get<List>();
@@ -2379,7 +2430,7 @@ namespace pythonic
23792430 {
23802431 return subPromoted (other);
23812432 }
2382- throw pythonic::PythonicTypeError (" operator- requires arithmetic types or containers" );
2433+ throw pythonic::PythonicTypeError (" operator- requires arithmetic types or containers. Cannot perform ' " + type () + " - " + other. type () + " '. " );
23832434 }
23842435
23852436 var operator *(const var &other) const
@@ -2457,7 +2508,7 @@ namespace pythonic
24572508 }
24582509 return var (std::move (result));
24592510 }
2460- throw pythonic::PythonicTypeError (" unsupported types for multiplication " );
2511+ throw pythonic::PythonicTypeError (" operator* not supported for these types. Cannot perform ' " + type () + " * " + other. type () + " '. " );
24612512 }
24622513
24632514 var operator /(const var &other) const
@@ -2569,7 +2620,7 @@ namespace pythonic
25692620 {
25702621 return divPromoted (other);
25712622 }
2572- throw pythonic::PythonicTypeError (" unsupported types for division " );
2623+ throw pythonic::PythonicTypeError (" operator/ not supported for these types. Cannot perform ' " + type () + " / " + other. type () + " '. " );
25732624 }
25742625
25752626 var operator %(const var &other) const
@@ -2636,7 +2687,7 @@ namespace pythonic
26362687 {
26372688 return modPromoted (other);
26382689 }
2639- throw pythonic::PythonicTypeError (" unsupported types for modulo " );
2690+ throw pythonic::PythonicTypeError (" operator% not supported for these types. Cannot perform ' " + type () + " % " + other. type () + " '. " );
26402691 }
26412692
26422693 // ============ In-Place Arithmetic Operators ============
@@ -3154,8 +3205,8 @@ namespace pythonic
31543205 {
31553206 return var (toDouble () == other.toDouble ());
31563207 }
3157- // Different types (except numeric) are not equal
3158- return var ( false );
3208+ // Different types (except numeric) are not equal: throw for clarity
3209+ throw pythonic::PythonicTypeError ( " operator== not supported for these types. Cannot perform ' " + type () + " == " + other. type () + " '. " );
31593210 }
31603211
31613212 var operator !=(const var &other) const
@@ -3271,7 +3322,7 @@ namespace pythonic
32713322 {
32723323 return var (toDouble () != other.toDouble ());
32733324 }
3274- return var ( true );
3325+ throw pythonic::PythonicTypeError ( " operator!= not supported for these types. Cannot perform ' " + type () + " != " + other. type () + " '. " );
32753326 }
32763327
32773328 var operator >(const var &other) const
@@ -3310,7 +3361,7 @@ namespace pythonic
33103361 {
33113362 return var (toDouble () > other.toDouble ());
33123363 }
3313- throw pythonic::PythonicTypeError (" unsupported types for comparison " );
3364+ throw pythonic::PythonicTypeError (" operator> not supported for these types. Cannot perform ' " + type () + " > " + other. type () + " '. " );
33143365 }
33153366
33163367 var operator >=(const var &other) const
@@ -3349,7 +3400,7 @@ namespace pythonic
33493400 {
33503401 return var (toDouble () >= other.toDouble ());
33513402 }
3352- throw pythonic::PythonicTypeError (" unsupported types for comparison " );
3403+ throw pythonic::PythonicTypeError (" operator>= not supported for these types. Cannot perform ' " + type () + " >= " + other. type () + " '. " );
33533404 }
33543405
33553406 var operator <=(const var &other) const
@@ -3388,7 +3439,7 @@ namespace pythonic
33883439 {
33893440 return var (toDouble () <= other.toDouble ());
33903441 }
3391- throw pythonic::PythonicTypeError (" unsupported types for comparison " );
3442+ throw pythonic::PythonicTypeError (" operator<= not supported for these types. Cannot perform ' " + type () + " <= " + other. type () + " '. " );
33923443 }
33933444
33943445 // ============ OPTIMIZED Implicit Conversion Operators for Arithmetic Types ============
@@ -3747,7 +3798,7 @@ namespace pythonic
37473798 case TypeTag::ULONG_LONG :
37483799 return var (~var_get<unsigned long long >());
37493800 default :
3750- throw pythonic::PythonicTypeError (" bitwise NOT requires integral type" );
3801+ throw pythonic::PythonicTypeError (" operator~ requires integral type. Cannot perform '~ " + type () + " '. " );
37513802 }
37523803 }
37533804
@@ -3864,7 +3915,7 @@ namespace pythonic
38643915 {
38653916 return var (toLongLong () & other.toLongLong ());
38663917 }
3867- throw pythonic::PythonicTypeError (" operator& requires integral types or containers" );
3918+ throw pythonic::PythonicTypeError (" operator& requires integral types or containers. Cannot perform ' " + type () + " & " + other. type () + " '. " );
38683919 }
38693920
38703921 var operator |(const var &other) const
@@ -3976,7 +4027,7 @@ namespace pythonic
39764027 {
39774028 return var (toLongLong () | other.toLongLong ());
39784029 }
3979- throw pythonic::PythonicTypeError (" operator| requires integral types or containers" );
4030+ throw pythonic::PythonicTypeError (" operator| requires integral types or containers. Cannot perform ' " + type () + " | " + other. type () + " '. " );
39804031 }
39814032
39824033 var operator ^(const var &other) const
@@ -4090,46 +4141,52 @@ namespace pythonic
40904141 {
40914142 return var (toLongLong () ^ other.toLongLong ());
40924143 }
4093- throw pythonic::PythonicTypeError (" operator^ requires integral types or sets/lists" );
4144+ throw pythonic::PythonicTypeError (" operator^ requires integral types or sets/lists. Cannot perform ' " + type () + " ^ " + other. type () + " '. " );
40944145 }
40954146 // In-place bitwise AND
4096- var &operator &=(const var &other) {
4097- *this = *this & other;
4098- return *this ;
4099- }
4147+ var &operator &=(const var &other)
4148+ {
4149+ *this = *this & other;
4150+ return *this ;
4151+ }
41004152
4101- // In-place bitwise OR
4102- var &operator |=(const var &other) {
4103- *this = *this | other;
4104- return *this ;
4105- }
4153+ // In-place bitwise OR
4154+ var &operator |=(const var &other)
4155+ {
4156+ *this = *this | other;
4157+ return *this ;
4158+ }
41064159
4107- // In-place bitwise XOR
4108- var &operator ^=(const var &other) {
4109- *this = *this ^ other;
4110- return *this ;
4111- }
4160+ // In-place bitwise XOR
4161+ var &operator ^=(const var &other)
4162+ {
4163+ *this = *this ^ other;
4164+ return *this ;
4165+ }
41124166
4113- // In-place bitwise AND with primitive
4114- template <typename T, typename = std::enable_if_t <std::is_arithmetic_v<T>>>
4115- var &operator &=(T other) {
4116- *this = *this & var (other);
4117- return *this ;
4118- }
4167+ // In-place bitwise AND with primitive
4168+ template <typename T, typename = std::enable_if_t <std::is_arithmetic_v<T>>>
4169+ var &operator &=(T other)
4170+ {
4171+ *this = *this & var (other);
4172+ return *this ;
4173+ }
41194174
4120- // In-place bitwise OR with primitive
4121- template <typename T, typename = std::enable_if_t <std::is_arithmetic_v<T>>>
4122- var &operator |=(T other) {
4123- *this = *this | var (other);
4124- return *this ;
4125- }
4175+ // In-place bitwise OR with primitive
4176+ template <typename T, typename = std::enable_if_t <std::is_arithmetic_v<T>>>
4177+ var &operator |=(T other)
4178+ {
4179+ *this = *this | var (other);
4180+ return *this ;
4181+ }
41264182
4127- // In-place bitwise XOR with primitive
4128- template <typename T, typename = std::enable_if_t <std::is_arithmetic_v<T>>>
4129- var &operator ^=(T other) {
4130- *this = *this ^ var (other);
4131- return *this ;
4132- }
4183+ // In-place bitwise XOR with primitive
4184+ template <typename T, typename = std::enable_if_t <std::is_arithmetic_v<T>>>
4185+ var &operator ^=(T other)
4186+ {
4187+ *this = *this ^ var (other);
4188+ return *this ;
4189+ }
41334190
41344191 // Bool conversion
41354192 operator bool () const
@@ -4234,7 +4291,7 @@ namespace pythonic
42344291 }
42354292 return lst[index];
42364293 }
4237- throw pythonic::PythonicTypeError (" operator[] requires a list" );
4294+ throw pythonic::PythonicTypeError (" operator[] requires a list. Cannot perform ' " + type () + " [index]'. " );
42384295 }
42394296
42404297 const var &operator [](size_t index) const
@@ -4248,7 +4305,7 @@ namespace pythonic
42484305 }
42494306 return lst[index];
42504307 }
4251- throw pythonic::PythonicTypeError (" operator[] requires a list" );
4308+ throw pythonic::PythonicTypeError (" operator[] requires a list. Cannot perform ' " + type () + " [index]'. " );
42524309 }
42534310
42544311 var &operator [](const std::string &key)
@@ -4261,7 +4318,7 @@ namespace pythonic
42614318 {
42624319 return var_get<OrderedDict>()[key];
42634320 }
4264- throw pythonic::PythonicTypeError (" operator[] requires a dict or ordered_dict" );
4321+ throw pythonic::PythonicTypeError (" operator[] requires a dict or ordered_dict. Cannot perform ' " + type () + " [key]'. " );
42654322 }
42664323
42674324 var &operator [](const char *key)
0 commit comments