/// <summary> /// Determines whether the specified type is an <see cref="ExtensibleEnum{T}"/> type. /// </summary> /// <param name="type">The type to be checked.</param> /// <returns> /// <see langword="true"/> if the specified type is an extensible enum type; otherwise, <see langword="false"/>. /// </returns> /// <exception cref="ArgumentNullException">The <paramref name="type"/> parameter is <see langword="null" />.</exception> /// <remarks> /// For performance reasons, this method only checks if the <paramref name="type"/> implements <see cref="IExtensibleEnum"/>, it does not /// check whether the type is derived from <see cref="ExtensibleEnum{T}"/>. The <see cref="GetDefinition"/> method, however, will throw /// an exception when used with a type not derived from <see cref="ExtensibleEnum{T}"/>. /// </remarks> public static bool IsExtensibleEnumType(ITypeInformation type) { ArgumentUtility.CheckNotNull("type", type); return(s_extensibleEnumInterfaceType.IsAssignableFrom(type) && !type.Equals(s_extensibleEnumGenericBaseType) && !(type.IsGenericType && type.GetGenericTypeDefinition().Equals(s_extensibleEnumGenericBaseType)) && !type.Equals(s_extensibleEnumInterfaceType)); }
public override Func <IExtractContext, string[]> Apply( ITypeInformation operand, DecodeContext decodeContext) { var si = decodeContext.PopStack(); if (!(si.TargetType.IsValueType && // We have to value type (operand.Equals(si.TargetType) || // Same type (operand.IsInt32StackFriendlyType && si.TargetType.IsInt32StackFriendlyType) || // Same size or implicit expanders (operand.IsInt64StackFriendlyType && si.TargetType.IsInt64StackFriendlyType) || // Same size (operand.IsIntPtrStackFriendlyType && si.TargetType.IsIntPtrStackFriendlyType)))) // Same size { throw new InvalidProgramSequenceException( "Invalid type at stack: Location={0}, TokenType={1}, StackType={2}", decodeContext.CurrentCode.RawLocation, operand.FriendlyName, si.TargetType.FriendlyName); } // NOTE: The 'O' type means System.Object, but we have to push the System.ValueType (BoxedValueTypeInformation). // Because the boxed value types can implicit cast to both types. // The upcast can be inlining (System.ValueType --> System.Object), // but downcast requires runtime cast operator (System.Object --> System.ValueType). var symbol = decodeContext.PushStack( new BoxedValueTypeInformation(si.TargetType)); // NOTE: The IL2C strict type infers the evaluation stack. // The unbox operator is handling by the pointer. // So, we have to simulate implicitly conversion from little size value to large size value. // (It's only 8/16 --> 32bit. See ECMA-335 III.1.1.1 Numeric data types) // We can use conversion with the "il2c_box2" function in this case. // For example: // // object value = (byte)123; // ldc.i4.s 123 // int32_t // box [mscorlib]System.Byte // int32_t --> objref(uint8_t) // size[4] --> size[1] if (operand.InternalStaticSizeOfValue == si.TargetType.InternalStaticSizeOfValue) { return(extractContext => { return new[] { string.Format( "{0} = il2c_box(&{1}, {2})", extractContext.GetSymbolName(symbol), extractContext.GetSymbolName(si), operand.MangledName) }; }); } else { return(extractContext => { return new[] { string.Format( "{0} = il2c_box2(&{1}, {2}, {3})", extractContext.GetSymbolName(symbol), extractContext.GetSymbolName(si), operand.MangledName, si.TargetType.MangledName) }; }); } }
public bool IsAssignableFrom(ITypeInformation rhs) { return(rhs.Equals(boxedType)); }