Skip to content

Commit ddf1400

Browse files
authored
Add rich comparison operators to number types (#1088)
* Add rich comparison operators to number types * Add SortKeyWrapper * Cleanup * Add __iter__ methods to str and bytes * Don't fallback to types comparisons * Some __cmp__ cleanup
1 parent c8371e6 commit ddf1400

File tree

17 files changed

+321
-138
lines changed

17 files changed

+321
-138
lines changed

Src/IronPython.Modules/_datetime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ public override bool Equals(object obj) {
14171417
#region Rich Comparison Members
14181418

14191419
/// <summary>
1420-
/// Helper function for doing the comparisons. time has no __cmp__ method
1420+
/// Helper function for doing the comparisons.
14211421
/// </summary>
14221422
private int CompareTo(object other) {
14231423
time other2 = other as time;

Src/IronPython/Modules/_locale.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,24 @@ public static int strcoll(CodeContext/*!*/ context, string string1, string strin
9191
return GetLocaleInfo(context).Collate.CompareInfo.Compare(string1, string2, CompareOptions.None);
9292
}
9393

94-
[Documentation(@"returns a System.Globalization.SortKey that can be compared using the built-in cmp.
94+
private sealed class SortKeyWrapper : IComparable<SortKeyWrapper>, IComparable {
95+
public SortKey SortKey { get; }
9596

96-
Note: Return value differs from CPython - it is not a string.")]
97-
public static object strxfrm(CodeContext/*!*/ context, string @string) {
98-
return GetLocaleInfo(context).Collate.CompareInfo.GetSortKey(@string);
97+
public SortKeyWrapper(SortKey sortKey) {
98+
SortKey = sortKey;
99+
}
100+
101+
public int CompareTo(SortKeyWrapper other) => SortKey.Compare(SortKey, other.SortKey);
102+
103+
public int CompareTo(object other) => (other is SortKeyWrapper wrapper) ? CompareTo(wrapper) : throw new ArgumentException($"The parameter must be a {nameof(SortKeyWrapper)}.", nameof(other));
99104
}
100105

106+
[Documentation(@"returns a wrapped System.Globalization.SortKey that can be compared using the built-in cmp.
107+
108+
Note: Return value differs from CPython - it is not a string.")]
109+
public static object strxfrm(CodeContext/*!*/ context, string @string)
110+
=> new SortKeyWrapper(GetLocaleInfo(context).Collate.CompareInfo.GetSortKey(@string));
111+
101112
private enum LocaleCategories {
102113
All = 0,
103114
Collate = 1,

Src/IronPython/Runtime/Binding/PythonBinder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,11 +380,11 @@ public override ErrorInfo MakeUndeletableMemberError(Type type, string name) {
380380
#endregion
381381

382382
internal IList<Type> GetExtensionTypesInternal(Type t) {
383-
List<Type> res = new List<Type>(base.GetExtensionTypes(t));
383+
var res = new List<Type>(base.GetExtensionTypes(t));
384384

385385
AddExtensionTypes(t, res);
386386

387-
return res.ToArray();
387+
return res;
388388
}
389389

390390
public override bool IncludeExtensionMember(MemberInfo member) {

Src/IronPython/Runtime/ByteArray.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,9 @@ public bool __contains__(CodeContext context, object? value) {
10561056
throw PythonOps.TypeError("Type {0} doesn't support the buffer API", PythonTypeOps.GetName(value));
10571057
}
10581058

1059+
public IEnumerator<int> __iter__()
1060+
=> IListOfByteOps.BytesEnumerator(this);
1061+
10591062
public PythonTuple __reduce__(CodeContext context) {
10601063
return PythonTuple.MakeTuple(
10611064
DynamicHelpers.GetPythonType(this),
@@ -1437,10 +1440,6 @@ public bool Remove(byte item) {
14371440

14381441
#endregion
14391442

1440-
public IEnumerator __iter__() {
1441-
return PythonOps.BytesEnumerator(this).Key;
1442-
}
1443-
14441443
#region IEnumerable<byte> Members
14451444

14461445
[PythonHidden]

Src/IronPython/Runtime/Bytes.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,9 @@ public bool __contains__(CodeContext context, object? value) {
846846
throw PythonOps.TypeError("Type {0} doesn't support the buffer API", PythonTypeOps.GetName(value));
847847
}
848848

849+
public IEnumerator<int> __iter__()
850+
=> IListOfByteOps.BytesEnumerator(this);
851+
849852
public PythonTuple __reduce__(CodeContext context) {
850853
return PythonTuple.MakeTuple(
851854
DynamicHelpers.GetPythonType(this),

Src/IronPython/Runtime/Operations/DecimalOps.cs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
namespace IronPython.Runtime.Operations {
1717
public static class DecimalOps {
1818

19-
public static int __cmp__(CodeContext context, decimal x, decimal other) {
19+
internal static int __cmp__(CodeContext context, decimal x, decimal other) {
2020
return x.CompareTo(other);
2121
}
2222

@@ -29,29 +29,30 @@ public static string __repr__(decimal x) {
2929
}
3030

3131
[SpecialName]
32-
public static bool LessThan(decimal x, decimal y) {
33-
return x < y;
34-
}
32+
public static bool LessThan(decimal x, decimal y) => x < y;
3533
[SpecialName]
36-
public static bool LessThanOrEqual(decimal x, decimal y) {
37-
return x <= y;
38-
}
34+
public static bool LessThanOrEqual(decimal x, decimal y) => x <= y;
3935
[SpecialName]
40-
public static bool GreaterThan(decimal x, decimal y) {
41-
return x > y;
42-
}
36+
public static bool GreaterThan(decimal x, decimal y) => x > y;
4337
[SpecialName]
44-
public static bool GreaterThanOrEqual(decimal x, decimal y) {
45-
return x >= y;
46-
}
38+
public static bool GreaterThanOrEqual(decimal x, decimal y) => x >= y;
4739
[SpecialName]
48-
public static bool Equals(decimal x, decimal y) {
49-
return x == y;
50-
}
40+
public static bool Equals(decimal x, decimal y) => x == y;
5141
[SpecialName]
52-
public static bool NotEquals(decimal x, decimal y) {
53-
return x != y;
54-
}
42+
public static bool NotEquals(decimal x, decimal y) => x != y;
43+
44+
[SpecialName]
45+
public static bool LessThan(decimal x, BigInteger y) => __cmp__(x, y) < 0;
46+
[SpecialName]
47+
public static bool LessThanOrEqual(decimal x, BigInteger y) => __cmp__(x, y) <= 0;
48+
[SpecialName]
49+
public static bool GreaterThan(decimal x, BigInteger y) => __cmp__(x, y) > 0;
50+
[SpecialName]
51+
public static bool GreaterThanOrEqual(decimal x, BigInteger y) => __cmp__(x, y) >= 0;
52+
[SpecialName]
53+
public static bool Equals(decimal x, BigInteger y) => __cmp__(x, y) == 0;
54+
[SpecialName]
55+
public static bool NotEquals(decimal x, BigInteger y) => __cmp__(x, y) != 0;
5556

5657
internal static int __cmp__(BigInteger x, decimal y) {
5758
return -__cmp__(y, x);

Src/IronPython/Runtime/Operations/InstanceOps.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,6 @@ public static object NonDefaultNewKWNoParams(CodeContext context, PythonType typ
182182

183183
#region Iteration
184184

185-
// 3.0-only
186-
public static object IterMethodForString(string self) {
187-
return StringOps.StringEnumerator(self);
188-
}
189-
190-
// 3.0-only
191-
public static object IterMethodForBytes(Bytes self) {
192-
return IListOfByteOps.BytesEnumerator(self);
193-
}
194-
195185
public static object IterMethodForEnumerator(IEnumerator self) {
196186
return self;
197187
}

Src/IronPython/Runtime/Operations/IntOps.Generated.cs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,18 @@ public static SByte ExclusiveOr(SByte x, SByte y) {
183183
public static int Compare(SByte x, SByte y) {
184184
return x == y ? 0 : x > y ? 1 : -1;
185185
}
186+
[SpecialName]
187+
public static bool LessThan(SByte x, SByte y) => x < y;
188+
[SpecialName]
189+
public static bool LessThanOrEqual(SByte x, SByte y) => x <= y;
190+
[SpecialName]
191+
public static bool GreaterThan(SByte x, SByte y) => x > y;
192+
[SpecialName]
193+
public static bool GreaterThanOrEqual(SByte x, SByte y) => x >= y;
194+
[SpecialName]
195+
public static bool Equals(SByte x, SByte y) => x == y;
196+
[SpecialName]
197+
public static bool NotEquals(SByte x, SByte y) => x != y;
186198

187199
// Conversion operators
188200
[SpecialName, ExplicitConversionMethod]
@@ -498,6 +510,30 @@ public static int Compare(Byte x, SByte y) {
498510
public static int Compare(SByte x, Byte y) {
499511
return Int16Ops.Compare((Int16)x, (Int16)y);
500512
}
513+
[SpecialName]
514+
public static bool LessThan(Byte x, Byte y) => x < y;
515+
[SpecialName]
516+
public static bool LessThan(Byte x, SByte y) => x < y;
517+
[SpecialName]
518+
public static bool LessThanOrEqual(Byte x, Byte y) => x <= y;
519+
[SpecialName]
520+
public static bool LessThanOrEqual(Byte x, SByte y) => x <= y;
521+
[SpecialName]
522+
public static bool GreaterThan(Byte x, Byte y) => x > y;
523+
[SpecialName]
524+
public static bool GreaterThan(Byte x, SByte y) => x > y;
525+
[SpecialName]
526+
public static bool GreaterThanOrEqual(Byte x, Byte y) => x >= y;
527+
[SpecialName]
528+
public static bool GreaterThanOrEqual(Byte x, SByte y) => x >= y;
529+
[SpecialName]
530+
public static bool Equals(Byte x, Byte y) => x == y;
531+
[SpecialName]
532+
public static bool Equals(Byte x, SByte y) => x == y;
533+
[SpecialName]
534+
public static bool NotEquals(Byte x, Byte y) => x != y;
535+
[SpecialName]
536+
public static bool NotEquals(Byte x, SByte y) => x != y;
501537

502538
// Conversion operators
503539
[SpecialName, ExplicitConversionMethod]
@@ -727,6 +763,18 @@ public static Int16 ExclusiveOr(Int16 x, Int16 y) {
727763
public static int Compare(Int16 x, Int16 y) {
728764
return x == y ? 0 : x > y ? 1 : -1;
729765
}
766+
[SpecialName]
767+
public static bool LessThan(Int16 x, Int16 y) => x < y;
768+
[SpecialName]
769+
public static bool LessThanOrEqual(Int16 x, Int16 y) => x <= y;
770+
[SpecialName]
771+
public static bool GreaterThan(Int16 x, Int16 y) => x > y;
772+
[SpecialName]
773+
public static bool GreaterThanOrEqual(Int16 x, Int16 y) => x >= y;
774+
[SpecialName]
775+
public static bool Equals(Int16 x, Int16 y) => x == y;
776+
[SpecialName]
777+
public static bool NotEquals(Int16 x, Int16 y) => x != y;
730778

731779
// Conversion operators
732780
[SpecialName, ExplicitConversionMethod]
@@ -1045,6 +1093,30 @@ public static int Compare(UInt16 x, Int16 y) {
10451093
public static int Compare(Int16 x, UInt16 y) {
10461094
return Int32Ops.Compare((Int32)x, (Int32)y);
10471095
}
1096+
[SpecialName]
1097+
public static bool LessThan(UInt16 x, UInt16 y) => x < y;
1098+
[SpecialName]
1099+
public static bool LessThan(UInt16 x, Int16 y) => x < y;
1100+
[SpecialName]
1101+
public static bool LessThanOrEqual(UInt16 x, UInt16 y) => x <= y;
1102+
[SpecialName]
1103+
public static bool LessThanOrEqual(UInt16 x, Int16 y) => x <= y;
1104+
[SpecialName]
1105+
public static bool GreaterThan(UInt16 x, UInt16 y) => x > y;
1106+
[SpecialName]
1107+
public static bool GreaterThan(UInt16 x, Int16 y) => x > y;
1108+
[SpecialName]
1109+
public static bool GreaterThanOrEqual(UInt16 x, UInt16 y) => x >= y;
1110+
[SpecialName]
1111+
public static bool GreaterThanOrEqual(UInt16 x, Int16 y) => x >= y;
1112+
[SpecialName]
1113+
public static bool Equals(UInt16 x, UInt16 y) => x == y;
1114+
[SpecialName]
1115+
public static bool Equals(UInt16 x, Int16 y) => x == y;
1116+
[SpecialName]
1117+
public static bool NotEquals(UInt16 x, UInt16 y) => x != y;
1118+
[SpecialName]
1119+
public static bool NotEquals(UInt16 x, Int16 y) => x != y;
10481120

10491121
// Conversion operators
10501122
[SpecialName, ExplicitConversionMethod]
@@ -1219,6 +1291,18 @@ public static Int32 ExclusiveOr(Int32 x, Int32 y) {
12191291
public static int Compare(Int32 x, Int32 y) {
12201292
return x == y ? 0 : x > y ? 1 : -1;
12211293
}
1294+
[SpecialName]
1295+
public static bool LessThan(Int32 x, Int32 y) => x < y;
1296+
[SpecialName]
1297+
public static bool LessThanOrEqual(Int32 x, Int32 y) => x <= y;
1298+
[SpecialName]
1299+
public static bool GreaterThan(Int32 x, Int32 y) => x > y;
1300+
[SpecialName]
1301+
public static bool GreaterThanOrEqual(Int32 x, Int32 y) => x >= y;
1302+
[SpecialName]
1303+
public static bool Equals(Int32 x, Int32 y) => x == y;
1304+
[SpecialName]
1305+
public static bool NotEquals(Int32 x, Int32 y) => x != y;
12221306

12231307
// Conversion operators
12241308
[SpecialName, ExplicitConversionMethod]
@@ -1532,6 +1616,30 @@ public static int Compare(UInt32 x, Int32 y) {
15321616
public static int Compare(Int32 x, UInt32 y) {
15331617
return Int64Ops.Compare((Int64)x, (Int64)y);
15341618
}
1619+
[SpecialName]
1620+
public static bool LessThan(UInt32 x, UInt32 y) => x < y;
1621+
[SpecialName]
1622+
public static bool LessThan(UInt32 x, Int32 y) => x < y;
1623+
[SpecialName]
1624+
public static bool LessThanOrEqual(UInt32 x, UInt32 y) => x <= y;
1625+
[SpecialName]
1626+
public static bool LessThanOrEqual(UInt32 x, Int32 y) => x <= y;
1627+
[SpecialName]
1628+
public static bool GreaterThan(UInt32 x, UInt32 y) => x > y;
1629+
[SpecialName]
1630+
public static bool GreaterThan(UInt32 x, Int32 y) => x > y;
1631+
[SpecialName]
1632+
public static bool GreaterThanOrEqual(UInt32 x, UInt32 y) => x >= y;
1633+
[SpecialName]
1634+
public static bool GreaterThanOrEqual(UInt32 x, Int32 y) => x >= y;
1635+
[SpecialName]
1636+
public static bool Equals(UInt32 x, UInt32 y) => x == y;
1637+
[SpecialName]
1638+
public static bool Equals(UInt32 x, Int32 y) => x == y;
1639+
[SpecialName]
1640+
public static bool NotEquals(UInt32 x, UInt32 y) => x != y;
1641+
[SpecialName]
1642+
public static bool NotEquals(UInt32 x, Int32 y) => x != y;
15351643

15361644
// Conversion operators
15371645
[SpecialName, ExplicitConversionMethod]
@@ -1768,6 +1876,18 @@ public static Int64 ExclusiveOr(Int64 x, Int64 y) {
17681876
public static int Compare(Int64 x, Int64 y) {
17691877
return x == y ? 0 : x > y ? 1 : -1;
17701878
}
1879+
[SpecialName]
1880+
public static bool LessThan(Int64 x, Int64 y) => x < y;
1881+
[SpecialName]
1882+
public static bool LessThanOrEqual(Int64 x, Int64 y) => x <= y;
1883+
[SpecialName]
1884+
public static bool GreaterThan(Int64 x, Int64 y) => x > y;
1885+
[SpecialName]
1886+
public static bool GreaterThanOrEqual(Int64 x, Int64 y) => x >= y;
1887+
[SpecialName]
1888+
public static bool Equals(Int64 x, Int64 y) => x == y;
1889+
[SpecialName]
1890+
public static bool NotEquals(Int64 x, Int64 y) => x != y;
17711891

17721892
// Conversion operators
17731893
[SpecialName, ExplicitConversionMethod]
@@ -2081,6 +2201,30 @@ public static int Compare(UInt64 x, Int64 y) {
20812201
public static int Compare(Int64 x, UInt64 y) {
20822202
return BigIntegerOps.Compare((BigInteger)x, (BigInteger)y);
20832203
}
2204+
[SpecialName]
2205+
public static bool LessThan(UInt64 x, UInt64 y) => x < y;
2206+
[SpecialName]
2207+
public static bool LessThan(UInt64 x, Int64 y) => BigIntegerOps.LessThan((BigInteger)x, (BigInteger)y);
2208+
[SpecialName]
2209+
public static bool LessThanOrEqual(UInt64 x, UInt64 y) => x <= y;
2210+
[SpecialName]
2211+
public static bool LessThanOrEqual(UInt64 x, Int64 y) => BigIntegerOps.LessThanOrEqual((BigInteger)x, (BigInteger)y);
2212+
[SpecialName]
2213+
public static bool GreaterThan(UInt64 x, UInt64 y) => x > y;
2214+
[SpecialName]
2215+
public static bool GreaterThan(UInt64 x, Int64 y) => BigIntegerOps.GreaterThan((BigInteger)x, (BigInteger)y);
2216+
[SpecialName]
2217+
public static bool GreaterThanOrEqual(UInt64 x, UInt64 y) => x >= y;
2218+
[SpecialName]
2219+
public static bool GreaterThanOrEqual(UInt64 x, Int64 y) => BigIntegerOps.GreaterThanOrEqual((BigInteger)x, (BigInteger)y);
2220+
[SpecialName]
2221+
public static bool Equals(UInt64 x, UInt64 y) => x == y;
2222+
[SpecialName]
2223+
public static bool Equals(UInt64 x, Int64 y) => BigIntegerOps.Equals((BigInteger)x, (BigInteger)y);
2224+
[SpecialName]
2225+
public static bool NotEquals(UInt64 x, UInt64 y) => x != y;
2226+
[SpecialName]
2227+
public static bool NotEquals(UInt64 x, Int64 y) => BigIntegerOps.NotEquals((BigInteger)x, (BigInteger)y);
20842228

20852229
// Conversion operators
20862230
[SpecialName, ExplicitConversionMethod]

0 commit comments

Comments
 (0)