incremental changes
This commit is contained in:
parent
9181b2ab62
commit
5aa43c15ee
@ -16,9 +16,12 @@ System.ArithmeticException
|
||||
System.ArrayTypeMismatchException
|
||||
System.ApplicationException
|
||||
System.Comparison`*
|
||||
System.Convert
|
||||
System.Converter`*
|
||||
System.DateTime
|
||||
System.DBNull
|
||||
System.DllNotFoundException
|
||||
System.Empty
|
||||
System.EventArgs
|
||||
System.EventHandler
|
||||
System.EventHandler`*
|
||||
@ -49,6 +52,7 @@ System.Nullable`*
|
||||
System.SystemException
|
||||
System.OverflowException
|
||||
|
||||
System.Collections.Comparer
|
||||
System.Collections.ICollection
|
||||
System.Collections.IDictionary
|
||||
System.Collections.IDictionaryEnumerator
|
||||
@ -147,6 +151,7 @@ System.Reflection.Assembly
|
||||
System.Reflection.AssemblyName
|
||||
System.Reflection.AssemblyNameFlags
|
||||
System.Reflection.AssemblyProductAttribute
|
||||
System.Reflection.Binder
|
||||
System.Reflection.BindingFlags
|
||||
System.Reflection.CallingConventions
|
||||
System.Reflection.IReflect
|
||||
@ -160,9 +165,12 @@ System.Reflection.TypeInfo
|
||||
System.Reflection.MemberFilter
|
||||
System.Reflection.Missing
|
||||
System.Reflection.ICustomAttributeProvider
|
||||
System.Reflection.InterfaceMapping
|
||||
System.Reflection.InvalidFilterCriteriaException
|
||||
System.Reflection.IReflectableType
|
||||
System.Reflection.ParameterModifier
|
||||
System.Reflection.TypeAttributes
|
||||
System.Reflection.TypeFilter
|
||||
System.Reflection.TargetParameterCountException
|
||||
System.Reflection.TargetInvocationException
|
||||
System.IRuntimeMethodInfo
|
||||
|
@ -5,6 +5,8 @@ namespace system.collections
|
||||
[java.attr.AsInterface]
|
||||
public abstract class IComparer : java.lang.Comparable, java.util.Comparator
|
||||
{
|
||||
public abstract int Compare(object x, object y);
|
||||
|
||||
[java.attr.RetainName]
|
||||
public int compareTo(object obj)
|
||||
=> ((System.Collections.IComparer) this).Compare(this, obj);
|
||||
@ -26,6 +28,11 @@ namespace system.collections.generic
|
||||
[java.attr.AsInterface]
|
||||
public abstract class IComparer<T> : java.lang.Comparable, java.util.Comparator
|
||||
{
|
||||
// a generic variance field is created for this abstract class,
|
||||
// see also GenericUtil::CreateGenericVarianceField()
|
||||
|
||||
public abstract int Compare(T x, T y);
|
||||
|
||||
[java.attr.RetainName]
|
||||
public int compareTo(object obj)
|
||||
=> ((System.Collections.Generic.IComparer<T>) this).Compare((T) (object) this, (T) obj);
|
||||
|
@ -1,4 +1,6 @@
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
namespace system
|
||||
{
|
||||
|
||||
@ -6,9 +8,12 @@ namespace system
|
||||
|
||||
[System.Serializable]
|
||||
public abstract class Enum : system.ValueType, system.ValueMethod, System.IComparable,
|
||||
System.IFormattable //System.IConvertible
|
||||
System.IFormattable, System.IConvertible
|
||||
{
|
||||
|
||||
// warning, do not add fields in this class.
|
||||
// doing so will interfere with enumeration of constants.
|
||||
|
||||
//
|
||||
// getters and setters
|
||||
//
|
||||
@ -80,31 +85,105 @@ namespace system
|
||||
|
||||
|
||||
//
|
||||
// GetUnderlyingType
|
||||
// ToObject
|
||||
//
|
||||
|
||||
public static object ToObject(System.Type enumType, long value)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(enumType);
|
||||
if (! enumType.IsEnum)
|
||||
throw new System.ArgumentException();
|
||||
var enumRuntimeType = enumType as RuntimeType;
|
||||
if (enumRuntimeType == null)
|
||||
throw new System.ArgumentException();
|
||||
return Box(value, enumRuntimeType.JavaClassForArray());
|
||||
}
|
||||
|
||||
public static object ToObject(System.Type enumType, ulong value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, uint value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, int value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, ushort value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, short value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, char value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, byte value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, sbyte value)
|
||||
=> ToObject(enumType, (long) value);
|
||||
|
||||
public static object ToObject(System.Type enumType, bool value)
|
||||
=> ToObject(enumType, value ? 1L : 0L);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// HasFlag
|
||||
//
|
||||
|
||||
public bool HasFlag(Enum flag)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(flag);
|
||||
if (! this.GetType().IsEquivalentTo(flag.GetType()))
|
||||
throw new System.ArgumentException();
|
||||
var v = flag.GetLong();
|
||||
return (GetLong() & v) == v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// implemented via System.Type: GetUnderlyingType, GetTypeCode,
|
||||
// IsDefined, GetName, GetNames, GetValues
|
||||
//
|
||||
|
||||
public static System.Type GetUnderlyingType(System.Type enumType)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(enumType);
|
||||
return enumType.GetEnumUnderlyingType();
|
||||
#if false
|
||||
if (enumType.IsEnum && enumType is RuntimeType enumRuntimeType)
|
||||
{
|
||||
var fields = enumRuntimeType.JavaClassForArray().getDeclaredFields();
|
||||
if (fields.Length > 1)
|
||||
{
|
||||
var f = fields[0];
|
||||
if ((f.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0)
|
||||
{
|
||||
var fldType = system.RuntimeType.GetType(f.getType());
|
||||
var typeCode = (int) System.Type.GetTypeCode(fldType);
|
||||
if (typeCode >= 4 && typeCode <= 12)
|
||||
return fldType;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new System.ArgumentException();
|
||||
#endif
|
||||
}
|
||||
|
||||
public System.TypeCode GetTypeCode()
|
||||
{
|
||||
var typeCode = System.Type.GetTypeCode(GetType().GetEnumUnderlyingType());
|
||||
if ((int) typeCode >= 3 && (int) typeCode <= 12) // boolean .. uint64
|
||||
return typeCode;
|
||||
throw new System.InvalidOperationException();
|
||||
}
|
||||
|
||||
public static bool IsDefined(System.Type enumType, object value)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(enumType);
|
||||
return enumType.IsEnumDefined(value);
|
||||
}
|
||||
|
||||
public static string GetName(System.Type enumType, object value)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(enumType);
|
||||
return enumType.GetEnumName(value);
|
||||
}
|
||||
|
||||
public static string[] GetNames(System.Type enumType)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(enumType);
|
||||
return enumType.GetEnumNames();
|
||||
}
|
||||
|
||||
public static System.Array GetValues(System.Type enumType)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(enumType);
|
||||
return enumType.GetEnumValues();
|
||||
}
|
||||
|
||||
|
||||
@ -166,33 +245,21 @@ namespace system
|
||||
{
|
||||
if (format.Length == 1)
|
||||
{
|
||||
bool asFlags = false;
|
||||
switch (format[0])
|
||||
switch (Char.ToUpperInvariant(format[0]))
|
||||
{
|
||||
case 'f': case 'F':
|
||||
asFlags = true;
|
||||
goto case 'G';
|
||||
|
||||
case 'g': case 'G':
|
||||
if (! asFlags)
|
||||
{
|
||||
asFlags = ((java.lang.Class) typeof (EnumFlags))
|
||||
.isAssignableFrom(cls);
|
||||
}
|
||||
return FormatNames(cls, asFlags, value);
|
||||
|
||||
case 'd': case 'D':
|
||||
return java.lang.Long.toString(value);
|
||||
|
||||
case 'x': case 'X':
|
||||
return java.lang.Long.toHexString(value);
|
||||
}
|
||||
case 'F': return FormatNames(cls, value, true);
|
||||
case 'G': return FormatNames(cls, value,
|
||||
((java.lang.Class) typeof (EnumFlags))
|
||||
.isAssignableFrom(cls));
|
||||
case 'D': return java.lang.Long.toString(value);
|
||||
case 'X': return FormatHex(cls, value);
|
||||
};
|
||||
}
|
||||
throw new System.FormatException();
|
||||
|
||||
|
||||
|
||||
static string FormatNames(java.lang.Class cls, bool asFlags, long v)
|
||||
static string FormatNames(java.lang.Class cls, long v, bool asFlags)
|
||||
{
|
||||
var fields = cls.getDeclaredFields();
|
||||
int n = fields.Length;
|
||||
@ -252,10 +319,85 @@ namespace system
|
||||
|
||||
return (v == 0) ? sb.ToString() : null;
|
||||
}
|
||||
|
||||
static string FormatHex(java.lang.Class cls, long v)
|
||||
{
|
||||
var typeCode = System.Type.GetTypeCode(
|
||||
system.RuntimeType.GetType(cls).GetEnumUnderlyingType());
|
||||
var hexfmt = typeCode switch
|
||||
{
|
||||
System.TypeCode.Boolean => "%02X",
|
||||
System.TypeCode.Char => "%04X",
|
||||
System.TypeCode.SByte => "%02X",
|
||||
System.TypeCode.Byte => "%02X",
|
||||
System.TypeCode.Int16 => "%04X",
|
||||
System.TypeCode.UInt16 => "%04X",
|
||||
System.TypeCode.Int32 => "%08X",
|
||||
System.TypeCode.UInt32 => "%08X",
|
||||
System.TypeCode.Int64 => "%016X",
|
||||
System.TypeCode.UInt64 => "%016X",
|
||||
_ => throw new System.InvalidOperationException()
|
||||
};
|
||||
return java.lang.String.format(
|
||||
hexfmt, new object[] { java.lang.Long.valueOf(v) });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// IConvertible
|
||||
//
|
||||
|
||||
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
|
||||
=> System.Convert.ToBoolean(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
char System.IConvertible.ToChar(System.IFormatProvider provider)
|
||||
=> System.Convert.ToChar(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
sbyte System.IConvertible.ToSByte(System.IFormatProvider provider)
|
||||
=> System.Convert.ToSByte(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
byte System.IConvertible.ToByte(System.IFormatProvider provider)
|
||||
=> System.Convert.ToByte(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
short System.IConvertible.ToInt16(System.IFormatProvider provider)
|
||||
=> System.Convert.ToInt16(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
ushort System.IConvertible.ToUInt16(System.IFormatProvider provider)
|
||||
=> System.Convert.ToUInt16(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
int System.IConvertible.ToInt32(System.IFormatProvider provider)
|
||||
=> System.Convert.ToInt32(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
uint System.IConvertible.ToUInt32(System.IFormatProvider provider)
|
||||
=> System.Convert.ToUInt32(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
long System.IConvertible.ToInt64(System.IFormatProvider provider)
|
||||
=> System.Convert.ToInt64(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
ulong System.IConvertible.ToUInt64(System.IFormatProvider provider)
|
||||
=> System.Convert.ToUInt64(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
float System.IConvertible.ToSingle(System.IFormatProvider provider)
|
||||
=> System.Convert.ToSingle(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
double System.IConvertible.ToDouble(System.IFormatProvider provider)
|
||||
=> System.Convert.ToDouble(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
|
||||
=> System.Convert.ToDecimal(GetLong(), CultureInfo.CurrentCulture);
|
||||
|
||||
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
|
||||
=> throw new System.InvalidCastException();
|
||||
|
||||
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
|
||||
=> system.Convert.DefaultToType((System.IConvertible) this, type, provider);
|
||||
|
||||
//
|
||||
// value methods
|
||||
//
|
||||
|
||||
void ValueMethod.Clear() => SetLong(0L);
|
||||
void ValueMethod.CopyTo(ValueType into) => ((Enum) into).SetLong(GetLong());
|
||||
ValueType ValueMethod.Clone() => (ValueType) this.MemberwiseClone();
|
||||
|
@ -120,6 +120,12 @@ namespace system
|
||||
{
|
||||
if (genericObject.TryCast(castToType) != null)
|
||||
return obj;
|
||||
if (obj is system.Array.ProxySyncRoot objArray)
|
||||
{
|
||||
var proxy = Array.GetProxy(objArray.SyncRoot, castToType, false);
|
||||
if (proxy != null)
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -92,6 +92,9 @@ namespace system.globalization {
|
||||
|
||||
public virtual CompareInfo CompareInfo => CompareInfoRef;
|
||||
|
||||
public static CultureInfo CurrentCulture
|
||||
=> system.threading.Thread.CurrentThread.CurrentCulture;
|
||||
|
||||
public static CultureInfo InvariantCulture => s_InvariantCultureInfo;
|
||||
|
||||
public virtual object Clone() => throw new System.NotImplementedException();
|
||||
|
@ -3,6 +3,7 @@ namespace system
|
||||
{
|
||||
|
||||
public class Int16 : system.ValueType, system.ValueMethod,
|
||||
System.IComparable, System.IComparable<short>,
|
||||
System.IConvertible, System.IEquatable<short>, System.IFormattable
|
||||
{
|
||||
|
||||
@ -46,10 +47,32 @@ namespace system
|
||||
{
|
||||
if (string.IsNullOrEmpty(format))
|
||||
return ToString();
|
||||
return ParseNumbers.FormatNumber(
|
||||
(java.lang.String) (object) format, provider, java.lang.Integer.valueOf(Get()));
|
||||
return ParseNumbers.FormatNumber((java.lang.String) (object) format, provider,
|
||||
java.lang.Short.valueOf((short) Get()));
|
||||
}
|
||||
|
||||
public string ToString(string format) => ToString(format, null);
|
||||
|
||||
public string ToString(System.IFormatProvider provider) => ToString();
|
||||
|
||||
// System.IComparable
|
||||
public virtual int CompareTo(object obj)
|
||||
{
|
||||
if (object.ReferenceEquals(obj, null))
|
||||
return 1;
|
||||
if (obj is Int16 objInt16)
|
||||
return CompareTo((short) objInt16.Get());
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
|
||||
// System.IComparable<short>
|
||||
public int CompareTo(short b)
|
||||
{
|
||||
int a = Get();
|
||||
return (a < b ? -1 : a > b ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ValueMethod.Clear() => Set(0);
|
||||
@ -134,11 +157,9 @@ namespace system
|
||||
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
|
||||
=> System.Convert.ToDecimal(Get());
|
||||
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
|
||||
=> throw new System.InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo_Int32_DateTime"));
|
||||
string System.IConvertible.ToString(System.IFormatProvider provider)
|
||||
=> ToString();
|
||||
=> throw new System.InvalidCastException();
|
||||
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
|
||||
=> null;//System.Convert.DefaultToType((System.IConvertible) this, type, provider);
|
||||
=> system.Convert.DefaultToType((System.IConvertible) this, type, provider);
|
||||
|
||||
|
||||
|
||||
@ -171,7 +192,7 @@ namespace system
|
||||
|
||||
|
||||
#pragma warning disable 0659
|
||||
public class UInt16 : Int16, System.IEquatable<ushort>
|
||||
public class UInt16 : Int16, System.IComparable<ushort>, System.IEquatable<ushort>
|
||||
{
|
||||
|
||||
new public static UInt16 Box(int v) => new UInt16() { v = (short) v };
|
||||
@ -191,6 +212,17 @@ namespace system
|
||||
|
||||
public override System.TypeCode GetTypeCode() => System.TypeCode.UInt16;
|
||||
|
||||
// System.IComparable
|
||||
public override int CompareTo(object obj)
|
||||
{
|
||||
if (object.ReferenceEquals(obj, null))
|
||||
return 1;
|
||||
if (obj is UInt16 objUInt16)
|
||||
return CompareTo((ushort) objUInt16.Get());
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
|
||||
// System.IComparable<ushort>
|
||||
public int CompareTo(ushort v) => CompareTo((short) Get(), (short) v);
|
||||
|
||||
public static int CompareTo(short a, short b)
|
||||
|
@ -3,6 +3,7 @@ namespace system
|
||||
{
|
||||
|
||||
public class Int32 : system.ValueType, system.ValueMethod,
|
||||
System.IComparable, System.IComparable<int>,
|
||||
System.IConvertible, System.IEquatable<int>, System.IFormattable
|
||||
{
|
||||
|
||||
@ -49,14 +50,31 @@ namespace system
|
||||
{
|
||||
if (string.IsNullOrEmpty(format))
|
||||
return ToString();
|
||||
return ParseNumbers.FormatNumber(
|
||||
(java.lang.String) (object) format, provider, java.lang.Integer.valueOf(Get()));
|
||||
return ParseNumbers.FormatNumber((java.lang.String) (object) format, provider,
|
||||
java.lang.Integer.valueOf(Get()));
|
||||
}
|
||||
|
||||
public string ToString(string format) => ToString(format, null);
|
||||
|
||||
public string ToString(System.IFormatProvider provider) => ToString();
|
||||
|
||||
// System.IComparable
|
||||
public virtual int CompareTo(object obj)
|
||||
{
|
||||
if (object.ReferenceEquals(obj, null))
|
||||
return 1;
|
||||
if (obj is Int32 objInt32)
|
||||
return CompareTo((int) objInt32.Get());
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
|
||||
// System.IComparable<int>
|
||||
public int CompareTo(int b)
|
||||
{
|
||||
int a = Get();
|
||||
return (a < b ? -1 : a > b ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int OverflowAdd(int a, int b)
|
||||
@ -189,11 +207,9 @@ namespace system
|
||||
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
|
||||
=> System.Convert.ToDecimal(Get());
|
||||
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
|
||||
=> throw new System.InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo_Int32_DateTime"));
|
||||
string System.IConvertible.ToString(System.IFormatProvider provider)
|
||||
=> ToString();
|
||||
=> throw new System.InvalidCastException();
|
||||
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
|
||||
=> null;//System.Convert.DefaultToType((System.IConvertible) this, type, provider);
|
||||
=> system.Convert.DefaultToType((System.IConvertible) this, type, provider);
|
||||
|
||||
|
||||
|
||||
@ -231,7 +247,7 @@ namespace system
|
||||
|
||||
|
||||
#pragma warning disable 0659
|
||||
public class UInt32 : Int32, System.IEquatable<uint>
|
||||
public class UInt32 : Int32, System.IComparable<uint>, System.IEquatable<uint>
|
||||
{
|
||||
|
||||
new public static UInt32 Box(int v) => new UInt32() { v = v };
|
||||
@ -254,8 +270,17 @@ namespace system
|
||||
|
||||
public override System.TypeCode GetTypeCode() => System.TypeCode.UInt32;
|
||||
|
||||
//public int CompareTo(uint v) => java.lang.Integer.compareUnsigned(Get(), (int) v);
|
||||
// System.IComparable
|
||||
public override int CompareTo(object obj)
|
||||
{
|
||||
if (object.ReferenceEquals(obj, null))
|
||||
return 1;
|
||||
if (obj is UInt32 objUInt32)
|
||||
return CompareTo((uint) objUInt32.Get());
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
|
||||
// System.IComparable<uint>
|
||||
public int CompareTo(uint v) => CompareTo(Get(), (int) v);
|
||||
|
||||
public static int CompareTo(int a, int b)
|
||||
|
@ -2,7 +2,8 @@
|
||||
namespace system
|
||||
{
|
||||
|
||||
public class Int64 : system.ValueType, system.ValueMethod, java.lang.Cloneable
|
||||
public class Int64 : system.ValueType, system.ValueMethod,
|
||||
System.IConvertible, System.IEquatable<long>, System.IFormattable
|
||||
{
|
||||
|
||||
[java.attr.RetainType] protected long v;
|
||||
@ -23,6 +24,9 @@ namespace system
|
||||
public static void Set(long v, Int64 o) => o.Set(v);
|
||||
public static void VolatileSet(long v, Int64 o) => o.VolatileSet(v);
|
||||
|
||||
public virtual bool CompareAndSwap(long expect, long update) =>
|
||||
Util.JavaUnsafe.compareAndSwapLong(this, ValueOffset, expect, update);
|
||||
|
||||
|
||||
|
||||
public override bool Equals(object obj)
|
||||
@ -37,11 +41,28 @@ namespace system
|
||||
return ((int) v) ^ (int) (v >> 32);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
public override string ToString() => java.lang.Long.toString(Get());
|
||||
|
||||
|
||||
|
||||
// System.IEquatable<long>
|
||||
public bool Equals(long v) => v == Get();
|
||||
|
||||
// System.IFormattable
|
||||
public string ToString(string format, System.IFormatProvider provider)
|
||||
{
|
||||
return java.lang.Long.toString(Get());
|
||||
if (string.IsNullOrEmpty(format))
|
||||
return ToString();
|
||||
return ParseNumbers.FormatNumber((java.lang.String) (object) format, provider,
|
||||
java.lang.Long.valueOf(Get()));
|
||||
}
|
||||
|
||||
public string ToString(string format) => ToString(format, null);
|
||||
|
||||
public string ToString(System.IFormatProvider provider) => ToString();
|
||||
|
||||
|
||||
|
||||
public static long OverflowAdd(long a, long b)
|
||||
{
|
||||
long c = a + b;
|
||||
@ -123,6 +144,47 @@ namespace system
|
||||
|
||||
|
||||
|
||||
//
|
||||
// IConvertible
|
||||
//
|
||||
|
||||
|
||||
|
||||
public virtual System.TypeCode GetTypeCode() => System.TypeCode.Int64;
|
||||
|
||||
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
|
||||
=> System.Convert.ToBoolean(Get());
|
||||
char System.IConvertible.ToChar(System.IFormatProvider provider)
|
||||
=> System.Convert.ToChar(Get());
|
||||
sbyte System.IConvertible.ToSByte(System.IFormatProvider provider)
|
||||
=> System.Convert.ToSByte(Get());
|
||||
byte System.IConvertible.ToByte(System.IFormatProvider provider)
|
||||
=> System.Convert.ToByte(Get());
|
||||
short System.IConvertible.ToInt16(System.IFormatProvider provider)
|
||||
=> System.Convert.ToInt16(Get());
|
||||
ushort System.IConvertible.ToUInt16(System.IFormatProvider provider)
|
||||
=> System.Convert.ToUInt16(Get());
|
||||
int System.IConvertible.ToInt32(System.IFormatProvider provider)
|
||||
=> System.Convert.ToInt32(Get());
|
||||
uint System.IConvertible.ToUInt32(System.IFormatProvider provider)
|
||||
=> System.Convert.ToUInt32(Get());
|
||||
long System.IConvertible.ToInt64(System.IFormatProvider provider)
|
||||
=> System.Convert.ToInt64(Get());
|
||||
ulong System.IConvertible.ToUInt64(System.IFormatProvider provider)
|
||||
=> System.Convert.ToUInt64(Get());
|
||||
float System.IConvertible.ToSingle(System.IFormatProvider provider)
|
||||
=> System.Convert.ToSingle(Get());
|
||||
double System.IConvertible.ToDouble(System.IFormatProvider provider)
|
||||
=> System.Convert.ToDouble(Get());
|
||||
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
|
||||
=> System.Convert.ToDecimal(Get());
|
||||
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
|
||||
=> throw new System.InvalidCastException();
|
||||
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
|
||||
=> system.Convert.DefaultToType((System.IConvertible) this, type, provider);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// InArray
|
||||
//
|
||||
@ -147,6 +209,9 @@ namespace system
|
||||
public override void Set(long v) => a[i] = v;
|
||||
public override void VolatileSet(long v) =>
|
||||
Util.JavaUnsafe.putLongVolatile(a, Util.ElementOffset64(i), v);
|
||||
|
||||
public override bool CompareAndSwap(long expect, long update) =>
|
||||
Util.JavaUnsafe.compareAndSwapLong(a, Util.ElementOffset64(i), expect, update);
|
||||
}
|
||||
|
||||
}
|
||||
@ -167,7 +232,7 @@ namespace system
|
||||
|
||||
|
||||
#pragma warning disable 0659
|
||||
public class UInt64 : Int64
|
||||
public class UInt64 : Int64, System.IEquatable<ulong>
|
||||
{
|
||||
|
||||
new public static UInt64 Box(long v) => new UInt64() { v = v };
|
||||
@ -176,12 +241,20 @@ namespace system
|
||||
public static void Set(long v, UInt64 o) => o.Set(v);
|
||||
public static void VolatileSet(long v, UInt64 o) => o.VolatileSet(v);
|
||||
|
||||
public override bool CompareAndSwap(long expect, long update) =>
|
||||
throw new System.NotSupportedException();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var objUInt64 = obj as UInt64;
|
||||
return (objUInt64 != null && objUInt64.Get() == Get());
|
||||
}
|
||||
|
||||
// System.IEquatable<ulong>
|
||||
public bool Equals(ulong v) => v == (ulong) Get();
|
||||
|
||||
public override System.TypeCode GetTypeCode() => System.TypeCode.UInt64;
|
||||
|
||||
//public int CompareTo(ulong v) => java.lang.Long.compareUnsigned(Get(), (long) v);
|
||||
|
||||
public int CompareTo(ulong v) => CompareTo(Get(), (long) v);
|
||||
|
@ -14,6 +14,10 @@ namespace system.reflection
|
||||
MemberTypes memberType,
|
||||
System.Predicate<java.lang.reflect.AccessibleObject> callback)
|
||||
{
|
||||
//
|
||||
// calculate modifier AND mask and result for matches
|
||||
//
|
||||
|
||||
int modifierMask = 0;
|
||||
int modifierValue = 0;
|
||||
|
||||
@ -43,6 +47,10 @@ namespace system.reflection
|
||||
}
|
||||
bindingAttr &= ~chk;
|
||||
|
||||
//
|
||||
// check if iteration is required on base hierarchy
|
||||
//
|
||||
|
||||
RuntimeType stopAtType = null;
|
||||
if ((bindingAttr & BindingFlags.DeclaredOnly) != 0)
|
||||
{
|
||||
@ -50,6 +58,10 @@ namespace system.reflection
|
||||
bindingAttr &= ~BindingFlags.DeclaredOnly;
|
||||
}
|
||||
|
||||
//
|
||||
// run iteration
|
||||
//
|
||||
|
||||
if (bindingAttr != 0)
|
||||
{
|
||||
throw new System.PlatformNotSupportedException(
|
||||
|
@ -25,7 +25,7 @@ namespace system.reflection
|
||||
}
|
||||
|
||||
//
|
||||
// GetFields (called by system.RuntimeType.GetFields(GetFields)
|
||||
// GetFields (called by system.RuntimeType.GetFields()
|
||||
//
|
||||
|
||||
public static FieldInfo[] GetFields(BindingFlags bindingAttr, RuntimeType initialType)
|
||||
@ -35,8 +35,9 @@ namespace system.reflection
|
||||
BindingFlagsIterator.Run(bindingAttr, initialType, MemberTypes.Field,
|
||||
(javaAccessibleObject) =>
|
||||
{
|
||||
list.Add(new RuntimeFieldInfo((java.lang.reflect.Field) javaAccessibleObject,
|
||||
initialType));
|
||||
var javaField = (java.lang.reflect.Field) javaAccessibleObject;
|
||||
javaField.setAccessible(true);
|
||||
list.Add(new RuntimeFieldInfo(javaField, initialType));
|
||||
return true;
|
||||
});
|
||||
|
||||
@ -66,8 +67,35 @@ namespace system.reflection
|
||||
public override System.Type ReflectedType
|
||||
=> throw new PlatformNotSupportedException();
|
||||
|
||||
public override string Name
|
||||
=> throw new PlatformNotSupportedException();
|
||||
public override string Name => JavaField.getName();
|
||||
|
||||
public override object GetRawConstantValue()
|
||||
{
|
||||
if ((JavaField.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
|
||||
{
|
||||
var value = JavaField.get(null);
|
||||
switch (value)
|
||||
{
|
||||
case java.lang.Boolean boolBox:
|
||||
return system.Boolean.Box(boolBox.booleanValue() ? 1 : 0);
|
||||
case java.lang.Byte byteBox:
|
||||
return system.SByte.Box(byteBox.byteValue());
|
||||
case java.lang.Character charBox:
|
||||
return system.Char.Box(charBox.charValue());
|
||||
case java.lang.Short shortBox:
|
||||
return system.Int16.Box(shortBox.shortValue());
|
||||
case java.lang.Integer intBox:
|
||||
return system.Int32.Box(intBox.intValue());
|
||||
case java.lang.Long longBox:
|
||||
return system.Int64.Box(longBox.longValue());
|
||||
case java.lang.Float floatBox:
|
||||
return system.Single.Box(floatBox.floatValue());
|
||||
case java.lang.Double doubleBox:
|
||||
return system.Double.Box(doubleBox.doubleValue());
|
||||
}
|
||||
}
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public override System.RuntimeFieldHandle FieldHandle
|
||||
=> throw new PlatformNotSupportedException();
|
||||
|
@ -52,92 +52,42 @@ namespace system.reflection
|
||||
// calculate modifier AND mask and result for matches
|
||||
//
|
||||
|
||||
int modifierMask = 0;
|
||||
int modifierValue = 0;
|
||||
RuntimeMethodInfo foundMethod = null;
|
||||
|
||||
BindingFlags chk = bindingAttr & (BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (chk != (BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
if (chk == 0) // if neither, no methods will match
|
||||
return null;
|
||||
// methods with internal access are converted to public access,
|
||||
// so we cannot honor the distinction between Public and NonPublic
|
||||
/*
|
||||
modifierMask |= java.lang.reflect.Modifier.PUBLIC;
|
||||
if (chk == BindingFlags.Public)
|
||||
modifierValue |= java.lang.reflect.Modifier.PUBLIC;
|
||||
*/
|
||||
bindingAttr &= ~chk;
|
||||
}
|
||||
|
||||
chk = bindingAttr & (BindingFlags.Static | BindingFlags.Instance);
|
||||
if (chk != (BindingFlags.Static | BindingFlags.Instance))
|
||||
{
|
||||
if (chk == 0) // if neither, no methods will match
|
||||
return null;
|
||||
modifierMask |= java.lang.reflect.Modifier.STATIC;
|
||||
if (chk == BindingFlags.Static)
|
||||
modifierValue |= java.lang.reflect.Modifier.STATIC;
|
||||
bindingAttr &= ~chk;
|
||||
}
|
||||
|
||||
RuntimeType stopAtType = null;
|
||||
if ((bindingAttr & BindingFlags.DeclaredOnly) != 0)
|
||||
{
|
||||
stopAtType = initialType;
|
||||
bindingAttr &= ~BindingFlags.DeclaredOnly;
|
||||
}
|
||||
|
||||
if (bindingAttr != 0)
|
||||
throw new PlatformNotSupportedException("bad binding flags " + bindingAttr);
|
||||
|
||||
//
|
||||
// collect methods from class and base classes
|
||||
//
|
||||
|
||||
var currentType = initialType;
|
||||
for (;;)
|
||||
BindingFlagsIterator.Run(bindingAttr, initialType, MemberTypes.Method,
|
||||
(javaAccessibleObject) =>
|
||||
{
|
||||
#pragma warning disable 0436
|
||||
java.lang.reflect.Method[] javaMethods =
|
||||
(java.lang.reflect.Method[]) (object)
|
||||
currentType.JavaClassForArray().getDeclaredMethods();
|
||||
var javaMethod = (java.lang.reflect.Method) javaAccessibleObject;
|
||||
#pragma warning restore 0436
|
||||
|
||||
foreach (var javaMethod in javaMethods)
|
||||
{
|
||||
int jmodifiers = javaMethod.getModifiers();
|
||||
if ((jmodifiers & modifierMask) == modifierValue)
|
||||
{
|
||||
string originalName = javaMethod.getName();
|
||||
// note the actual suffix character below is configured
|
||||
// in CilMain.cs, with special considerations for Android.
|
||||
// we list all possible characters here, just in case.
|
||||
int idx = originalName.IndexOf('\u00AB'); // U+00AB Left-Pointing Double Angle Quotation Mark
|
||||
if (idx == -1)
|
||||
idx = originalName.IndexOf('\u00A1'); // U+00A1 Inverted Exclamation Mark
|
||||
if (idx == -1)
|
||||
idx = originalName.IndexOf('(');
|
||||
if (idx == -1)
|
||||
idx = originalName.IndexOf('!');
|
||||
var compareName =
|
||||
(idx == -1) ? originalName : originalName.Substring(0, idx);
|
||||
string originalName = javaMethod.getName();
|
||||
// note the actual suffix character below is configured
|
||||
// in CilMain.cs, with special considerations for Android.
|
||||
// we list all possible characters here, just in case.
|
||||
int idx = originalName.IndexOf('\u00AB'); // U+00AB Left-Pointing Double Angle Quotation Mark
|
||||
if (idx == -1)
|
||||
idx = originalName.IndexOf('\u00A1'); // U+00A1 Inverted Exclamation Mark
|
||||
if (idx == -1)
|
||||
idx = originalName.IndexOf('(');
|
||||
if (idx == -1)
|
||||
idx = originalName.IndexOf('!');
|
||||
var compareName =
|
||||
(idx == -1) ? originalName : originalName.Substring(0, idx);
|
||||
|
||||
if (name == compareName)
|
||||
{
|
||||
javaMethod.setAccessible(true);
|
||||
return new RuntimeMethodInfo(javaMethod, jmodifiers, initialType,
|
||||
originalName, compareName);
|
||||
}
|
||||
}
|
||||
if (name == compareName)
|
||||
{
|
||||
javaMethod.setAccessible(true);
|
||||
var jmodifiers = javaMethod.getModifiers();
|
||||
foundMethod = new RuntimeMethodInfo(javaMethod, jmodifiers, initialType,
|
||||
originalName, compareName);
|
||||
return false; // stop iteration
|
||||
}
|
||||
|
||||
currentType = (system.RuntimeType) currentType.BaseType;
|
||||
if (currentType == stopAtType)
|
||||
break;
|
||||
}
|
||||
return true; // continue iteration
|
||||
});
|
||||
|
||||
return null;
|
||||
return foundMethod;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -4,6 +4,8 @@ using System.Runtime.InteropServices;
|
||||
namespace system.reflection
|
||||
{
|
||||
|
||||
public abstract class Module { }
|
||||
|
||||
public sealed class RuntimeModule
|
||||
{
|
||||
|
||||
|
@ -1433,6 +1433,54 @@ namespace system
|
||||
|
||||
|
||||
|
||||
#pragma warning disable 0436
|
||||
public override System.Array GetEnumValues()
|
||||
{
|
||||
// the default implementation of System.Type::GetEnumValues()
|
||||
// throws NotImplementedException, so we have to use reflection
|
||||
// to invoke the underlying private method that does the work
|
||||
|
||||
if (! IsEnum)
|
||||
throw new ArgumentException();
|
||||
|
||||
// the default implementation of System.Type::GetEnumValues()
|
||||
// throws NotImplementedException, so we have to use reflection
|
||||
// to invoke the underlying private method that does the work
|
||||
|
||||
if (GetEnumRawConstantValues == null)
|
||||
{
|
||||
var searchClass = (java.lang.Class) typeof(System.Type);
|
||||
var modifierMask = java.lang.reflect.Modifier.PRIVATE
|
||||
| java.lang.reflect.Modifier.FINAL
|
||||
| java.lang.reflect.Modifier.STATIC;
|
||||
var modifierValue = java.lang.reflect.Modifier.PRIVATE
|
||||
| java.lang.reflect.Modifier.FINAL;
|
||||
|
||||
foreach (java.lang.reflect.Method method in
|
||||
(java.lang.reflect.Method[]) (object) searchClass.getDeclaredMethods())
|
||||
{
|
||||
if ( (method.getModifiers() & modifierMask) == modifierValue
|
||||
&& method.getParameterTypes().Length == 0
|
||||
&& method.getReturnType() == (java.lang.Class) typeof(System.Array))
|
||||
{
|
||||
method.setAccessible(true);
|
||||
GetEnumRawConstantValues = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetEnumRawConstantValues != null)
|
||||
{
|
||||
return (System.Array) GetEnumRawConstantValues.invoke(this, null);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
[java.attr.RetainType] private static java.lang.reflect.Method GetEnumRawConstantValues;
|
||||
#pragma warning restore 0436
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Reflection on members of the type
|
||||
//
|
||||
@ -1531,8 +1579,6 @@ namespace system
|
||||
public virtual int GenericParameterPosition
|
||||
public virtual Type[] GetGenericParameterConstraints()
|
||||
|
||||
public virtual Array GetEnumValues()
|
||||
|
||||
internal virtual string FormatTypeName(bool serialization)
|
||||
public virtual InterfaceMapping GetInterfaceMap(Type interfaceType)
|
||||
*/
|
||||
|
@ -46,7 +46,11 @@ namespace system
|
||||
|
||||
count = count >> shift;
|
||||
this.array.Set(array = java.lang.reflect.Array.newInstance(cls, count));
|
||||
|
||||
if (! cls.isPrimitive())
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
java.lang.reflect.Array.set(array, i, cls.newInstance());
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
@ -63,22 +67,14 @@ namespace system
|
||||
}
|
||||
|
||||
[java.attr.RetainName]
|
||||
public static Span<object> Localloc(long bytes)
|
||||
public static Span<ValueType> Localloc(long bytes)
|
||||
{
|
||||
// this helper method is invoked by code which uses the 'localloc'
|
||||
// instruction. see also CodeSpan::Localloc method.
|
||||
int intBytes = (int) bytes;
|
||||
if (intBytes != bytes)
|
||||
throw new System.ArgumentOutOfRangeException();
|
||||
return new Span<object>() { array = new Reference(), count = intBytes };
|
||||
}
|
||||
|
||||
[java.attr.RetainName]
|
||||
public static Span<char> String(java.lang.String str)
|
||||
{
|
||||
// this helper method is invoked by code which stores a string
|
||||
// variable into a pointer. see also CodeSpan::Address method.
|
||||
return new Span<char>(str.toCharArray()) { count = System.SByte.MinValue };
|
||||
return new Span<ValueType>() { array = new Reference(), count = intBytes };
|
||||
}
|
||||
|
||||
[java.attr.RetainName]
|
||||
@ -115,6 +111,21 @@ namespace system
|
||||
return system.Array.Box(Array(null), start);
|
||||
}
|
||||
|
||||
//
|
||||
// Assign
|
||||
//
|
||||
// this helper method is invoked by code which stores an address into
|
||||
// a pointer. see also CodeSpan::Address method.
|
||||
//
|
||||
|
||||
[java.attr.RetainName]
|
||||
public static Span<char> Assign(java.lang.String str)
|
||||
=> new Span<char>(str.toCharArray()) { count = System.SByte.MinValue };
|
||||
|
||||
[java.attr.RetainName]
|
||||
public static System.ValueType Assign(ValueType source)
|
||||
=> new Span<T>((T[]) (object) (new ValueType[1] { source }));
|
||||
|
||||
//
|
||||
// helper methods to access a span of a primitive type.
|
||||
// see also CodeSpan::LoadStore method.
|
||||
@ -150,8 +161,24 @@ namespace system
|
||||
public double LoadD() => ((double[]) Array(java.lang.Double.TYPE))[start];
|
||||
public void StoreD(double value) => ((double[]) Array(java.lang.Double.TYPE))[start] = value;
|
||||
|
||||
public object Load() => ((object[]) Array((java.lang.Class) typeof(object)))[start];
|
||||
public void Store(object value) => ((object[]) Array((java.lang.Class) typeof(object)))[start] = value;
|
||||
//
|
||||
// helper methods to access a span of a value type.
|
||||
// see also CodeSpan::LoadStore method.
|
||||
//
|
||||
|
||||
public system.ValueType Load(java.lang.Class cls)
|
||||
=> (system.ValueType) java.lang.reflect.Array.get(Array(cls), start);
|
||||
|
||||
public void Store(ValueType value, java.lang.Class cls)
|
||||
=> ((ValueMethod) value).CopyTo(Load(cls));
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (this.array != null && this.array.Get() != null)
|
||||
{
|
||||
((ValueMethod) Load(null)).Clear();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// System.Span methods
|
||||
|
@ -91,4 +91,14 @@ namespace system
|
||||
ValueType Clone();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[java.attr.Discard] // discard in output
|
||||
public static class Convert
|
||||
{
|
||||
// called by various implementations of System.IConvertible.ToType
|
||||
[java.attr.Discard] extern public static object DefaultToType(
|
||||
System.IConvertible value, System.Type targetType, System.IFormatProvider provider);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -110,6 +110,20 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
|
||||
|
||||
internal static void MakeRoomForCategory2ValueOnStack(JavaCode code)
|
||||
{
|
||||
// ensure the stack has enough space for a category-2 value
|
||||
if (code.StackMap != null)
|
||||
{
|
||||
code.StackMap.PushStack(JavaType.IntegerType);
|
||||
code.StackMap.PushStack(JavaType.LongType);
|
||||
code.StackMap.PopStack(CilMain.Where);
|
||||
code.StackMap.PopStack(CilMain.Where);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static List<JavaClass> Import(List<TypeDefinition> cilTypes)
|
||||
{
|
||||
if (_Where != null)
|
||||
|
@ -160,7 +160,7 @@ namespace SpaceFlint.CilToJava
|
||||
if (defType.HasFields && numGeneric == 0)
|
||||
{
|
||||
var type = From(defType.Fields[0].FieldType);
|
||||
if ((! type.IsReference) && type.PrimitiveType >= TypeCode.SByte
|
||||
if ((! type.IsReference) && type.PrimitiveType >= TypeCode.Boolean
|
||||
&& type.PrimitiveType <= TypeCode.UInt64)
|
||||
{
|
||||
JavaName = ImportName(defType, 0);
|
||||
@ -733,10 +733,14 @@ namespace SpaceFlint.CilToJava
|
||||
private string VolatileName(string nm, bool isVolatile)
|
||||
=> ((UnboxedType.IsVolatile || isVolatile) ? ("Volatile" + nm) : nm);
|
||||
|
||||
public virtual void GetValue(JavaCode code, bool isVolatile = false) =>
|
||||
public virtual void GetValue(JavaCode code, bool isVolatile = false)
|
||||
{
|
||||
code.NewInstruction(0xB6 /* invokevirtual */, ThisOrEnum,
|
||||
new JavaMethodRef(VolatileName("Get", isVolatile),
|
||||
UnboxedTypeInMethod));
|
||||
if (UnboxedTypeInMethod.Category == 2)
|
||||
CilMain.MakeRoomForCategory2ValueOnStack(code);
|
||||
}
|
||||
|
||||
public virtual void SetValueOV(JavaCode code, bool isVolatile = false) =>
|
||||
code.NewInstruction(0xB6 /* invokevirtual */, ThisOrEnum,
|
||||
@ -783,6 +787,8 @@ namespace SpaceFlint.CilToJava
|
||||
var innerOrEnum = GetInnerObject(code);
|
||||
code.NewInstruction(0xB6 /* invokevirtual */, innerOrEnum,
|
||||
new JavaMethodRef("Get", UnboxedTypeInMethod));
|
||||
if (UnboxedTypeInMethod.Category == 2)
|
||||
CilMain.MakeRoomForCategory2ValueOnStack(code);
|
||||
}
|
||||
|
||||
public override void SetValueOV(JavaCode code, bool isVolatile = false)
|
||||
|
@ -521,8 +521,7 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
|
||||
|
||||
public static bool MaybeGetProxy(CilType fromType, CilType intoType,
|
||||
JavaCode code, bool pushFromType = false)
|
||||
public static bool MaybeGetProxy(CilType fromType, CilType intoType, JavaCode code)
|
||||
{
|
||||
if ( fromType.IsArray
|
||||
|| object.ReferenceEquals(fromType, GenericArrayType)
|
||||
|
@ -237,7 +237,7 @@ namespace SpaceFlint.CilToJava
|
||||
}
|
||||
else
|
||||
{
|
||||
return TestGtLt(code, stackTop,
|
||||
return TestGtLt(code, stackTop, stackTop2,
|
||||
/* if greater than */ ( cilOp == Code.Bgt
|
||||
/* (vs less than) */ || cilOp == Code.Bgt_S
|
||||
|| cilOp == Code.Bgt_Un
|
||||
@ -286,7 +286,7 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
byte op = (cilOp == Code.Ceq)
|
||||
? TestEq(code, stackTop, stackTop2, cilInst)
|
||||
: TestGtLt(code, stackTop,
|
||||
: TestGtLt(code, stackTop, stackTop2,
|
||||
/* if greater than */ ( cilOp == Code.Cgt
|
||||
/* (vs less than) */ || cilOp == Code.Cgt_Un),
|
||||
/* if unsigned */ ( cilOp == Code.Cgt_Un
|
||||
@ -326,7 +326,7 @@ namespace SpaceFlint.CilToJava
|
||||
{
|
||||
if (stackTop.IsReference || stackTop2.IsReference)
|
||||
{
|
||||
CodeSpan.Compare(stackTop, stackTop2, cilInst, code);
|
||||
CodeSpan.CompareEq(stackTop, stackTop2, cilInst, code);
|
||||
return 0xA5; // if_acmpeq (reference)
|
||||
}
|
||||
|
||||
@ -373,7 +373,8 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
|
||||
|
||||
static byte TestGtLt(JavaCode code, JavaType stackTop, bool greater, bool unsigned_unordered)
|
||||
static byte TestGtLt(JavaCode code, JavaType stackTop, JavaType stackTop2,
|
||||
bool greater, bool unsigned_unordered)
|
||||
{
|
||||
byte op;
|
||||
|
||||
@ -444,7 +445,15 @@ namespace SpaceFlint.CilToJava
|
||||
return 0xA6; // if_acmpne
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CodeSpan.CompareGtLt(stackTop, stackTop2, code))
|
||||
{
|
||||
return (byte) (greater ? 0x9D // ifgt
|
||||
: 0x9B); // iflt
|
||||
}
|
||||
|
||||
throw new InvalidProgramException();
|
||||
}
|
||||
|
||||
if (typeBits != 0)
|
||||
typeName = "UInt" + typeBits.ToString();
|
||||
|
@ -140,7 +140,7 @@ namespace SpaceFlint.CilToJava
|
||||
var dataType = CilType.From(typeRef);
|
||||
var fromType = (CilType) code.StackMap.PopStack(CilMain.Where);
|
||||
|
||||
if (CodeSpan.LoadStore(true, fromType, null, code))
|
||||
if (CodeSpan.LoadStore(true, fromType, null, dataType, code))
|
||||
return;
|
||||
|
||||
if ( (! dataType.IsReference) && cilOp == Code.Ldobj
|
||||
@ -265,14 +265,15 @@ namespace SpaceFlint.CilToJava
|
||||
{
|
||||
if (data is TypeReference typeRef)
|
||||
{
|
||||
var dataType = CilType.From(typeRef);
|
||||
|
||||
var stackTop1 = (CilType) code.StackMap.PopStack(CilMain.Where);
|
||||
var stackTop2 = (CilType) code.StackMap.PopStack(CilMain.Where);
|
||||
if (CodeSpan.LoadStore(false, stackTop2, null, code))
|
||||
if (CodeSpan.LoadStore(false, stackTop2, null, dataType, code))
|
||||
return;
|
||||
code.StackMap.PushStack(stackTop2);
|
||||
code.StackMap.PushStack(stackTop1);
|
||||
|
||||
var dataType = CilType.From(typeRef);
|
||||
GenericUtil.ValueCopy(dataType, code, true);
|
||||
code.StackMap.PopStack(CilMain.Where);
|
||||
code.StackMap.PopStack(CilMain.Where);
|
||||
@ -290,6 +291,9 @@ namespace SpaceFlint.CilToJava
|
||||
var dataType = CilType.From(typeRef);
|
||||
var fromType = code.StackMap.PopStack(CilMain.Where);
|
||||
|
||||
if (CodeSpan.Clear(fromType, dataType, code))
|
||||
return;
|
||||
|
||||
if ( dataType.IsGenericParameter
|
||||
|| (dataType.IsValueClass && dataType.Equals(fromType)))
|
||||
{
|
||||
|
@ -89,7 +89,10 @@ namespace SpaceFlint.CilToJava
|
||||
return 0x00; // nop
|
||||
|
||||
if (oldType == TypeCode.Single)
|
||||
{
|
||||
CilMain.MakeRoomForCategory2ValueOnStack(code);
|
||||
return 0x8D; // f2d
|
||||
}
|
||||
|
||||
if (oldType == TypeCode.Int64)
|
||||
return 0x8A; // l2d
|
||||
@ -113,6 +116,8 @@ namespace SpaceFlint.CilToJava
|
||||
bool fromInt32 = (oldType != TypeCode.Int64 && oldType != TypeCode.UInt64);
|
||||
if (fromInt32)
|
||||
{
|
||||
CilMain.MakeRoomForCategory2ValueOnStack(code);
|
||||
|
||||
code.NewInstruction(0x85 /* i2l */, null, null);
|
||||
code.StackMap.PushStack(JavaType.LongType);
|
||||
|
||||
@ -176,6 +181,7 @@ namespace SpaceFlint.CilToJava
|
||||
return 0x7F; // land
|
||||
}
|
||||
|
||||
CilMain.MakeRoomForCategory2ValueOnStack(code);
|
||||
return 0x85; // i2l
|
||||
}
|
||||
|
||||
@ -285,6 +291,8 @@ namespace SpaceFlint.CilToJava
|
||||
public static void Calculation(JavaCode code, Code cilOp)
|
||||
{
|
||||
var stackTop1 = code.StackMap.PopStack(CilMain.Where);
|
||||
if (cilOp == Code.Sub && CodeSpan.SubOffset(stackTop1, code))
|
||||
return;
|
||||
var type1 = GetNumericTypeCode(stackTop1);
|
||||
|
||||
if (cilOp == Code.Not)
|
||||
@ -300,7 +308,7 @@ namespace SpaceFlint.CilToJava
|
||||
else
|
||||
{
|
||||
var stackTop2 = code.StackMap.PopStack(CilMain.Where);
|
||||
if (CodeSpan.AddOffset(stackTop1, stackTop2, code))
|
||||
if (cilOp == Code.Add && CodeSpan.AddOffset(stackTop1, stackTop2, code))
|
||||
return;
|
||||
|
||||
char kind;
|
||||
@ -547,7 +555,7 @@ namespace SpaceFlint.CilToJava
|
||||
var boxedType = stackTop as BoxedType;
|
||||
if (boxedType == null || boxedType.IsBoxedReference != isRef)
|
||||
{
|
||||
if (CodeSpan.LoadStore(isLoad, stackTop, opcodeType, code))
|
||||
if (CodeSpan.LoadStore(isLoad, stackTop, opcodeType, null, code))
|
||||
return;
|
||||
|
||||
if (object.ReferenceEquals(stackTop, CodeArrays.GenericArrayType))
|
||||
@ -590,7 +598,13 @@ namespace SpaceFlint.CilToJava
|
||||
code.StackMap.PushStack(unboxedType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are storing a real array into a boxed reference of
|
||||
// e.g., system.Array, then we have to create an array proxy
|
||||
CodeArrays.MaybeGetProxy(CodeArrays.GenericArrayType, unboxedType, code);
|
||||
|
||||
boxedType.SetValueOV(code);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,46 @@ namespace SpaceFlint.CilToJava
|
||||
}
|
||||
|
||||
|
||||
public static bool SubOffset(JavaType secondType, JavaCode code)
|
||||
{
|
||||
// make sure the first operand is a pointer span, not a real Span<T>
|
||||
var spanType1 = (CilType) code.StackMap.PopStack(CilMain.Where);
|
||||
if ( (! spanType1.HasGenericParameters)
|
||||
&& spanType1.GenericParameters != null
|
||||
&& spanType1.GenericParameters[0] is CilType span1PointerType
|
||||
&& (! span1PointerType.IsGenericParameter))
|
||||
{
|
||||
var spanType2 = (CilType) secondType;
|
||||
|
||||
// check if subtracting two pointer spans
|
||||
if ( (! spanType2.HasGenericParameters)
|
||||
&& spanType2.GenericParameters != null
|
||||
&& spanType2.GenericParameters[0] is CilType span2PointerType
|
||||
&& (! span2PointerType.IsGenericParameter))
|
||||
{
|
||||
code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
|
||||
new JavaMethodRef("Subtract",
|
||||
JavaType.LongType, spanType2));
|
||||
code.StackMap.PushStack(CilType.From(JavaType.LongType));
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if subtracting an offset from a pointer span
|
||||
if (spanType2.Equals(JavaType.IntegerType))
|
||||
{
|
||||
code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
|
||||
new JavaMethodRef("Subtract",
|
||||
SpanType, spanType2));
|
||||
code.StackMap.PushStack(SpanType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
code.StackMap.PushStack(spanType1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static bool Box(CilType intoType, JavaType spanType, JavaCode code)
|
||||
{
|
||||
@ -122,42 +162,87 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
public static bool Address(CilType fromType, CilType intoType, JavaCode code)
|
||||
{
|
||||
if (intoType.Equals(CodeSpan.SpanType) && (! fromType.Equals(CodeSpan.SpanType)))
|
||||
if (intoType.Equals(SpanType) && (! fromType.Equals(SpanType)))
|
||||
{
|
||||
if ( fromType.Equals(JavaType.StringType)
|
||||
&& intoType.GenericParameters != null
|
||||
&& intoType.GenericParameters[0].Equals(fromType))
|
||||
// allow assignment of null to clear the pointer
|
||||
if (fromType.Equals(JavaStackMap.Null))
|
||||
return true;
|
||||
|
||||
// allow assignment of native int (presumably zero)
|
||||
bool callAssign = false;
|
||||
bool pushNullType = true;
|
||||
JavaType argType = fromType;
|
||||
JavaType retType = SpanType;
|
||||
|
||||
if ((! fromType.IsReference) && fromType.PrimitiveType == TypeCode.UInt64)
|
||||
callAssign = true;
|
||||
else if (intoType.GenericParameters != null)
|
||||
{
|
||||
code.NewInstruction(0x01 /* aconst_null */, null, null);
|
||||
code.StackMap.PushStack(CilType.SystemTypeType);
|
||||
// allow assignment when the types match
|
||||
callAssign = intoType.GenericParameters[0].Equals(fromType)
|
||||
|| fromType.JavaName == intoType.GenericParameters[0].JavaName;
|
||||
|
||||
// for arbitrary value types, call a Assign(ValueType)
|
||||
if (fromType.IsValueClass)
|
||||
{
|
||||
argType = retType = CilType.SystemValueType;
|
||||
GenericUtil.LoadMaybeGeneric(fromType, code);
|
||||
pushNullType = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (callAssign)
|
||||
{
|
||||
if (pushNullType)
|
||||
{
|
||||
code.NewInstruction(0x01 /* aconst_null */, null, null);
|
||||
code.StackMap.PushStack(CilType.SystemTypeType);
|
||||
}
|
||||
|
||||
code.NewInstruction(0xB8 /* invokestatic */, SpanType,
|
||||
new JavaMethodRef("String" + CilMain.EXCLAMATION,
|
||||
SpanType, JavaType.StringType, CilType.SystemTypeType));
|
||||
new JavaMethodRef("Assign" + CilMain.EXCLAMATION,
|
||||
retType, argType, CilType.SystemTypeType));
|
||||
|
||||
code.NewInstruction(0xC0 /* checkcast */, SpanType, null);
|
||||
|
||||
code.StackMap.PopStack(CilMain.Where); // null type
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fromType.Equals(JavaStackMap.Null))
|
||||
return true;
|
||||
|
||||
throw new Exception($"bad assignment of '{fromType.JavaName}' into pointer");
|
||||
throw new Exception($"bad assignment of '{fromType.JavaName}' into pointer of '{intoType.GenericParameters[0].JavaName}'");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static bool LoadStore(bool isLoad, CilType stackTop, JavaType opcodeType, JavaCode code)
|
||||
public static bool LoadStore(bool isLoad, CilType stackTop, JavaType opcodeType,
|
||||
CilType dataType, JavaCode code)
|
||||
{
|
||||
if (stackTop.Equals(SpanType) && code.Method.Class.Name != SpanType.ClassName)
|
||||
{
|
||||
string opcodeDescr;
|
||||
if (opcodeType == null)
|
||||
{
|
||||
opcodeType = JavaType.ObjectType;
|
||||
opcodeType = CilType.SystemValueType;
|
||||
opcodeDescr = "";
|
||||
|
||||
// at this point we should have been called from LoadObject or
|
||||
// StoreObject in CodeMisc to handle a ldobj/stobj instruction,
|
||||
// so make sure the pointer-span element is a value type
|
||||
if (dataType.IsGenericParameter || (! dataType.IsValueClass))
|
||||
throw new InvalidProgramException();
|
||||
code.NewInstruction(0x12 /* ldc */, dataType.AsWritableClass, null);
|
||||
|
||||
// make sure the stack has room for three parameters:
|
||||
// 'this', value reference (in case of Store), and class
|
||||
code.StackMap.PushStack(JavaType.ObjectType);
|
||||
code.StackMap.PushStack(JavaType.ObjectType);
|
||||
code.StackMap.PushStack(JavaType.ObjectType);
|
||||
code.StackMap.PopStack(CilMain.Where);
|
||||
code.StackMap.PopStack(CilMain.Where);
|
||||
code.StackMap.PopStack(CilMain.Where);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -175,6 +260,8 @@ namespace SpaceFlint.CilToJava
|
||||
var spanMethod = isLoad
|
||||
? (new JavaMethodRef("Load" + opcodeDescr, opcodeType))
|
||||
: (new JavaMethodRef("Store" + opcodeDescr, voidType, opcodeType));
|
||||
if (opcodeDescr == "")
|
||||
spanMethod.Parameters.Add(new JavaFieldRef("", JavaType.ClassType));
|
||||
code.NewInstruction(0xB6 /* invokevirtual */, SpanType, spanMethod);
|
||||
if (isLoad)
|
||||
code.StackMap.PushStack(CilType.From(opcodeType));
|
||||
@ -186,10 +273,26 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
|
||||
|
||||
public static void Compare(JavaType stackTop, JavaType stackTop2,
|
||||
Mono.Cecil.Cil.Instruction cilInst, JavaCode code)
|
||||
public static bool Clear(JavaType stackTop, CilType dataType, JavaCode code)
|
||||
{
|
||||
if ( stackTop.Equals(CodeSpan.SpanType)
|
||||
if ( stackTop.Equals(SpanType)
|
||||
&& dataType.IsValueClass
|
||||
&& code.Method.Class.Name != SpanType.ClassName)
|
||||
{
|
||||
// if initobj is called on a span or pointer, call Span<T>.Clear()
|
||||
code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
|
||||
new JavaMethodRef("Clear", JavaType.VoidType));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void CompareEq(JavaType stackTop, JavaType stackTop2,
|
||||
Mono.Cecil.Cil.Instruction cilInst, JavaCode code)
|
||||
{
|
||||
if ( stackTop.Equals(SpanType)
|
||||
&& ( stackTop2.PrimitiveType == TypeCode.Int64
|
||||
|| stackTop2.PrimitiveType == TypeCode.UInt64))
|
||||
{
|
||||
@ -197,7 +300,7 @@ namespace SpaceFlint.CilToJava
|
||||
throw new InvalidProgramException();
|
||||
}
|
||||
|
||||
if ( stackTop2.Equals(CodeSpan.SpanType)
|
||||
if ( stackTop2.Equals(SpanType)
|
||||
&& ( stackTop.PrimitiveType == TypeCode.Int64
|
||||
|| stackTop.PrimitiveType == TypeCode.UInt64))
|
||||
{
|
||||
@ -222,6 +325,26 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
|
||||
|
||||
public static bool CompareGtLt(JavaType stackTop, JavaType stackTop2, JavaCode code)
|
||||
{
|
||||
if (stackTop.Equals(SpanType) && stackTop2.Equals(SpanType))
|
||||
{
|
||||
code.NewInstruction(0x01 /* aconst_null */, null, null);
|
||||
code.StackMap.PushStack(CilType.SystemTypeType);
|
||||
|
||||
code.NewInstruction(0xB8 /* invokestatic */, SpanType,
|
||||
new JavaMethodRef("CompareTo" + CilMain.EXCLAMATION,
|
||||
JavaType.IntegerType, SpanType, SpanType, CilType.SystemTypeType));
|
||||
|
||||
code.StackMap.PopStack(CilMain.Where); // null type
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal static readonly CilType SpanType =
|
||||
CilType.From(new JavaType(0, 0, "system.Span$$1"));
|
||||
}
|
||||
|
@ -322,6 +322,8 @@ namespace SpaceFlint.CilToJava
|
||||
|
||||
if (! (fromType.IsInterface || fromType.IsDelegate))
|
||||
return;
|
||||
string varianceString = null;
|
||||
|
||||
bool anyVariance = false;
|
||||
foreach (var gp in defType.GenericParameters)
|
||||
{
|
||||
@ -332,18 +334,31 @@ namespace SpaceFlint.CilToJava
|
||||
}
|
||||
}
|
||||
if (! anyVariance)
|
||||
return;
|
||||
{
|
||||
if (fromType.JavaName == "system.collections.generic.IComparer$$1")
|
||||
{
|
||||
// force a variance string for an interface that we create
|
||||
// as an abstract class; see also IComparer.cs in baselib
|
||||
varianceString = "I";
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// build a string that describes the generic variance
|
||||
|
||||
var chars = new char[defType.GenericParameters.Count];
|
||||
int idx = 0;
|
||||
foreach (var gp in defType.GenericParameters)
|
||||
if (varianceString == null)
|
||||
{
|
||||
var v = gp.Attributes & GenericParameterAttributes.VarianceMask;
|
||||
chars[idx++] = (v == GenericParameterAttributes.Covariant) ? 'O'
|
||||
: (v == GenericParameterAttributes.Contravariant) ? 'I'
|
||||
: ' ';
|
||||
var chars = new char[defType.GenericParameters.Count];
|
||||
int idx = 0;
|
||||
foreach (var gp in defType.GenericParameters)
|
||||
{
|
||||
var v = gp.Attributes & GenericParameterAttributes.VarianceMask;
|
||||
chars[idx++] = (v == GenericParameterAttributes.Covariant) ? 'O'
|
||||
: (v == GenericParameterAttributes.Contravariant) ? 'I'
|
||||
: ' ';
|
||||
}
|
||||
varianceString = new string(chars);
|
||||
}
|
||||
|
||||
var varianceField = new JavaField();
|
||||
@ -354,7 +369,7 @@ namespace SpaceFlint.CilToJava
|
||||
| JavaAccessFlags.ACC_PUBLIC
|
||||
| JavaAccessFlags.ACC_TRANSIENT
|
||||
| JavaAccessFlags.ACC_SYNTHETIC;
|
||||
varianceField.Constant = new string(chars);
|
||||
varianceField.Constant = varianceString;
|
||||
varianceField.Class = theClass;
|
||||
|
||||
if (theClass.Fields == null)
|
||||
|
@ -11,7 +11,8 @@ namespace Tests
|
||||
{
|
||||
Test1();
|
||||
Test2("Hello, world");
|
||||
//Test3(default(Guid));
|
||||
Test3(default(Guid));
|
||||
Test4(default(AAA));
|
||||
}
|
||||
|
||||
unsafe void Test1()
|
||||
@ -59,12 +60,21 @@ namespace Tests
|
||||
Console.WriteLine(from + " -> " + new String(into) + "~~~");
|
||||
}
|
||||
|
||||
/*unsafe void Test3(Guid from)
|
||||
unsafe void Test3(Guid from)
|
||||
{
|
||||
Guid *pFrom = &from;
|
||||
*pFrom = new Guid("00000001-0000-0000-0000-000000000000");
|
||||
Console.WriteLine(from);
|
||||
}*/
|
||||
}
|
||||
|
||||
struct AAA {}
|
||||
|
||||
unsafe void Test4(AAA from)
|
||||
{
|
||||
AAA *pFrom = &from;
|
||||
*pFrom = new AAA();
|
||||
Console.WriteLine(from);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ namespace Tests
|
||||
// Enum
|
||||
//
|
||||
|
||||
[Flags] enum MyEnum : sbyte { None, First = 1, Second = 8, Third = 32 };
|
||||
[Flags] enum MyEnum : short { None, First = 1, Second = 8, Third = 32 };
|
||||
|
||||
void TestEnum()
|
||||
{
|
||||
@ -92,6 +92,14 @@ namespace Tests
|
||||
Console.Write("\t");
|
||||
Console.Write(y);
|
||||
Console.Write($"\t{x:F},{x:G},{x:D},{x:X},{x.GetType().GetEnumUnderlyingType()}");
|
||||
Console.Write($"\t{((IConvertible) x).ToType(typeof(long), null)}");
|
||||
Console.Write($"\t{x.HasFlag(MyEnum.Third)}");
|
||||
Console.WriteLine();
|
||||
|
||||
var names = typeof(MyEnum).GetEnumNames();
|
||||
var values = typeof(MyEnum).GetEnumValues();
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
Console.Write($"\t{names[i]} = {(short) values.GetValue(i)}");
|
||||
Console.WriteLine();
|
||||
|
||||
void TestEnum2<T>(ref T e)
|
||||
|
Loading…
x
Reference in New Issue
Block a user