Some compat fixes for .NET 5
This commit is contained in:
parent
a6fa3eef08
commit
67ad9b0ccc
@ -57,6 +57,8 @@ System.IFormattable
|
||||
System.IFormatProvider
|
||||
System.InvalidCastException
|
||||
System.IServiceProvider
|
||||
System.IObservable`*
|
||||
System.IObserver`*
|
||||
|
||||
System.Nullable`*
|
||||
|
||||
@ -188,6 +190,7 @@ System.Reflection.IReflect
|
||||
System.Reflection.MemberInfo
|
||||
System.Reflection.FieldInfo
|
||||
System.Reflection.EventInfo
|
||||
System.Reflection.ParameterAttributes
|
||||
System.Reflection.ParameterInfo
|
||||
System.Reflection.PropertyInfo
|
||||
System.Reflection.MethodInfo
|
||||
|
@ -881,63 +881,56 @@ namespace system
|
||||
{
|
||||
ThrowIfNull(array);
|
||||
if (index < 0 || length < 0)
|
||||
throw new System.ArgumentOutOfRangeException();
|
||||
if (array.len - index < length)
|
||||
throw new System.ArgumentException();
|
||||
throw new System.IndexOutOfRangeException();
|
||||
var endIndex = index + length;
|
||||
if (endIndex > array.len)
|
||||
throw new System.IndexOutOfRangeException();
|
||||
|
||||
switch (array.arr)
|
||||
{
|
||||
case bool[] boolArray:
|
||||
for (; length-- > 0; index++)
|
||||
boolArray[index] = default(bool);
|
||||
java.util.Arrays.fill(boolArray, index, endIndex, false);
|
||||
break;
|
||||
|
||||
case sbyte[] byteArray:
|
||||
for (; length-- > 0; index++)
|
||||
byteArray[index] = default(sbyte);
|
||||
java.util.Arrays.fill(byteArray, index, endIndex, (sbyte) 0);
|
||||
break;
|
||||
|
||||
case char[] charArray:
|
||||
for (; length-- > 0; index++)
|
||||
charArray[index] = default(char);
|
||||
java.util.Arrays.fill(charArray, index, endIndex, (char) 0);
|
||||
break;
|
||||
|
||||
case short[] shortArray:
|
||||
for (; length-- > 0; index++)
|
||||
shortArray[index] = default(short);
|
||||
java.util.Arrays.fill(shortArray, index, endIndex, (short) 0);
|
||||
break;
|
||||
|
||||
case int[] intArray:
|
||||
for (; length-- > 0; index++)
|
||||
intArray[index] = default(int);
|
||||
java.util.Arrays.fill(intArray, index, endIndex, (int) 0);
|
||||
break;
|
||||
|
||||
case long[] longArray:
|
||||
for (; length-- > 0; index++)
|
||||
longArray[index] = default(long);
|
||||
java.util.Arrays.fill(longArray, index, endIndex, (long) 0);
|
||||
break;
|
||||
|
||||
case float[] floatArray:
|
||||
for (; length-- > 0; index++)
|
||||
floatArray[index] = default(float);
|
||||
java.util.Arrays.fill(floatArray, index, endIndex, (float) 0);
|
||||
break;
|
||||
|
||||
case double[] doubleArray:
|
||||
for (; length-- > 0; index++)
|
||||
doubleArray[index] = default(double);
|
||||
java.util.Arrays.fill(doubleArray, index, endIndex, (double) 0);
|
||||
break;
|
||||
|
||||
case object[] objectArray:
|
||||
if (system.RuntimeType.IsValueClass(
|
||||
((java.lang.Object) array.arr).getClass().getComponentType()))
|
||||
((java.lang.Object) (object) objectArray)
|
||||
.getClass().getComponentType()))
|
||||
{
|
||||
for (; length-- > 0; index++)
|
||||
((ValueMethod) (ValueType) objectArray[index]).Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; length-- > 0; index++)
|
||||
objectArray[index] = null;
|
||||
java.util.Arrays.fill(objectArray, index, endIndex, null);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -946,6 +939,86 @@ namespace system
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Fill
|
||||
//
|
||||
|
||||
public static void Fill<T>(T[] array, T value)
|
||||
{
|
||||
ThrowIfNull(array);
|
||||
FillCommon(array, (object) value, 0, java.lang.reflect.Array.getLength(array));
|
||||
}
|
||||
|
||||
public static void Fill<T>(T[] array, T value, int startIndex, int count)
|
||||
{
|
||||
ThrowIfNull(array);
|
||||
if (startIndex < 0 || count < 0)
|
||||
throw new System.IndexOutOfRangeException();
|
||||
var endIndex = startIndex + count;
|
||||
if (endIndex > java.lang.reflect.Array.getLength(array))
|
||||
throw new System.IndexOutOfRangeException();
|
||||
FillCommon(array, (object) value, startIndex, endIndex);
|
||||
}
|
||||
|
||||
private static void FillCommon(object array, object value, int startIndex, int endIndex)
|
||||
{
|
||||
switch (array)
|
||||
{
|
||||
case bool[] boolArray:
|
||||
java.util.Arrays.fill(boolArray, startIndex, endIndex, (bool) value);
|
||||
break;
|
||||
|
||||
case sbyte[] byteArray:
|
||||
java.util.Arrays.fill(byteArray, startIndex, endIndex, (sbyte) value);
|
||||
break;
|
||||
|
||||
case char[] charArray:
|
||||
java.util.Arrays.fill(charArray, startIndex, endIndex, (char) value);
|
||||
break;
|
||||
|
||||
case short[] shortArray:
|
||||
java.util.Arrays.fill(shortArray, startIndex, endIndex, (short) value);
|
||||
break;
|
||||
|
||||
case int[] intArray:
|
||||
java.util.Arrays.fill(intArray, startIndex, endIndex, (int) value);
|
||||
break;
|
||||
|
||||
case long[] longArray:
|
||||
java.util.Arrays.fill(longArray, startIndex, endIndex, (long) value);
|
||||
break;
|
||||
|
||||
case float[] floatArray:
|
||||
java.util.Arrays.fill(floatArray, startIndex, endIndex, (float) value);
|
||||
break;
|
||||
|
||||
case double[] doubleArray:
|
||||
java.util.Arrays.fill(doubleArray, startIndex, endIndex, (double) value);
|
||||
break;
|
||||
|
||||
case object[] objectArray:
|
||||
if (system.RuntimeType.IsValueClass(
|
||||
((java.lang.Object) array).getClass().getComponentType()))
|
||||
{
|
||||
ValueType v = (ValueType) value;
|
||||
for (; startIndex < endIndex; startIndex++)
|
||||
((ValueMethod) v).CopyTo((ValueType) objectArray[startIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
java.util.Arrays.fill(objectArray, startIndex, endIndex, value);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new System.InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var type = ((java.lang.Object) arr).getClass().getComponentType();
|
||||
|
@ -25,6 +25,8 @@ namespace system
|
||||
// number of days between 1/1/0001 and 1/1/10000 is 3,652,059
|
||||
const long MaxTicks = 3652059 * TicksPerDay - 1;
|
||||
|
||||
public static readonly DateTime MaxValue = new DateTime(MaxTicks, DateTimeKind.Unspecified);
|
||||
|
||||
//
|
||||
// Constructors (Now)
|
||||
//
|
||||
|
@ -33,7 +33,6 @@ namespace system
|
||||
{
|
||||
DelegateUtil.CopyBoxed(fromObj, toObj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -161,8 +160,22 @@ namespace system
|
||||
proxy = genericObject.TryCast(castToType);
|
||||
else
|
||||
proxy = Array.GetProxy(obj, castToType, true);
|
||||
|
||||
if (proxy == null)
|
||||
{
|
||||
if ( (obj != null) && (! castToType.IsGenericType)
|
||||
&& castToType is RuntimeType castToRuntimeType
|
||||
&& castToRuntimeType.JavaClassForArray()
|
||||
.isAssignableFrom(((java.lang.Object) obj).getClass()))
|
||||
{
|
||||
// target type is not generic, but the object can be cast to
|
||||
// it. this happens when both object and target type are one
|
||||
// of the non-generic interfaces implemented by Array.
|
||||
// see also IsArray() in GenericUtil::ShouldCallGenericCast.
|
||||
return obj;
|
||||
}
|
||||
ThrowInvalidCastException(obj, castToType);
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
@ -141,14 +141,17 @@ namespace system
|
||||
try
|
||||
{
|
||||
// TODO: check if begins with NumberFormatInfo.Positive/NegativeSign
|
||||
result = java.lang.Integer.parseInt(s.Trim());
|
||||
return true;
|
||||
if (s != null)
|
||||
{
|
||||
result = java.lang.Integer.parseInt(s.Trim());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (java.lang.NumberFormatException)
|
||||
{
|
||||
result = 0;
|
||||
return false;
|
||||
}
|
||||
result = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@ namespace system
|
||||
|
||||
int len = format.length();
|
||||
|
||||
bool explicit_width = false;
|
||||
int width = -1;
|
||||
if (len == 1)
|
||||
width = 0;
|
||||
@ -72,18 +73,22 @@ namespace system
|
||||
|
||||
case 'D':
|
||||
c = isInt ? 'd' : (char) 0;
|
||||
pfx = '0';
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if (isInt)
|
||||
{
|
||||
c = 'd';
|
||||
pfx = ',';
|
||||
sfx = "." + new string('0', width);
|
||||
width = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 'f';
|
||||
explicit_width = true; // set width even if zero
|
||||
}
|
||||
pfx = ',';
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
@ -116,7 +121,7 @@ namespace system
|
||||
var format1 = "%";
|
||||
if (pfx != 0)
|
||||
format1 += pfx;
|
||||
if (width != 0)
|
||||
if (explicit_width || width != 0)
|
||||
{
|
||||
if (! isInt)
|
||||
format1 += ".";
|
||||
|
@ -5,6 +5,10 @@ namespace system.runtime.interopservices
|
||||
public static class Marshal
|
||||
{
|
||||
|
||||
[java.attr.RetainType] private static java.util.concurrent.ConcurrentHashMap MarshalTypes =
|
||||
new java.util.concurrent.ConcurrentHashMap();
|
||||
|
||||
|
||||
public static int SizeOf(System.Type t)
|
||||
{
|
||||
var j = ((system.RuntimeType) t).JavaClassForArray();
|
||||
@ -12,9 +16,26 @@ namespace system.runtime.interopservices
|
||||
: (j == java.lang.Character.TYPE || j == java.lang.Short.TYPE) ? 2
|
||||
: (j == java.lang.Integer.TYPE || j == java.lang.Float.TYPE) ? 4
|
||||
: (j == java.lang.Long.TYPE || j == java.lang.Double.TYPE) ? 8
|
||||
: MarshalTypes.get(t) is int sz ? sz
|
||||
: throw new System.PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
|
||||
public static bool SetComObjectData(object obj, object key, object data)
|
||||
{
|
||||
// this method is used to record extra types that Marshal.SizeOf
|
||||
// should recognize, and the size returned for each such type
|
||||
|
||||
#pragma warning disable 0252
|
||||
if (obj == typeof(Marshal) && key is System.Type && data is int)
|
||||
{
|
||||
MarshalTypes.put(key, data);
|
||||
return true;
|
||||
}
|
||||
throw new System.PlatformNotSupportedException();
|
||||
//return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -145,7 +145,15 @@ namespace system
|
||||
|
||||
[java.attr.RetainName]
|
||||
public static System.ValueType Assign(ValueType source)
|
||||
=> new Span<T>((T[]) (object) (new ValueType[1] { source }));
|
||||
{
|
||||
return new Span<T>()
|
||||
{
|
||||
array = Reference.Box(new ValueType[1] { source }),
|
||||
count = 1,
|
||||
shift = Shiftof() + 1
|
||||
};
|
||||
// => new Span<T>((T[]) (object) (new ValueType[1] { source }));
|
||||
}
|
||||
|
||||
[java.attr.RetainName]
|
||||
public static Span<object> Assign(long zero)
|
||||
|
@ -186,6 +186,7 @@ namespace SpaceFlint.CilToJava
|
||||
.Replace(']', '\uFF3D') // U+FF3D Fullwidth Right Square Bracket
|
||||
.Replace('`', '\uFF40') // U+FF40 Fullwidth Grave Accent
|
||||
.Replace('~', '\uFF5E') // U+FF40 Fullwidth Tilde
|
||||
.Replace(' ', '\uFFE2') // U+FFE2 Fullwidth Not Sign
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -811,7 +811,7 @@ namespace SpaceFlint.CilToJava
|
||||
var thisRef = stackMap.PopStack(CilMain.Where);
|
||||
if (updateThis && thisRef.Equals(JavaStackMap.UninitializedThis))
|
||||
{
|
||||
// an 'uninitializedthis' first argument is updated in
|
||||
// an 'uninitializedThis' first argument is updated in
|
||||
// the stack frame after calling the super constructor
|
||||
locals.UpdateThis(method.DeclType);
|
||||
}
|
||||
|
@ -592,13 +592,15 @@ namespace SpaceFlint.CilToJava
|
||||
var castType = (CilType) CilType.From(cilType);
|
||||
JavaType castClass = CilType.From(cilType).AsWritableClass;
|
||||
|
||||
if (GenericUtil.ShouldCallGenericCast(stackTop, castType))
|
||||
if ( GenericUtil.ShouldCallGenericCast(stackTop, castType)
|
||||
|| castType.IsGenericParameter)
|
||||
{
|
||||
code.StackMap.PushStack(stackTop);
|
||||
// casting to a generic type is done via GenericType.TestCast
|
||||
GenericUtil.CastToGenericType(cilType, 0, code);
|
||||
code.StackMap.PopStack(CilMain.Where); // stackTop
|
||||
code.NewInstruction(0xC0 /* checkcast */, castClass, null);
|
||||
if (! castType.IsGenericParameter)
|
||||
code.NewInstruction(0xC0 /* checkcast */, castClass, null);
|
||||
code.StackMap.PushStack(castClass);
|
||||
}
|
||||
|
||||
|
@ -403,7 +403,31 @@ namespace SpaceFlint.CilToJava
|
||||
// is a value class that is assigned before the call to the
|
||||
// base constructor.
|
||||
|
||||
if (fldType.IsValueClass)
|
||||
if (fldType.IsGenericParameter)
|
||||
{
|
||||
// if the field has a generic type, we first need to allocate
|
||||
// it (as would be done by ValueUtil.ConstructValue) and then
|
||||
// copy the value on the stack into it
|
||||
|
||||
GenericUtil.LoadMaybeGeneric(fldType, code);
|
||||
code.NewInstruction(0xB8 /* invokestatic */, GenericUtil.SystemGenericType,
|
||||
new JavaMethodRef("New", CilType.SystemValueType, CilType.SystemTypeType));
|
||||
|
||||
// use dup_x1 to arrange the stack as (newObj, sourceObj, newObj)
|
||||
code.NewInstruction(0x5A /* dup_x1 */, null, null);
|
||||
stackMap.PushStack(fldType);
|
||||
stackMap.PushStack(fldType);
|
||||
|
||||
// call GenericType.Copy(fromObj, toObj) in baselib
|
||||
code.NewInstruction(0xB8 /* invokestatic */, GenericUtil.SystemGenericType,
|
||||
new JavaMethod("Copy", JavaType.VoidType,
|
||||
JavaType.ObjectType, JavaType.ObjectType));
|
||||
|
||||
stackMap.PopStack(CilMain.Where);
|
||||
stackMap.PopStack(CilMain.Where);
|
||||
}
|
||||
|
||||
else if (fldType.IsValueClass)
|
||||
{
|
||||
CilMethod.ValueMethod(CilMethod.ValueClone, code);
|
||||
code.NewInstruction(0xC0 /* checkcast */, fldType.AsWritableClass, null);
|
||||
|
@ -136,6 +136,11 @@ namespace SpaceFlint.CilToJava
|
||||
if (code.MaxStack < 1)
|
||||
code.MaxStack = 1;
|
||||
|
||||
// we are injecting a call to super constructor at the very top,
|
||||
// so local 0 should have the proper type, not uninitializedThis
|
||||
code.StackMap.SetLocalInAllFrames(
|
||||
0, CilType.From(new JavaType(0, 0, dataClass.Name)), null);
|
||||
|
||||
insertReturn = false;
|
||||
}
|
||||
|
||||
|
@ -600,9 +600,22 @@ namespace SpaceFlint.CilToJava
|
||||
}
|
||||
if (sameParameters)
|
||||
{
|
||||
//Console.WriteLine($"proxying {targetMethod} in class {targetMethod.DeclType}");
|
||||
BuildGenericProxy2(baseMethod, targetMethod,
|
||||
false, targetMethod.DeclType, intoClass);
|
||||
if (baseMethod.Method.WithGenericParameters.ToString()
|
||||
!= targetMethod.WithGenericParameters.ToString())
|
||||
{
|
||||
// the proxy method may have the same signature as the
|
||||
// target method. for example in a generic class that
|
||||
// inherits from a generic class:
|
||||
// class A<T> { virtual T Method(T arg); }
|
||||
// and class B<T> : A<T> { override T Method(T arg); }
|
||||
// in such a case, we should not generate a specialized
|
||||
// proxy for the generic method in class B.
|
||||
//
|
||||
|
||||
//Console.WriteLine($"proxying {targetMethod} in class {targetMethod.DeclType}");
|
||||
BuildGenericProxy2(baseMethod, targetMethod,
|
||||
false, targetMethod.DeclType, intoClass);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ namespace SpaceFlint.JavaBinary
|
||||
{
|
||||
if (! frm.locals[index].Equals(type))
|
||||
{
|
||||
if (frm.locals[index] != Top)
|
||||
if (Where != null && frm.locals[index] != Top)
|
||||
throw Where.Exception($"local already assigned in stack frame");
|
||||
frm.locals[index] = type;
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ namespace Tests
|
||||
|
||||
//TestDictionary();
|
||||
TestSet();
|
||||
|
||||
TestStack();
|
||||
TestHash();
|
||||
}
|
||||
|
||||
|
||||
@ -127,5 +127,18 @@ namespace Tests
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void TestHash()
|
||||
{
|
||||
var dict = new System.Collections.Hashtable();
|
||||
dict["int1"] = (int) 10;
|
||||
dict["int2"] = (int) 20;
|
||||
int sum = 0;
|
||||
foreach (var key in dict.Keys)
|
||||
sum += (int) dict[key];
|
||||
Console.WriteLine(sum);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ namespace Tests
|
||||
TestCompare();
|
||||
TestCast("Test");
|
||||
TestEncoding();
|
||||
TestNumber();
|
||||
}
|
||||
|
||||
|
||||
@ -244,5 +245,14 @@ namespace Tests
|
||||
Console.WriteLine(string.CompareOrdinal(aString, bString));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TestNumber()
|
||||
{
|
||||
int x = 1;
|
||||
var y = 33333.030303;
|
||||
Console.WriteLine($"[{x:D3}] [{y:N0}]");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user