Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port IronLanguages/ironpython3#1643 to ironpython2 for #838. #839

Merged
merged 1 commit into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions Src/IronPython/Runtime/Operations/IntOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public static object __new__(CodeContext context, PythonType cls) {
}

#region Binary Operators

[SpecialName]
public static object FloorDivide(int x, int y) {
if (y == -1 && x == Int32.MinValue) {
Expand Down Expand Up @@ -414,15 +414,14 @@ public static object __coerce__(CodeContext context, int x, object o) {
public static string __format__(CodeContext/*!*/ context, int self, [NotNull]string/*!*/ formatSpec) {
StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}

string digits;
int width = 0;

switch (spec.Type) {
case 'n':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
CultureInfo culture = context.LanguageContext.NumericCulture;

if (culture == CultureInfo.InvariantCulture) {
Expand All @@ -444,6 +443,9 @@ public static string __format__(CodeContext/*!*/ context, int self, [NotNull]str
break;
case null:
case 'd':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.ThousandsComma) {
width = spec.Width ?? 0;

Expand Down Expand Up @@ -511,22 +513,36 @@ public static string __format__(CodeContext/*!*/ context, int self, [NotNull]str
}
break;
case 'X':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToHex(self, false);
break;
case 'x':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToHex(self, true);
break;
case 'o': // octal
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToOctal(self, true);
break;
case 'b': // binary
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToBinary(self, false);
break;
case 'c': // single char
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.Sign != null) {
throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
}

if (self < 0 || self > 0xFF) {
throw PythonOps.OverflowError("%c arg not in range(0x10000)");
}
Expand Down Expand Up @@ -588,7 +604,7 @@ internal static string ToBinary(int self) {
if (self == Int32.MinValue) {
return "-0b10000000000000000000000000000000";
}

string res = ToBinary(self, true);
if (self < 0) {
res = "-" + res;
Expand Down Expand Up @@ -619,7 +635,7 @@ private static string ToBinary(int self, bool includeType) {
} else {
digits = "10000000000000000000000000000000";
}

if (includeType) {
digits = "0b" + digits;
}
Expand Down
63 changes: 42 additions & 21 deletions Src/IronPython/Runtime/Operations/LongOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static object __new__(CodeContext context, PythonType cls, string s, int
public static object __new__(CodeContext/*!*/ context, PythonType cls, IList<byte> s) {
return __new__(context, cls, s, 10);
}

[StaticExtensionMethod]
public static object __new__(CodeContext/*!*/ context, PythonType cls, IList<byte> s, int redix) {
object value;
Expand Down Expand Up @@ -86,7 +86,7 @@ public static object __new__(CodeContext context, PythonType cls, object x) {
if (x is double) return ReturnObject(context, cls, DoubleOps.__long__((double)x));
if (x is int) return ReturnObject(context, cls, (BigInteger)(int)x);
if (x is BigInteger) return ReturnObject(context, cls, x);

if (x is Complex) throw PythonOps.TypeError("can't convert complex to long; use long(abs(z))");

if (x is decimal) {
Expand Down Expand Up @@ -331,7 +331,7 @@ public static double TrueDivide([NotNull]BigInteger x, [NotNull]BigInteger y) {
// otherwise give the user the truncated result if the result fits in a float
BigInteger rem;
BigInteger res = BigInteger.DivRem(x, y, out rem);
if (res.TryToFloat64(out fRes)) {
if (res.TryToFloat64(out fRes)) {
if(rem != BigInteger.Zero) {
// try and figure out the fractional portion
BigInteger fraction = y / rem;
Expand All @@ -343,7 +343,7 @@ public static double TrueDivide([NotNull]BigInteger x, [NotNull]BigInteger y) {
}

return fRes;
}
}

// otherwise report an error
throw PythonOps.OverflowError("long/long too large for a float");
Expand Down Expand Up @@ -444,7 +444,7 @@ public static string __oct__(BigInteger x) {
}

public static string __hex__(BigInteger x) {
// CPython 2.5 prints letters in lowercase, with a capital L.
// CPython 2.5 prints letters in lowercase, with a capital L.
if (x < 0) {
return "-0x" + (-x).ToString(16).ToLower() + "L";
} else {
Expand Down Expand Up @@ -540,7 +540,7 @@ public static int Compare(BigInteger x, BigInteger y) {
[SpecialName]
public static int Compare(BigInteger x, int y) {
int ix;
if (x.AsInt32(out ix)) {
if (x.AsInt32(out ix)) {
return ix == y ? 0 : ix > y ? 1 : -1;
}

Expand Down Expand Up @@ -568,7 +568,7 @@ public static int Compare(BigInteger x, [NotNull]Extensible<double> y) {
}

[SpecialName]
public static int Compare(BigInteger x, decimal y) {
public static int Compare(BigInteger x, decimal y) {
return DecimalOps.__cmp__(x, y);
}

Expand Down Expand Up @@ -604,7 +604,7 @@ public static int __hash__(BigInteger self) {
}

// Call the DLR's BigInteger hash function, which will return an int32 representation of
// b if b is within the int32 range. We use that as an optimization for hashing, and
// b if b is within the int32 range. We use that as an optimization for hashing, and
// assert the assumption below.
int hash = self.GetHashCode();
#if DEBUG
Expand Down Expand Up @@ -637,7 +637,7 @@ public static float ToFloat(BigInteger/*!*/ self) {
}

#region Binary Ops

[PythonHidden]
public static BigInteger Xor(BigInteger x, BigInteger y) {
return x ^ y;
Expand Down Expand Up @@ -706,7 +706,7 @@ public static bool AsUInt32(BigInteger self, out uint res) {
public static bool AsUInt64(BigInteger self, out ulong res) {
return self.AsUInt64(out res);
}

#endregion

#region Direct Conversions
Expand Down Expand Up @@ -907,18 +907,17 @@ public static int GetWordCount(BigInteger self) {
public static string/*!*/ __format__(CodeContext/*!*/ context, BigInteger/*!*/ self, [NotNull]string/*!*/ formatSpec) {
StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}

BigInteger val = self;
if (self < 0) {
val = -self;
}
string digits;

switch (spec.Type) {
case 'n':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
CultureInfo culture = context.LanguageContext.NumericCulture;

if (culture == CultureInfo.InvariantCulture) {
Expand All @@ -931,6 +930,9 @@ public static int GetWordCount(BigInteger self) {
break;
case null:
case 'd':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.ThousandsComma) {
var width = spec.Width ?? 0;
// If we're inserting commas, and we're padding with leading zeros.
Expand Down Expand Up @@ -995,22 +997,41 @@ public static int GetWordCount(BigInteger self) {
}
break;
case 'X':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = AbsToHex(val, false);
break;
case 'x':
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = AbsToHex(val, true);
break;
case 'o': // octal
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToOctal(val, true);
break;
case 'b': // binary
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
digits = ToBinary(val, false, true);
break;
case 'c': // single char
int iVal;
if (spec.Precision != null) {
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
}
if (spec.Sign != null) {
throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
} else if (!self.AsInt32(out iVal)) {
}
int iVal;
if (!self.AsInt32(out iVal)) {
throw PythonOps.OverflowError("long int too large to convert to int");
} else if(iVal < 0 || iVal > 0xFF) {
throw PythonOps.OverflowError("%c arg not in range(0x10000)");
Expand All @@ -1035,7 +1056,7 @@ private static string ToOctal(BigInteger val, bool lowercase) {
return ToDigits(val, 8, lowercase);
}

internal static string ToBinary(BigInteger val) {
internal static string ToBinary(BigInteger val) {
string res = ToBinary(val.Abs(), true, true);
if (val.IsNegative()) {
res = "-" + res;
Expand All @@ -1047,7 +1068,7 @@ private static string ToBinary(BigInteger val, bool includeType, bool lowercase)
Debug.Assert(!val.IsNegative());

string digits = ToDigits(val, 2, lowercase);

if (includeType) {
digits = (lowercase ? "0b" : "0B") + digits;
}
Expand All @@ -1062,7 +1083,7 @@ private static string ToBinary(BigInteger val, bool includeType, bool lowercase)

StringBuilder tmp = new StringBuilder();
tmp.Append(digits[0]);

for (int i = 1; i < maxPrecision && i < digits.Length; i++) {
// append if we have a significant digit or if we are forcing a minimum precision
if (digits[i] != '0' || i <= minPrecision) {
Expand Down Expand Up @@ -1129,7 +1150,7 @@ private static string ToBinary(BigInteger val, bool includeType, bool lowercase)
for (int i = str.Length - 1; i >= 0; i--) {
res.Append(str[i]);
}

return res.ToString();
}
}
Expand Down
Loading
Loading