incremental changes

This commit is contained in:
spaceflint 2020-09-01 18:28:45 +03:00
parent 9181b2ab62
commit 5aa43c15ee
25 changed files with 773 additions and 200 deletions

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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
{

View File

@ -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();

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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(

View File

@ -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();

View File

@ -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;
}
//

View File

@ -4,6 +4,8 @@ using System.Runtime.InteropServices;
namespace system.reflection
{
public abstract class Module { }
public sealed class RuntimeModule
{

View File

@ -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)
*/

View File

@ -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

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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();

View File

@ -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)))
{

View File

@ -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;
}

View File

@ -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"));
}

View File

@ -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)

View File

@ -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);
}
}
}

View File

@ -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)