//
// typemanager.cs: C# type manager
//
// Author: Miguel de Icaza (miguel@gnu.org)
// Ravi Pratap (ravi@ximian.com)
// Marek Safar (marek.safar@seznam.cz)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
//
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Text;
namespace Mono.CSharp
{
//
// All compiler build-in types (they have to exist otherwise the compile will not work)
//
public class BuildinTypes
{
public readonly BuildinTypeSpec Object;
public readonly BuildinTypeSpec ValueType;
public readonly BuildinTypeSpec Attribute;
public readonly BuildinTypeSpec Int;
public readonly BuildinTypeSpec UInt;
public readonly BuildinTypeSpec Long;
public readonly BuildinTypeSpec ULong;
public readonly BuildinTypeSpec Float;
public readonly BuildinTypeSpec Double;
public readonly BuildinTypeSpec Char;
public readonly BuildinTypeSpec Short;
public readonly BuildinTypeSpec Decimal;
public readonly BuildinTypeSpec Bool;
public readonly BuildinTypeSpec SByte;
public readonly BuildinTypeSpec Byte;
public readonly BuildinTypeSpec UShort;
public readonly BuildinTypeSpec String;
public readonly BuildinTypeSpec Enum;
public readonly BuildinTypeSpec Delegate;
public readonly BuildinTypeSpec MulticastDelegate;
public readonly BuildinTypeSpec Void;
public readonly BuildinTypeSpec Array;
public readonly BuildinTypeSpec Type;
public readonly BuildinTypeSpec IEnumerator;
public readonly BuildinTypeSpec IEnumerable;
public readonly BuildinTypeSpec IDisposable;
public readonly BuildinTypeSpec IntPtr;
public readonly BuildinTypeSpec UIntPtr;
public readonly BuildinTypeSpec RuntimeFieldHandle;
public readonly BuildinTypeSpec RuntimeTypeHandle;
public readonly BuildinTypeSpec Exception;
//
// These are internal buil-in types which depend on other
// build-in type (mostly object)
//
public readonly BuildinTypeSpec Dynamic;
public readonly BuildinTypeSpec Null;
readonly BuildinTypeSpec[] types;
public BuildinTypes ()
{
Object = new BuildinTypeSpec (MemberKind.Class, "System", "Object", BuildinTypeSpec.Type.Object);
ValueType = new BuildinTypeSpec (MemberKind.Class, "System", "ValueType", BuildinTypeSpec.Type.ValueType);
Attribute = new BuildinTypeSpec (MemberKind.Class, "System", "Attribute", BuildinTypeSpec.Type.Attribute);
Int = new BuildinTypeSpec (MemberKind.Struct, "System", "Int32", BuildinTypeSpec.Type.Int);
Long = new BuildinTypeSpec (MemberKind.Struct, "System", "Int64", BuildinTypeSpec.Type.Long);
UInt = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt32", BuildinTypeSpec.Type.UInt);
ULong = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt64", BuildinTypeSpec.Type.ULong);
Byte = new BuildinTypeSpec (MemberKind.Struct, "System", "Byte", BuildinTypeSpec.Type.Byte);
SByte = new BuildinTypeSpec (MemberKind.Struct, "System", "SByte", BuildinTypeSpec.Type.SByte);
Short = new BuildinTypeSpec (MemberKind.Struct, "System", "Int16", BuildinTypeSpec.Type.Short);
UShort = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt16", BuildinTypeSpec.Type.UShort);
IEnumerator = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuildinTypeSpec.Type.IEnumerator);
IEnumerable = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuildinTypeSpec.Type.IEnumerable);
IDisposable = new BuildinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuildinTypeSpec.Type.IDisposable);
Char = new BuildinTypeSpec (MemberKind.Struct, "System", "Char", BuildinTypeSpec.Type.Char);
String = new BuildinTypeSpec (MemberKind.Class, "System", "String", BuildinTypeSpec.Type.String);
Float = new BuildinTypeSpec (MemberKind.Struct, "System", "Single", BuildinTypeSpec.Type.Float);
Double = new BuildinTypeSpec (MemberKind.Struct, "System", "Double", BuildinTypeSpec.Type.Double);
Decimal = new BuildinTypeSpec (MemberKind.Struct, "System", "Decimal", BuildinTypeSpec.Type.Decimal);
Bool = new BuildinTypeSpec (MemberKind.Struct, "System", "Boolean", BuildinTypeSpec.Type.Bool);
IntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuildinTypeSpec.Type.IntPtr);
UIntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuildinTypeSpec.Type.UIntPtr);
MulticastDelegate = new BuildinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuildinTypeSpec.Type.MulticastDelegate);
Delegate = new BuildinTypeSpec (MemberKind.Class, "System", "Delegate", BuildinTypeSpec.Type.Delegate);
Enum = new BuildinTypeSpec (MemberKind.Class, "System", "Enum", BuildinTypeSpec.Type.Enum);
Array = new BuildinTypeSpec (MemberKind.Class, "System", "Array", BuildinTypeSpec.Type.Array);
Void = new BuildinTypeSpec (MemberKind.Struct, "System", "Void", BuildinTypeSpec.Type.Void);
Type = new BuildinTypeSpec (MemberKind.Class, "System", "Type", BuildinTypeSpec.Type.Type);
Exception = new BuildinTypeSpec (MemberKind.Class, "System", "Exception", BuildinTypeSpec.Type.Exception);
RuntimeFieldHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuildinTypeSpec.Type.RuntimeFieldHandle);
RuntimeTypeHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuildinTypeSpec.Type.RuntimeTypeHandle);
Dynamic = new BuildinTypeSpec ("dynamic", BuildinTypeSpec.Type.Dynamic);
Null = new BuildinTypeSpec ("null", BuildinTypeSpec.Type.Null);
Null.MemberCache = MemberCache.Empty;
types = new BuildinTypeSpec[] {
Object, ValueType, Attribute,
Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String,
Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable,
IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception };
// Deal with obsolete static types
// TODO: remove
TypeManager.object_type = Object;
TypeManager.value_type = ValueType;
TypeManager.string_type = String;
TypeManager.int32_type = Int;
TypeManager.uint32_type = UInt;
TypeManager.int64_type = Long;
TypeManager.uint64_type = ULong;
TypeManager.float_type = Float;
TypeManager.double_type = Double;
TypeManager.char_type = Char;
TypeManager.short_type = Short;
TypeManager.decimal_type = Decimal;
TypeManager.bool_type = Bool;
TypeManager.sbyte_type = SByte;
TypeManager.byte_type = Byte;
TypeManager.ushort_type = UShort;
TypeManager.enum_type = Enum;
TypeManager.delegate_type = Delegate;
TypeManager.multicast_delegate_type = MulticastDelegate; ;
TypeManager.void_type = Void;
TypeManager.array_type = Array; ;
TypeManager.runtime_handle_type = RuntimeTypeHandle;
TypeManager.type_type = Type;
TypeManager.ienumerator_type = IEnumerator;
TypeManager.ienumerable_type = IEnumerable;
TypeManager.idisposable_type = IDisposable;
TypeManager.intptr_type = IntPtr;
TypeManager.uintptr_type = UIntPtr;
TypeManager.runtime_field_handle_type = RuntimeFieldHandle;
TypeManager.attribute_type = Attribute;
TypeManager.exception_type = Exception;
InternalType.Dynamic = Dynamic;
InternalType.Null = Null;
}
public BuildinTypeSpec[] AllTypes {
get {
return types;
}
}
public bool CheckDefinitions (ModuleContainer module)
{
var ctx = module.Compiler;
foreach (var p in types) {
var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity, Location.Null);
if (found == null || found == p)
continue;
if (!RootContext.StdLib) {
var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
ns.ReplaceTypeWithPredefined (found, p);
var tc = found.MemberDefinition as TypeContainer;
tc.SetPredefinedSpec (p);
p.SetDefinition (found);
}
}
if (ctx.Report.Errors != 0)
return false;
// Set internal build-in types
Dynamic.SetDefinition (Object);
Null.SetDefinition (Object);
return true;
}
}
//
// Compiler predefined types. Usually used for compiler generated
// code or for comparison against well known framework type
//
class PredefinedTypes
{
// TODO: These two exist only to reject type comparison
public readonly PredefinedType TypedReference;
public readonly PredefinedType ArgIterator;
public readonly PredefinedType MarshalByRefObject;
public readonly PredefinedType RuntimeHelpers;
public readonly PredefinedType IAsyncResult;
public readonly PredefinedType AsyncCallback;
public readonly PredefinedType RuntimeArgumentHandle;
public readonly PredefinedType CharSet;
public readonly PredefinedType IsVolatile;
public readonly PredefinedType IEnumeratorGeneric;
public readonly PredefinedType IListGeneric;
public readonly PredefinedType ICollectionGeneric;
public readonly PredefinedType IEnumerableGeneric;
public readonly PredefinedType Nullable;
public readonly PredefinedType Activator;
public readonly PredefinedType Interlocked;
public readonly PredefinedType Monitor;
public readonly PredefinedType NotSupportedException;
public readonly PredefinedType RuntimeFieldHandle;
public readonly PredefinedType RuntimeMethodHandle;
public readonly PredefinedType SecurityAction;
//
// C# 3.0
//
public readonly PredefinedType Expression;
public readonly PredefinedType ExpressionGeneric;
public readonly PredefinedType ParameterExpression;
public readonly PredefinedType FieldInfo;
public readonly PredefinedType MethodBase;
public readonly PredefinedType MethodInfo;
public readonly PredefinedType ConstructorInfo;
//
// C# 4.0
//
public readonly PredefinedType Binder;
public readonly PredefinedType CallSite;
public readonly PredefinedType CallSiteGeneric;
public readonly PredefinedType BinderFlags;
public PredefinedTypes (ModuleContainer module)
{
TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator");
MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject");
RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers");
IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult");
AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback");
RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle");
CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet");
IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile");
IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1);
IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1);
ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1);
IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1);
Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1);
Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator");
Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked");
Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor");
NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException");
RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle");
RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle");
SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction");
Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression");
ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1);
ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression");
FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo");
MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase");
MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo");
ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo");
CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite");
CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1);
Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder");
BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags");
//
// Define types which are used for comparison. It does not matter
// if they don't exist as no error report is needed
//
TypedReference.Define ();
ArgIterator.Define ();
MarshalByRefObject.Define ();
CharSet.Define ();
IEnumerableGeneric.Define ();
IListGeneric.Define ();
ICollectionGeneric.Define ();
IEnumerableGeneric.Define ();
IEnumeratorGeneric.Define ();
Nullable.Define ();
ExpressionGeneric.Define ();
// Deal with obsolete static types
// TODO: remove
TypeManager.typed_reference_type = TypedReference.TypeSpec;
TypeManager.arg_iterator_type = ArgIterator.TypeSpec;
TypeManager.mbr_type = MarshalByRefObject.TypeSpec;
TypeManager.generic_ilist_type = IListGeneric.TypeSpec;
TypeManager.generic_icollection_type = ICollectionGeneric.TypeSpec;
TypeManager.generic_ienumerator_type = IEnumeratorGeneric.TypeSpec;
TypeManager.generic_ienumerable_type = IEnumerableGeneric.TypeSpec;
TypeManager.generic_nullable_type = Nullable.TypeSpec;
TypeManager.expression_type = ExpressionGeneric.TypeSpec;
}
}
public class PredefinedType
{
string name;
string ns;
int arity;
MemberKind kind;
ModuleContainer module;
protected TypeSpec type;
public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
: this (module, kind, ns, name)
{
this.arity = arity;
}
public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name)
{
this.module = module;
this.kind = kind;
this.name = name;
this.ns = ns;
}
#region Properties
public int Arity {
get {
return arity;
}
}
public bool IsDefined {
get {
return type != null;
}
}
public string Name {
get {
return name;
}
}
public string Namespace {
get {
return ns;
}
}
public TypeSpec TypeSpec {
get {
return type;
}
}
#endregion
public bool Define ()
{
if (type != null)
return true;
Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
var te = type_ns.LookupType (module.Compiler, name, arity, true, Location.Null);
if (te == null)
return false;
if (te.Type.Kind != kind)
return false;
type = te.Type;
return true;
}
public FieldSpec GetField (string name, TypeSpec memberType, Location loc)
{
return TypeManager.GetPredefinedField (type, name, loc, memberType);
}
public string GetSignatureForError ()
{
return ns + "." + name;
}
public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, Location loc)
{
Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
var te = type_ns.LookupType (module.Compiler, name, arity, false, Location.Null);
if (te == null) {
module.Compiler.Report.Error (518, loc, "The predefined type `{0}.{1}' is not defined or imported", ns, name);
return null;
}
var type = te.Type;
if (type.Kind != kind) {
module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name);
return null;
}
return type;
}
public TypeSpec Resolve (Location loc)
{
if (type == null)
type = Resolve (module, kind, ns, name, arity, loc);
return type;
}
}
partial class TypeManager {
//
// A list of core types that the compiler requires or uses
//
static public BuildinTypeSpec object_type;
static public BuildinTypeSpec value_type;
static public BuildinTypeSpec string_type;
static public BuildinTypeSpec int32_type;
static public BuildinTypeSpec uint32_type;
static public BuildinTypeSpec int64_type;
static public BuildinTypeSpec uint64_type;
static public BuildinTypeSpec float_type;
static public BuildinTypeSpec double_type;
static public BuildinTypeSpec char_type;
static public BuildinTypeSpec short_type;
static public BuildinTypeSpec decimal_type;
static public BuildinTypeSpec bool_type;
static public BuildinTypeSpec sbyte_type;
static public BuildinTypeSpec byte_type;
static public BuildinTypeSpec ushort_type;
static public BuildinTypeSpec enum_type;
static public BuildinTypeSpec delegate_type;
static public BuildinTypeSpec multicast_delegate_type;
static public BuildinTypeSpec void_type;
static public BuildinTypeSpec array_type;
static public BuildinTypeSpec runtime_handle_type;
static public BuildinTypeSpec type_type;
static public BuildinTypeSpec ienumerator_type;
static public BuildinTypeSpec ienumerable_type;
static public BuildinTypeSpec idisposable_type;
static public BuildinTypeSpec intptr_type;
static public BuildinTypeSpec uintptr_type;
static public BuildinTypeSpec runtime_field_handle_type;
static public BuildinTypeSpec attribute_type;
static public BuildinTypeSpec exception_type;
static public TypeSpec typed_reference_type;
static public TypeSpec arg_iterator_type;
static public TypeSpec mbr_type;
static public TypeSpec generic_ilist_type;
static public TypeSpec generic_icollection_type;
static public TypeSpec generic_ienumerator_type;
static public TypeSpec generic_ienumerable_type;
static public TypeSpec generic_nullable_type;
static internal TypeSpec expression_type;
//
// These methods are called by code generated by the compiler
//
static public FieldSpec string_empty;
static public MethodSpec system_type_get_type_from_handle;
static public MethodSpec bool_movenext_void;
static public MethodSpec void_dispose_void;
static public MethodSpec void_monitor_enter_object;
static public MethodSpec void_monitor_exit_object;
static public MethodSpec void_initializearray_array_fieldhandle;
static public MethodSpec delegate_combine_delegate_delegate;
static public MethodSpec delegate_remove_delegate_delegate;
static public PropertySpec int_get_offset_to_string_data;
static public MethodSpec int_interlocked_compare_exchange;
public static MethodSpec gen_interlocked_compare_exchange;
static public PropertySpec ienumerator_getcurrent;
public static MethodSpec methodbase_get_type_from_handle;
public static MethodSpec methodbase_get_type_from_handle_generic;
public static MethodSpec fieldinfo_get_field_from_handle;
public static MethodSpec fieldinfo_get_field_from_handle_generic;
public static MethodSpec activator_create_instance;
//
// The constructors.
//
static public MethodSpec void_decimal_ctor_five_args;
static public MethodSpec void_decimal_ctor_int_arg;
public static MethodSpec void_decimal_ctor_long_arg;
static TypeManager ()
{
Reset ();
}
static public void Reset ()
{
// object_type = null;
// TODO: I am really bored by all this static stuff
system_type_get_type_from_handle =
bool_movenext_void =
void_dispose_void =
void_monitor_enter_object =
void_monitor_exit_object =
void_initializearray_array_fieldhandle =
int_interlocked_compare_exchange =
gen_interlocked_compare_exchange =
methodbase_get_type_from_handle =
methodbase_get_type_from_handle_generic =
fieldinfo_get_field_from_handle =
fieldinfo_get_field_from_handle_generic =
activator_create_instance =
delegate_combine_delegate_delegate =
delegate_remove_delegate_delegate = null;
int_get_offset_to_string_data =
ienumerator_getcurrent = null;
void_decimal_ctor_five_args =
void_decimal_ctor_int_arg =
void_decimal_ctor_long_arg = null;
string_empty = null;
typed_reference_type = arg_iterator_type = mbr_type =
generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
generic_ienumerable_type = generic_nullable_type = expression_type = null;
}
///
/// Returns the C# name of a type if possible, or the full type name otherwise
///
static public string CSharpName (TypeSpec t)
{
return t.GetSignatureForError ();
}
static public string CSharpName (IList types)
{
if (types.Count == 0)
return string.Empty;
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < types.Count; ++i) {
if (i > 0)
sb.Append (",");
sb.Append (CSharpName (types [i]));
}
return sb.ToString ();
}
static public string GetFullNameSignature (MemberSpec mi)
{
return mi.GetSignatureForError ();
}
static public string CSharpSignature (MemberSpec mb)
{
return mb.GetSignatureForError ();
}
static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, bool optional, Location loc)
{
var member = MemberCache.FindMember (t, filter, BindingRestriction.DeclaredOnly);
if (member != null && member.IsAccessible (InternalType.FakeInternalType))
return member;
if (optional)
return member;
string method_args = null;
if (filter.Parameters != null)
method_args = filter.Parameters.GetSignatureForError ();
RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
TypeManager.CSharpName (t), filter.Name, method_args);
return null;
}
//
// Returns the ConstructorInfo for "args"
//
public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
{
var pc = ParametersCompiled.CreateFullyResolved (args);
return GetPredefinedMember (t, MemberFilter.Constructor (pc), false, loc) as MethodSpec;
}
//
// Returns the method specification for a method named `name' defined
// in type `t' which takes arguments of types `args'
//
public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
{
var pc = ParametersCompiled.CreateFullyResolved (args);
return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), false, loc);
}
public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
{
return GetPredefinedMethod (t, filter, false, loc);
}
public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, bool optional, Location loc)
{
return GetPredefinedMember (t, filter, optional, loc) as MethodSpec;
}
public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
{
return GetPredefinedMember (t, MemberFilter.Field (name, type), false, loc) as FieldSpec;
}
public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
{
return GetPredefinedMember (t, MemberFilter.Property (name, type), false, loc) as PropertySpec;
}
public static bool IsBuiltinType (TypeSpec t)
{
if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
t == int64_type || t == uint64_type || t == float_type || t == double_type ||
t == char_type || t == short_type || t == decimal_type || t == bool_type ||
t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
return true;
else
return false;
}
//
// This is like IsBuiltinType, but lacks decimal_type, we should also clean up
// the pieces in the code where we use IsBuiltinType and special case decimal_type.
//
public static bool IsPrimitiveType (TypeSpec t)
{
return (t == int32_type || t == uint32_type ||
t == int64_type || t == uint64_type || t == float_type || t == double_type ||
t == char_type || t == short_type || t == bool_type ||
t == sbyte_type || t == byte_type || t == ushort_type);
}
// Obsolete
public static bool IsDelegateType (TypeSpec t)
{
return t.IsDelegate;
}
// Obsolete
public static bool IsEnumType (TypeSpec t)
{
return t.IsEnum;
}
public static bool IsBuiltinOrEnum (TypeSpec t)
{
if (IsBuiltinType (t))
return true;
if (IsEnumType (t))
return true;
return false;
}
//
// Whether a type is unmanaged. This is used by the unsafe code (25.2)
//
public static bool IsUnmanagedType (TypeSpec t)
{
var ds = t.MemberDefinition as DeclSpace;
if (ds != null)
return ds.IsUnmanagedType ();
// some builtins that are not unmanaged types
if (t == TypeManager.object_type || t == TypeManager.string_type)
return false;
if (IsBuiltinOrEnum (t))
return true;
// Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
if (t.IsPointer)
return IsUnmanagedType (GetElementType (t));
if (!IsValueType (t))
return false;
if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
return false;
return true;
}
//
// Null is considered to be a reference type
//
public static bool IsReferenceType (TypeSpec t)
{
if (t.IsGenericParameter)
return ((TypeParameterSpec) t).IsReferenceType;
return !t.IsStruct && !IsEnumType (t);
}
public static bool IsValueType (TypeSpec t)
{
if (t.IsGenericParameter)
return ((TypeParameterSpec) t).IsValueType;
return t.IsStruct || IsEnumType (t);
}
public static bool IsStruct (TypeSpec t)
{
return t.IsStruct;
}
public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
{
// TypeParameter tparam = LookupTypeParameter (type);
// TypeParameter pparam = LookupTypeParameter (parent);
if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
if (type == parent)
return true;
throw new NotImplementedException ("net");
// return tparam.IsSubclassOf (parent);
}
do {
if (IsInstantiationOfSameGenericType (type, parent))
return true;
type = type.BaseType;
} while (type != null);
return false;
}
//
// Checks whether `type' is a subclass or nested child of `base_type'.
//
public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type)
{
do {
if (IsFamilyAccessible (type, base_type))
return true;
// Handle nested types.
type = type.DeclaringType;
} while (type != null);
return false;
}
//
// Checks whether `type' is a nested child of `parent'.
//
public static bool IsNestedChildOf (TypeSpec type, TypeSpec parent)
{
if (type == null)
return false;
type = type.GetDefinition (); // DropGenericTypeArguments (type);
parent = parent.GetDefinition (); // DropGenericTypeArguments (parent);
if (type == parent)
return false;
type = type.DeclaringType;
while (type != null) {
if (type.GetDefinition () == parent)
return true;
type = type.DeclaringType;
}
return false;
}
public static bool IsSpecialType (TypeSpec t)
{
return t == arg_iterator_type || t == typed_reference_type;
}
public static TypeSpec GetElementType (TypeSpec t)
{
return ((ElementTypeSpec)t).Element;
}
///
/// This method is not implemented by MS runtime for dynamic types
///
public static bool HasElementType (TypeSpec t)
{
return t is ElementTypeSpec;
}
static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
// This is a custom version of Convert.ChangeType() which works
// with the TypeBuilder defined types when compiling corlib.
public static object ChangeType (object value, TypeSpec targetType, out bool error)
{
IConvertible convert_value = value as IConvertible;
if (convert_value == null){
error = true;
return null;
}
//
// We cannot rely on build-in type conversions as they are
// more limited than what C# supports.
// See char -> float/decimal/double conversion
//
error = false;
try {
if (targetType == TypeManager.bool_type)
return convert_value.ToBoolean (nf_provider);
if (targetType == TypeManager.byte_type)
return convert_value.ToByte (nf_provider);
if (targetType == TypeManager.char_type)
return convert_value.ToChar (nf_provider);
if (targetType == TypeManager.short_type)
return convert_value.ToInt16 (nf_provider);
if (targetType == TypeManager.int32_type)
return convert_value.ToInt32 (nf_provider);
if (targetType == TypeManager.int64_type)
return convert_value.ToInt64 (nf_provider);
if (targetType == TypeManager.sbyte_type)
return convert_value.ToSByte (nf_provider);
if (targetType == TypeManager.decimal_type) {
if (convert_value.GetType () == typeof (char))
return (decimal) convert_value.ToInt32 (nf_provider);
return convert_value.ToDecimal (nf_provider);
}
if (targetType == TypeManager.double_type) {
if (convert_value.GetType () == typeof (char))
return (double) convert_value.ToInt32 (nf_provider);
return convert_value.ToDouble (nf_provider);
}
if (targetType == TypeManager.float_type) {
if (convert_value.GetType () == typeof (char))
return (float)convert_value.ToInt32 (nf_provider);
return convert_value.ToSingle (nf_provider);
}
if (targetType == TypeManager.string_type)
return convert_value.ToString (nf_provider);
if (targetType == TypeManager.ushort_type)
return convert_value.ToUInt16 (nf_provider);
if (targetType == TypeManager.uint32_type)
return convert_value.ToUInt32 (nf_provider);
if (targetType == TypeManager.uint64_type)
return convert_value.ToUInt64 (nf_provider);
if (targetType == TypeManager.object_type)
return value;
error = true;
} catch {
error = true;
}
return null;
}
///
/// Utility function that can be used to probe whether a type
/// is managed or not.
///
public static bool VerifyUnmanaged (CompilerContext ctx, TypeSpec t, Location loc)
{
while (t.IsPointer)
t = GetElementType (t);
if (IsUnmanagedType (t))
return true;
ctx.Report.SymbolRelatedToPreviousError (t);
ctx.Report.Error (208, loc,
"Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
CSharpName (t));
return false;
}
#region Generics
// This method always return false for non-generic compiler,
// while Type.IsGenericParameter is returned if it is supported.
public static bool IsGenericParameter (TypeSpec type)
{
return type.IsGenericParameter;
}
public static bool IsGenericType (TypeSpec type)
{
return type.IsGeneric;
}
// TODO: Implement correctly
public static bool ContainsGenericParameters (TypeSpec type)
{
return type.GetMetaInfo ().ContainsGenericParameters;
}
public static TypeSpec[] GetTypeArguments (TypeSpec t)
{
// TODO: return empty array !!
return t.TypeArguments;
}
///
/// Check whether `type' and `parent' are both instantiations of the same
/// generic type. Note that we do not check the type parameters here.
///
public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent)
{
return type == parent || type.MemberDefinition == parent.MemberDefinition;
}
public static bool IsNullableType (TypeSpec t)
{
return generic_nullable_type == t.GetDefinition ();
}
#endregion
}
}