Skip to content

Commit

Permalink
generic tests are now passing
Browse files Browse the repository at this point in the history
  • Loading branch information
eirannejad committed Jan 13, 2024
1 parent 7333d16 commit 953a3c3
Show file tree
Hide file tree
Showing 10 changed files with 738 additions and 368 deletions.
40 changes: 34 additions & 6 deletions dev/MethodBinder.Tests/MethodBinderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public abstract class InvokeTests
protected static readonly TargetTypeA A = new();
protected static readonly TargetTypeB B = new();
protected static readonly TargetTypeC C = new();
protected static readonly TargetTypeD D = new();

protected static readonly object[] NoArgs = Array.Empty<object>();
protected static readonly KeywordArgs NoKwargs = new();
Expand All @@ -42,6 +43,16 @@ public void TestFooParam_0()

public sealed class InvokeTests_1 : InvokeTests
{
[Test]
public void TestFooParam_1_ShortAsGeneric()
{
// Foo(int _1)
object[] args = new object[] { (ushort)0 };
Guid t = A.Foo((ushort)0);
NewReference r = BINDER.Invoke(A, M, args, NoKwargs);
Assert.That(r.Value, Is.EqualTo(t));
}

[Test]
public void TestFooParam_1_Int()
{
Expand Down Expand Up @@ -168,7 +179,6 @@ public void TestFooParam_1_DataC()

public sealed class InvokeTests_2 : InvokeTests
{

[Test]
public void TestFooParam_2_Int_Int()
{
Expand Down Expand Up @@ -247,6 +257,29 @@ public void TestFooParam_2_FloatArray_FloatArray()
}
}

public sealed class InvokeTests_2_Ambig : InvokeTests
{
[Test]
public void TestFooParam_2_Int16_Int32()
{
// Foo(short _1, short _2)
object[] args = new object[] { (short)0, (int)1 };
Guid t = D.Foo((short)0, (short)1);
NewReference r = BINDER.Invoke(D, M, args, NoKwargs);
Assert.That(r.Value, Is.EqualTo(t));
}

[Test]
public void TestFooParam_2_Int64_Int32()
{
// Foo(long _1, long _2)
object[] args = new object[] { (long)0, 1 };
Guid t = D.Foo((long)0, 1);
NewReference r = BINDER.Invoke(D, M, args, NoKwargs);
Assert.That(r.Value, Is.EqualTo(t));
}
}

public sealed class InvokeTests_N : InvokeTests
{
[Test]
Expand Down Expand Up @@ -304,11 +337,6 @@ public void TestFooParam_X_Object_TwoIntAsArray()

/*
* UNUSED GUIDS
return new Guid("5755a950-a11d-11ee-8c90-0242ac120002");
return new Guid("5755aa86-a11d-11ee-8c90-0242ac120002");
return new Guid("5755ab9e-a11d-11ee-8c90-0242ac120002");
return new Guid("5755acac-a11d-11ee-8c90-0242ac120002");
return new Guid("5755adc4-a11d-11ee-8c90-0242ac120002");
return new Guid("5755aedc-a11d-11ee-8c90-0242ac120002");
return new Guid("5755afea-a11d-11ee-8c90-0242ac120002");
return new Guid("5755b2b0-a11d-11ee-8c90-0242ac120002");
Expand Down
13 changes: 13 additions & 0 deletions dev/MethodBinder.Tests/TargetTypeA.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#pragma warning disable CA1822
using System;

namespace MethodBinder.Tests
Expand All @@ -15,6 +16,18 @@ public Guid
}

// 1
public Guid
Foo(short _1)
{
return new Guid("5755ab9e-a11d-11ee-8c90-0242ac120002");
}

public Guid
Foo<T>(T _1)
{
return new Guid("5755acac-a11d-11ee-8c90-0242ac120002");
}

public Guid
Foo(int _1)
{
Expand Down
30 changes: 30 additions & 0 deletions dev/MethodBinder.Tests/TargetTypeD.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma warning disable CA1822
using System;

namespace MethodBinder.Tests
{
using O = System.Runtime.InteropServices.OptionalAttribute;
using D = System.Runtime.InteropServices.DefaultParameterValueAttribute;

public class TargetTypeD
{
// 2
public Guid
Foo(short _1, short _2)
{
return new Guid("5755a950-a11d-11ee-8c90-0242ac120002");
}

public Guid
Foo(int _1, int _2)
{
return new Guid("5755aa86-a11d-11ee-8c90-0242ac120002");
}

public Guid
Foo(long _1, long _2)
{
return new Guid("5755adc4-a11d-11ee-8c90-0242ac120002");
}
}
}
30 changes: 24 additions & 6 deletions dev/MethodBinder/MethodBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,13 @@ public static NewReference Invoke(object instance,

if (TryBind(methods, argsRef, kwargsRef, true, out BindSpec ? spec))
{
if (spec!.TryGetArguments(instance, out object?[] arguments))
if (spec!.TryGetArguments(instance,
out MethodBase method,
out object?[] arguments))
{
try
{
object? result = spec!.Method.Invoke(instance, arguments);
object? result = method.Invoke(instance, arguments);

if (result is null)
{
Expand Down Expand Up @@ -257,15 +259,33 @@ public static NewReference Invoke(object instance,
"op_GreaterThan",
};

static Type? GetCLRType(BorrowedReference br, Type _)
=> br.Value?.GetType();
static Type? GetCLRType(BorrowedReference br) => br.Value?.GetType();

static bool TryGetManagedValue(BorrowedReference br,
out object? value)
{
return TryCast(br.Value, out value);
}

static bool TryGetManagedValue(BorrowedReference br, Type type,
out object? value)
{
return TryCast(br.Value, type, out value);
}

static bool TryCast(object? source, out object? cast)
{
cast = default;

if (source is null)
{
return false;
}

cast = source;
return true;
}

static bool TryCast(object? source, Type to, out object? cast)
{
cast = default;
Expand Down Expand Up @@ -339,7 +359,5 @@ static bool IsReverse(MethodBase method)
Type leftOperandType = method.GetParameters()[0].ParameterType;
return leftOperandType != method.DeclaringType;
}

static bool IsValid(MethodBase _) => true;
}
}
119 changes: 77 additions & 42 deletions src/runtime/Converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,64 @@ private Converter()
{
}

private static readonly Type objectType;
private static readonly Type stringType;
private static readonly Type singleType;
private static readonly Type doubleType;
private static readonly Type int16Type;
private static readonly Type int32Type;
private static readonly Type int64Type;
private static readonly Type boolType;
private static readonly Type typeType;

static Converter()
private static readonly Type typeType = typeof(Type);
private static readonly Type objectType = typeof(Object);
private static readonly Type boolType = typeof(Boolean);
private static readonly Type singleType = typeof(Single);
private static readonly Type doubleType = typeof(Double);
private static readonly Type int16Type = typeof(Int16);
private static readonly Type int32Type = typeof(Int32);
private static readonly Type int64Type = typeof(Int64);
private static readonly Type uint16Type = typeof(UInt16);
private static readonly Type uint32Type = typeof(UInt32);
private static readonly Type uint64Type = typeof(UInt64);
private static readonly Type stringType = typeof(String);

internal static Type? GetTypeByAlias(BorrowedReference pyType, BorrowedReference op)
{
objectType = typeof(Object);
stringType = typeof(String);
int16Type = typeof(Int16);
int32Type = typeof(Int32);
int64Type = typeof(Int64);
singleType = typeof(Single);
doubleType = typeof(Double);
boolType = typeof(Boolean);
typeType = typeof(Type);
}
if (pyType == Runtime.PyLongType)
{
nint? int32 = Runtime.PyLong_AsSignedSize_t(op);
if (int32 != null)
{
if (int32 > UInt32.MaxValue)
{
return int64Type;
}
return int32Type;
}

nuint? uint32 = Runtime.PyLong_AsUnsignedSize_t(op);
if (uint32 != null)
{
Exceptions.Clear();
if (uint32 > UInt32.MaxValue)
{
return uint64Type;
}
return uint32Type;
}

long? int64 = Runtime.PyLong_AsLongLong(op);
if (int64 != null)
{
Exceptions.Clear();
return int64Type;
}

ulong? uint64 = Runtime.PyLong_AsUnsignedLongLong(op);
if (uint64 != null)
{
Exceptions.Clear();
return uint64Type;
}

Exceptions.Clear();
Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
}

return GetTypeByAlias(pyType);
}

/// <summary>
/// Given a builtin Python type, return the corresponding CLR type.
Expand Down Expand Up @@ -74,13 +109,13 @@ internal static BorrowedReference GetPythonTypeByAlias(Type op)
if (op == stringType)
return Runtime.PyUnicodeType.Reference;

if (op == int16Type)
if (op == int16Type || op == uint16Type)
return Runtime.PyLongType.Reference;

if (op == int32Type)
if (op == int32Type || op == uint32Type)
return Runtime.PyLongType.Reference;

if (op == int64Type)
if (op == int64Type || op == uint64Type)
return Runtime.PyLongType.Reference;

if (op == doubleType)
Expand Down Expand Up @@ -582,8 +617,8 @@ static bool DecodableByUser(Type type)

internal static int ToInt32(BorrowedReference value)
{
nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
throw PythonException.ThrowLastAsClrException();
}
Expand Down Expand Up @@ -621,8 +656,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec
case TypeCode.Int32:
{
// Python3 always use PyLong API
nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand Down Expand Up @@ -664,8 +699,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec
goto type_error;
}

nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand All @@ -690,8 +725,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec
goto type_error;
}

nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand Down Expand Up @@ -725,8 +760,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec
}
goto type_error;
}
nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand All @@ -740,8 +775,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec

case TypeCode.Int16:
{
nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand Down Expand Up @@ -771,8 +806,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec
}
else
{
nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand All @@ -783,8 +818,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec

case TypeCode.UInt16:
{
nint num = Runtime.PyLong_AsSignedSize_t(value);
if (num == -1 && Exceptions.ErrorOccurred())
nint? num = Runtime.PyLong_AsSignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand All @@ -798,8 +833,8 @@ internal static bool ToPrimitive(BorrowedReference value, Type obType, out objec

case TypeCode.UInt32:
{
nuint num = Runtime.PyLong_AsUnsignedSize_t(value);
if (num == unchecked((nuint)(-1)) && Exceptions.ErrorOccurred())
nuint? num = Runtime.PyLong_AsUnsignedSize_t(value);
if (num is null)
{
goto convert_error;
}
Expand Down
Loading

0 comments on commit 953a3c3

Please sign in to comment.