From bf1ca889f84bddea770a2495617cce681aee3357 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 10 Aug 2022 14:18:42 +0200 Subject: [PATCH 1/3] Explicit float and int conversion for builtin types --- src/runtime/Native/ITypeOffsets.cs | 1 + src/runtime/Native/TypeOffset.cs | 1 + src/runtime/Types/ClassBase.cs | 25 +++++++++++++++++++++++++ src/runtime/Types/OperatorMethod.cs | 1 + tests/test_conversion.py | 9 +++++++++ 5 files changed, 37 insertions(+) diff --git a/src/runtime/Native/ITypeOffsets.cs b/src/runtime/Native/ITypeOffsets.cs index 2c4fdf59a..0920a312a 100644 --- a/src/runtime/Native/ITypeOffsets.cs +++ b/src/runtime/Native/ITypeOffsets.cs @@ -22,6 +22,7 @@ interface ITypeOffsets int nb_true_divide { get; } int nb_and { get; } int nb_int { get; } + int nb_float { get; } int nb_or { get; } int nb_xor { get; } int nb_lshift { get; } diff --git a/src/runtime/Native/TypeOffset.cs b/src/runtime/Native/TypeOffset.cs index 59c5c3ee0..847f1766d 100644 --- a/src/runtime/Native/TypeOffset.cs +++ b/src/runtime/Native/TypeOffset.cs @@ -31,6 +31,7 @@ static partial class TypeOffset internal static int nb_or { get; private set; } internal static int nb_xor { get; private set; } internal static int nb_int { get; private set; } + internal static int nb_float { get; private set; } internal static int nb_lshift { get; private set; } internal static int nb_rshift { get; private set; } internal static int nb_remainder { get; private set; } diff --git a/src/runtime/Types/ClassBase.cs b/src/runtime/Types/ClassBase.cs index 1e3c325cc..a48c72f32 100644 --- a/src/runtime/Types/ClassBase.cs +++ b/src/runtime/Types/ClassBase.cs @@ -529,6 +529,13 @@ static NewReference tp_call_impl(BorrowedReference ob, BorrowedReference args, B return callBinder.Invoke(ob, args, kw); } + static NewReference DoConvert(BorrowedReference ob) + { + var self = (CLRObject)GetManagedObject(ob)!; + using var python = self.inst.ToPython(); + return python.NewReferenceOrNull(); + } + static IEnumerable GetCallImplementations(Type type) => type.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(m => m.Name == "__call__"); @@ -564,6 +571,24 @@ public virtual void InitializeSlots(BorrowedReference pyType, SlotsHolder slotsH { TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.mp_length, new Interop.B_P(MpLengthSlot.impl), slotsHolder); } + + switch (Type.GetTypeCode(type.Value)) + { + case TypeCode.Byte: + case TypeCode.SByte: + case TypeCode.UInt16: + case TypeCode.UInt32: + case TypeCode.UInt64: + case TypeCode.Int16: + case TypeCode.Int32: + case TypeCode.Int64: + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvert), slotsHolder); + break; + case TypeCode.Double: + case TypeCode.Single: + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvert), slotsHolder); + break; + } } public virtual bool HasCustomNew() => this.GetType().GetMethod("tp_new") is not null; diff --git a/src/runtime/Types/OperatorMethod.cs b/src/runtime/Types/OperatorMethod.cs index 0c6127f65..88939a51d 100644 --- a/src/runtime/Types/OperatorMethod.cs +++ b/src/runtime/Types/OperatorMethod.cs @@ -53,6 +53,7 @@ static OperatorMethod() ["op_UnaryPlus"] = new SlotDefinition("__pos__", TypeOffset.nb_positive), ["__int__"] = new SlotDefinition("__int__", TypeOffset.nb_int), + ["__float__"] = new SlotDefinition("__float__", TypeOffset.nb_float), }; ComparisonOpMap = new Dictionary { diff --git a/tests/test_conversion.py b/tests/test_conversion.py index f8d8039c6..f5ceb45a1 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -720,3 +720,12 @@ def test_intptr_construction(): with pytest.raises(OverflowError): UIntPtr(v) +def test_explicit_conversion(): + from System import Int64, UInt64, Int32, UInt32, Int16, UInt16, Byte, SByte + from System import Double, Single + + for t in [Int64, UInt64, Int32, UInt32, Int16, UInt16, Byte, SByte]: + assert int(t(127)) == 127 + + for t in [Single, Double]: + assert float(t(0.125)) == 0.125 From 881b2b24e6a8e5ace4b99b78dbf569b2303e7a88 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 11 Aug 2022 09:28:02 +0200 Subject: [PATCH 2/3] Add conversions for int->float and bool->(int,float) --- src/runtime/Types/ClassBase.cs | 20 ++++++++++++++++++++ tests/test_conversion.py | 7 ++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/runtime/Types/ClassBase.cs b/src/runtime/Types/ClassBase.cs index a48c72f32..260427246 100644 --- a/src/runtime/Types/ClassBase.cs +++ b/src/runtime/Types/ClassBase.cs @@ -536,6 +536,20 @@ static NewReference DoConvert(BorrowedReference ob) return python.NewReferenceOrNull(); } + static NewReference DoConvertBooleanInt(BorrowedReference ob) + { + var self = (CLRObject)GetManagedObject(ob)!; + using var python = ((bool)self.inst ? 1 : 0).ToPython(); + return python.NewReferenceOrNull(); + } + + static NewReference DoConvertIntFloat(BorrowedReference ob) + { + var self = (CLRObject)GetManagedObject(ob)!; + using var python = (Convert.ToDouble(self.inst)).ToPython(); + return python.NewReferenceOrNull(); + } + static IEnumerable GetCallImplementations(Type type) => type.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(m => m.Name == "__call__"); @@ -574,6 +588,11 @@ public virtual void InitializeSlots(BorrowedReference pyType, SlotsHolder slotsH switch (Type.GetTypeCode(type.Value)) { + case TypeCode.Boolean: + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvertBooleanInt), slotsHolder); + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertIntFloat), slotsHolder); + break; + case TypeCode.Byte: case TypeCode.SByte: case TypeCode.UInt16: @@ -583,6 +602,7 @@ public virtual void InitializeSlots(BorrowedReference pyType, SlotsHolder slotsH case TypeCode.Int32: case TypeCode.Int64: TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvert), slotsHolder); + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertIntFloat), slotsHolder); break; case TypeCode.Double: case TypeCode.Single: diff --git a/tests/test_conversion.py b/tests/test_conversion.py index f5ceb45a1..3772c95cc 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -721,11 +721,16 @@ def test_intptr_construction(): UIntPtr(v) def test_explicit_conversion(): - from System import Int64, UInt64, Int32, UInt32, Int16, UInt16, Byte, SByte + from System import ( + Int64, UInt64, Int32, UInt32, Int16, UInt16, Byte, SByte, Boolean + ) from System import Double, Single + assert int(Boolean(True)) == 1 + for t in [Int64, UInt64, Int32, UInt32, Int16, UInt16, Byte, SByte]: assert int(t(127)) == 127 + assert float(t(127)) == 127.0 for t in [Single, Double]: assert float(t(0.125)) == 0.125 From 3cbdfdc6856783d23bc096409bf00f25aaa7bdee Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 11 Aug 2022 21:37:39 +0200 Subject: [PATCH 3/3] Use direct conversion functions and add more tests --- src/runtime/Types/ClassBase.cs | 39 +++++++++++++++++++++------------- tests/test_conversion.py | 13 +++++++++++- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/runtime/Types/ClassBase.cs b/src/runtime/Types/ClassBase.cs index 260427246..943841e25 100644 --- a/src/runtime/Types/ClassBase.cs +++ b/src/runtime/Types/ClassBase.cs @@ -536,18 +536,28 @@ static NewReference DoConvert(BorrowedReference ob) return python.NewReferenceOrNull(); } + static NewReference DoConvertInt(BorrowedReference ob) + { + var self = (CLRObject)GetManagedObject(ob)!; + return Runtime.PyLong_FromLongLong(Convert.ToInt64(self.inst)); + } + + static NewReference DoConvertUInt(BorrowedReference ob) + { + var self = (CLRObject)GetManagedObject(ob)!; + return Runtime.PyLong_FromUnsignedLongLong(Convert.ToUInt64(self.inst)); + } + static NewReference DoConvertBooleanInt(BorrowedReference ob) { var self = (CLRObject)GetManagedObject(ob)!; - using var python = ((bool)self.inst ? 1 : 0).ToPython(); - return python.NewReferenceOrNull(); + return Runtime.PyInt_FromInt32((bool)self.inst ? 1 : 0); } - static NewReference DoConvertIntFloat(BorrowedReference ob) + static NewReference DoConvertFloat(BorrowedReference ob) { var self = (CLRObject)GetManagedObject(ob)!; - using var python = (Convert.ToDouble(self.inst)).ToPython(); - return python.NewReferenceOrNull(); + return Runtime.PyFloat_FromDouble(Convert.ToDouble(self.inst)); } static IEnumerable GetCallImplementations(Type type) @@ -589,24 +599,23 @@ public virtual void InitializeSlots(BorrowedReference pyType, SlotsHolder slotsH switch (Type.GetTypeCode(type.Value)) { case TypeCode.Boolean: - TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvertBooleanInt), slotsHolder); - TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertIntFloat), slotsHolder); + case TypeCode.SByte: + case TypeCode.Int16: + case TypeCode.Int32: + case TypeCode.Int64: + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvertInt), slotsHolder); + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertFloat), slotsHolder); break; - case TypeCode.Byte: - case TypeCode.SByte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: - case TypeCode.Int16: - case TypeCode.Int32: - case TypeCode.Int64: - TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvert), slotsHolder); - TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertIntFloat), slotsHolder); + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvertUInt), slotsHolder); + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertFloat), slotsHolder); break; case TypeCode.Double: case TypeCode.Single: - TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvert), slotsHolder); + TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertFloat), slotsHolder); break; } } diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 3772c95cc..69e7ec63f 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -726,11 +726,22 @@ def test_explicit_conversion(): ) from System import Double, Single + assert int(Boolean(False)) == 0 assert int(Boolean(True)) == 1 - for t in [Int64, UInt64, Int32, UInt32, Int16, UInt16, Byte, SByte]: + for t in [UInt64, UInt32, UInt16, Byte]: assert int(t(127)) == 127 assert float(t(127)) == 127.0 + for t in [Int64, Int32, Int16, SByte]: + assert int(t(127)) == 127 + assert int(t(-127)) == -127 + assert float(t(127)) == 127.0 + assert float(t(-127)) == -127.0 + + assert int(Int64.MaxValue) == 2**63 - 1 + assert int(Int64.MinValue) == -2**63 + assert int(UInt64.MaxValue) == 2**64 - 1 + for t in [Single, Double]: assert float(t(0.125)) == 0.125 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy