5c029c6eba2d0351d6b49c3891988524dcc291e9
[mono.git] / mcs / mcs / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //         Marek Safar     (marek.safar@seznam.cz)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2003-2008 Novell, Inc.
12 //
13
14 using System;
15 using System.Globalization;
16 using System.Collections.Generic;
17 using System.Text;
18
19 namespace Mono.CSharp
20 {
21         //
22         // All compiler build-in types (they have to exist otherwise the compile will not work)
23         //
24         public class BuildinTypes
25         {
26                 public readonly BuildinTypeSpec Object;
27                 public readonly BuildinTypeSpec ValueType;
28                 public readonly BuildinTypeSpec Attribute;
29
30                 public readonly BuildinTypeSpec Int;
31                 public readonly BuildinTypeSpec UInt;
32                 public readonly BuildinTypeSpec Long;
33                 public readonly BuildinTypeSpec ULong;
34                 public readonly BuildinTypeSpec Float;
35                 public readonly BuildinTypeSpec Double;
36                 public readonly BuildinTypeSpec Char;
37                 public readonly BuildinTypeSpec Short;
38                 public readonly BuildinTypeSpec Decimal;
39                 public readonly BuildinTypeSpec Bool;
40                 public readonly BuildinTypeSpec SByte;
41                 public readonly BuildinTypeSpec Byte;
42                 public readonly BuildinTypeSpec UShort;
43                 public readonly BuildinTypeSpec String;
44
45                 public readonly BuildinTypeSpec Enum;
46                 public readonly BuildinTypeSpec Delegate;
47                 public readonly BuildinTypeSpec MulticastDelegate;
48                 public readonly BuildinTypeSpec Void;
49                 public readonly BuildinTypeSpec Array;
50                 public readonly BuildinTypeSpec Type;
51                 public readonly BuildinTypeSpec IEnumerator;
52                 public readonly BuildinTypeSpec IEnumerable;
53                 public readonly BuildinTypeSpec IDisposable;
54                 public readonly BuildinTypeSpec IntPtr;
55                 public readonly BuildinTypeSpec UIntPtr;
56                 public readonly BuildinTypeSpec RuntimeFieldHandle;
57                 public readonly BuildinTypeSpec RuntimeTypeHandle;
58                 public readonly BuildinTypeSpec Exception;
59
60                 readonly BuildinTypeSpec[] types;
61
62                 public BuildinTypes ()
63                 {
64                         Object = new BuildinTypeSpec (MemberKind.Class, "System", "Object", BuildinTypeSpec.Type.Object);
65                         ValueType = new BuildinTypeSpec (MemberKind.Class, "System", "ValueType", BuildinTypeSpec.Type.ValueType);
66                         Attribute = new BuildinTypeSpec (MemberKind.Class, "System", "Attribute", BuildinTypeSpec.Type.Attribute);
67
68                         Int = new BuildinTypeSpec (MemberKind.Struct, "System", "Int32", BuildinTypeSpec.Type.Int);
69                         Long = new BuildinTypeSpec (MemberKind.Struct, "System", "Int64", BuildinTypeSpec.Type.Long);
70                         UInt = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt32", BuildinTypeSpec.Type.UInt);
71                         ULong = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt64", BuildinTypeSpec.Type.ULong);
72                         Byte = new BuildinTypeSpec (MemberKind.Struct, "System", "Byte", BuildinTypeSpec.Type.Byte);
73                         SByte = new BuildinTypeSpec (MemberKind.Struct, "System", "SByte", BuildinTypeSpec.Type.SByte);
74                         Short = new BuildinTypeSpec (MemberKind.Struct, "System", "Int16", BuildinTypeSpec.Type.Short);
75                         UShort = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt16", BuildinTypeSpec.Type.UShort);
76
77                         IEnumerator = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuildinTypeSpec.Type.IEnumerator);
78                         IEnumerable = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuildinTypeSpec.Type.IEnumerable);
79                         IDisposable = new BuildinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuildinTypeSpec.Type.IDisposable);
80
81                         Char = new BuildinTypeSpec (MemberKind.Struct, "System", "Char", BuildinTypeSpec.Type.Char);
82                         String = new BuildinTypeSpec (MemberKind.Class, "System", "String", BuildinTypeSpec.Type.String);
83                         Float = new BuildinTypeSpec (MemberKind.Struct, "System", "Single", BuildinTypeSpec.Type.Float);
84                         Double = new BuildinTypeSpec (MemberKind.Struct, "System", "Double", BuildinTypeSpec.Type.Double);
85                         Decimal = new BuildinTypeSpec (MemberKind.Struct, "System", "Decimal", BuildinTypeSpec.Type.Decimal);
86                         Bool = new BuildinTypeSpec (MemberKind.Struct, "System", "Boolean", BuildinTypeSpec.Type.Bool);
87                         IntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuildinTypeSpec.Type.IntPtr);
88                         UIntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuildinTypeSpec.Type.UIntPtr);
89
90                         MulticastDelegate = new BuildinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuildinTypeSpec.Type.MulticastDelegate);
91                         Delegate = new BuildinTypeSpec (MemberKind.Class, "System", "Delegate", BuildinTypeSpec.Type.Delegate);
92                         Enum = new BuildinTypeSpec (MemberKind.Class, "System", "Enum", BuildinTypeSpec.Type.Enum);
93                         Array = new BuildinTypeSpec (MemberKind.Class, "System", "Array", BuildinTypeSpec.Type.Array);
94                         Void = new BuildinTypeSpec (MemberKind.Struct, "System", "Void", BuildinTypeSpec.Type.Void);
95                         Type = new BuildinTypeSpec (MemberKind.Class, "System", "Type", BuildinTypeSpec.Type.Type);
96                         Exception = new BuildinTypeSpec (MemberKind.Class, "System", "Exception", BuildinTypeSpec.Type.Exception);
97                         RuntimeFieldHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuildinTypeSpec.Type.RuntimeFieldHandle);
98                         RuntimeTypeHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuildinTypeSpec.Type.RuntimeTypeHandle);
99
100                         types = new BuildinTypeSpec[] {
101                                 Object, ValueType, Attribute,
102                                 Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String,
103                                 Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable,
104                                 IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception };
105
106                         // Deal with obsolete static types
107                         // TODO: remove
108                         TypeManager.object_type = Object;
109                         TypeManager.value_type = ValueType;
110                         TypeManager.string_type = String;
111                         TypeManager.int32_type = Int;
112                         TypeManager.uint32_type = UInt;
113                         TypeManager.int64_type = Long;
114                         TypeManager.uint64_type = ULong;
115                         TypeManager.float_type = Float;
116                         TypeManager.double_type = Double;
117                         TypeManager.char_type = Char;
118                         TypeManager.short_type = Short;
119                         TypeManager.decimal_type = Decimal;
120                         TypeManager.bool_type = Bool;
121                         TypeManager.sbyte_type = SByte;
122                         TypeManager.byte_type = Byte;
123                         TypeManager.ushort_type = UShort;
124                         TypeManager.enum_type = Enum;
125                         TypeManager.delegate_type = Delegate;
126                         TypeManager.multicast_delegate_type = MulticastDelegate; ;
127                         TypeManager.void_type = Void;
128                         TypeManager.array_type = Array; ;
129                         TypeManager.runtime_handle_type = RuntimeTypeHandle;
130                         TypeManager.type_type = Type;
131                         TypeManager.ienumerator_type = IEnumerator;
132                         TypeManager.ienumerable_type = IEnumerable;
133                         TypeManager.idisposable_type = IDisposable;
134                         TypeManager.intptr_type = IntPtr;
135                         TypeManager.uintptr_type = UIntPtr;
136                         TypeManager.runtime_field_handle_type = RuntimeFieldHandle;
137                         TypeManager.attribute_type = Attribute;
138                         TypeManager.exception_type = Exception;
139                 }
140
141                 #region Properties
142
143                 public BuildinTypeSpec[] Types {
144                         get {
145                                 return types;
146                         }
147                 }
148
149                 #endregion
150         }
151
152         //
153         // Compiler predefined types. Usually used for compiler generated
154         // code or for comparison against well known framework type
155         //
156         class PredefinedTypes
157         {
158                 // TODO: These two exist only to reject type comparison
159                 public readonly PredefinedType TypedReference;
160                 public readonly PredefinedType ArgIterator;
161
162                 public readonly PredefinedType MarshalByRefObject;
163                 public readonly PredefinedType RuntimeHelpers;
164                 public readonly PredefinedType IAsyncResult;
165                 public readonly PredefinedType AsyncCallback;
166                 public readonly PredefinedType RuntimeArgumentHandle;
167                 public readonly PredefinedType CharSet;
168                 public readonly PredefinedType IsVolatile;
169                 public readonly PredefinedType IEnumeratorGeneric;
170                 public readonly PredefinedType IListGeneric;
171                 public readonly PredefinedType ICollectionGeneric;
172                 public readonly PredefinedType IEnumerableGeneric;
173                 public readonly PredefinedType Nullable;
174                 public readonly PredefinedType Activator;
175                 public readonly PredefinedType Interlocked;
176                 public readonly PredefinedType Monitor;
177                 public readonly PredefinedType NotSupportedException;
178                 public readonly PredefinedType RuntimeFieldHandle;
179                 public readonly PredefinedType RuntimeMethodHandle;
180
181                 //
182                 // C# 3.0
183                 //
184                 public readonly PredefinedType Expression;
185                 public readonly PredefinedType ExpressionGeneric;
186                 public readonly PredefinedType ParameterExpression;
187                 public readonly PredefinedType FieldInfo;
188                 public readonly PredefinedType MethodBase;
189                 public readonly PredefinedType MethodInfo;
190                 public readonly PredefinedType ConstructorInfo;
191
192                 //
193                 // C# 4.0
194                 //
195                 public readonly PredefinedType Binder;
196                 public readonly PredefinedType CallSite;
197                 public readonly PredefinedType CallSiteGeneric;
198                 public readonly PredefinedType BinderFlags;
199
200                 public PredefinedTypes (ModuleContainer module)
201                 {
202                         TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
203                         ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator");
204                         MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject");
205                         RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers");
206                         IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult");
207                         AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback");
208                         RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle");
209                         CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet");
210                         IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile");
211                         IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1);
212                         IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1);
213                         ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1);
214                         IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1);
215                         Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1);
216                         Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator");
217                         Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked");
218                         Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor");
219                         NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException");
220                         RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle");
221                         RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle");
222
223                         Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression");
224                         ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1);
225                         ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression");
226                         FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo");
227                         MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase");
228                         MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo");
229                         ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo");
230
231                         CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite");
232                         CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1);
233                         Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder");
234                         BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags");
235
236                         //
237                         // Define types which are used for comparison. It does not matter
238                         // if they don't exist as no error report is needed
239                         //
240                         TypedReference.Define ();
241                         ArgIterator.Define ();
242                         MarshalByRefObject.Define ();
243                         CharSet.Define ();
244
245                         IEnumerableGeneric.Define ();
246                         IListGeneric.Define ();
247                         ICollectionGeneric.Define ();
248                         IEnumerableGeneric.Define ();
249                         IEnumeratorGeneric.Define ();
250                         Nullable.Define ();
251                         ExpressionGeneric.Define ();
252
253                         // Deal with obsolete static types
254                         // TODO: remove
255                         TypeManager.typed_reference_type = TypedReference.TypeSpec;
256                         TypeManager.arg_iterator_type = ArgIterator.TypeSpec;
257                         TypeManager.mbr_type = MarshalByRefObject.TypeSpec;
258                         TypeManager.generic_ilist_type = IListGeneric.TypeSpec;
259                         TypeManager.generic_icollection_type = ICollectionGeneric.TypeSpec;
260                         TypeManager.generic_ienumerator_type = IEnumeratorGeneric.TypeSpec;
261                         TypeManager.generic_ienumerable_type = IEnumerableGeneric.TypeSpec;
262                         TypeManager.generic_nullable_type = Nullable.TypeSpec;
263                         TypeManager.expression_type = ExpressionGeneric.TypeSpec;
264                 }
265         }
266
267         public class PredefinedType
268         {
269                 string name;
270                 string ns;
271                 int arity;
272                 MemberKind kind;
273                 ModuleContainer module;
274                 protected TypeSpec type;
275
276                 public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
277                         : this (module, kind, ns, name)
278                 {
279                         this.arity = arity;
280                 }
281
282                 public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name)
283                 {
284                         this.module = module;
285                         this.kind = kind;
286                         this.name = name;
287                         this.ns = ns;
288                 }
289
290                 #region Properties
291
292                 public int Arity {
293                         get {
294                                 return arity;
295                         }
296                 }
297
298                 public bool IsDefined {
299                         get {
300                                 return type != null;
301                         }
302                 }
303
304                 public string Name {
305                         get {
306                                 return name;
307                         }
308                 }
309
310                 public string Namespace {
311                         get {
312                                 return ns;
313                         }
314                 }
315
316                 public TypeSpec TypeSpec {
317                         get {
318                                 return type;
319                         }
320                 }
321
322                 #endregion
323
324                 public bool Define ()
325                 {
326                         if (type != null)
327                                 return true;
328
329                         Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
330                         var te = type_ns.LookupType (module.Compiler, name, arity, true, Location.Null);
331                         if (te == null)
332                                 return false;
333
334                         if (te.Type.Kind != kind)
335                                 return false;
336
337                         type = te.Type;
338                         return true;
339                 }
340
341                 public string GetSignatureForError ()
342                 {
343                         return ns + "." + name;
344                 }
345
346                 public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, Location loc)
347                 {
348                         Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
349                         var te = type_ns.LookupType (module.Compiler, name, arity, false, Location.Null);
350                         if (te == null) {
351                                 module.Compiler.Report.Error (518, loc, "The predefined type `{0}.{1}' is not defined or imported", ns, name);
352                                 return null;
353                         }
354
355                         var type = te.Type;
356                         if (type.Kind != kind) {
357                                 module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name);
358                                 return null;
359                         }
360
361                         return type;
362                 }
363
364                 public TypeSpec Resolve (Location loc)
365                 {
366                         if (type == null)
367                                 type = Resolve (module, kind, ns, name, arity, loc);
368
369                         return type;
370                 }
371         }
372
373         partial class TypeManager {
374         //
375         // A list of core types that the compiler requires or uses
376         //
377         static public BuildinTypeSpec object_type;
378         static public BuildinTypeSpec value_type;
379         static public BuildinTypeSpec string_type;
380         static public BuildinTypeSpec int32_type;
381         static public BuildinTypeSpec uint32_type;
382         static public BuildinTypeSpec int64_type;
383         static public BuildinTypeSpec uint64_type;
384         static public BuildinTypeSpec float_type;
385         static public BuildinTypeSpec double_type;
386         static public BuildinTypeSpec char_type;
387         static public BuildinTypeSpec short_type;
388         static public BuildinTypeSpec decimal_type;
389         static public BuildinTypeSpec bool_type;
390         static public BuildinTypeSpec sbyte_type;
391         static public BuildinTypeSpec byte_type;
392         static public BuildinTypeSpec ushort_type;
393         static public BuildinTypeSpec enum_type;
394         static public BuildinTypeSpec delegate_type;
395         static public BuildinTypeSpec multicast_delegate_type;
396         static public BuildinTypeSpec void_type;
397         static public BuildinTypeSpec array_type;
398         static public BuildinTypeSpec runtime_handle_type;
399         static public BuildinTypeSpec type_type;
400         static public BuildinTypeSpec ienumerator_type;
401         static public BuildinTypeSpec ienumerable_type;
402         static public BuildinTypeSpec idisposable_type;
403         static public BuildinTypeSpec intptr_type;
404         static public BuildinTypeSpec uintptr_type;
405         static public BuildinTypeSpec runtime_field_handle_type;
406         static public BuildinTypeSpec attribute_type;
407         static public BuildinTypeSpec exception_type;
408
409
410         static public TypeSpec typed_reference_type;
411         static public TypeSpec arg_iterator_type;
412         static public TypeSpec mbr_type;
413         static public TypeSpec generic_ilist_type;
414         static public TypeSpec generic_icollection_type;
415         static public TypeSpec generic_ienumerator_type;
416         static public TypeSpec generic_ienumerable_type;
417         static public TypeSpec generic_nullable_type;
418         static internal TypeSpec expression_type;
419
420         //
421         // These methods are called by code generated by the compiler
422         //
423         static public FieldSpec string_empty;
424         static public MethodSpec system_type_get_type_from_handle;
425         static public MethodSpec bool_movenext_void;
426         static public MethodSpec void_dispose_void;
427         static public MethodSpec void_monitor_enter_object;
428         static public MethodSpec void_monitor_exit_object;
429         static public MethodSpec void_initializearray_array_fieldhandle;
430         static public MethodSpec delegate_combine_delegate_delegate;
431         static public MethodSpec delegate_remove_delegate_delegate;
432         static public PropertySpec int_get_offset_to_string_data;
433         static public MethodSpec int_interlocked_compare_exchange;
434         public static MethodSpec gen_interlocked_compare_exchange;
435         static public PropertySpec ienumerator_getcurrent;
436         public static MethodSpec methodbase_get_type_from_handle;
437         public static MethodSpec methodbase_get_type_from_handle_generic;
438         public static MethodSpec fieldinfo_get_field_from_handle;
439         public static MethodSpec fieldinfo_get_field_from_handle_generic;
440         public static MethodSpec activator_create_instance;
441
442         //
443         // The constructors.
444         //
445         static public MethodSpec void_decimal_ctor_five_args;
446         static public MethodSpec void_decimal_ctor_int_arg;
447         public static MethodSpec void_decimal_ctor_long_arg;
448
449         static TypeManager ()
450         {
451                 Reset ();
452         }
453
454         static public void Reset ()
455         {
456 //              object_type = null;
457         
458                 // TODO: I am really bored by all this static stuff
459                 system_type_get_type_from_handle =
460                 bool_movenext_void =
461                 void_dispose_void =
462                 void_monitor_enter_object =
463                 void_monitor_exit_object =
464                 void_initializearray_array_fieldhandle =
465                 int_interlocked_compare_exchange =
466                 gen_interlocked_compare_exchange =
467                 methodbase_get_type_from_handle =
468                 methodbase_get_type_from_handle_generic =
469                 fieldinfo_get_field_from_handle =
470                 fieldinfo_get_field_from_handle_generic =
471                 activator_create_instance =
472                 delegate_combine_delegate_delegate =
473                 delegate_remove_delegate_delegate = null;
474
475                 int_get_offset_to_string_data =
476                 ienumerator_getcurrent = null;
477
478                 void_decimal_ctor_five_args =
479                 void_decimal_ctor_int_arg =
480                 void_decimal_ctor_long_arg = null;
481
482                 string_empty = null;
483
484                 typed_reference_type = arg_iterator_type = mbr_type =
485                 generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
486                 generic_ienumerable_type = generic_nullable_type = expression_type = null;
487         }
488
489         /// <summary>
490         ///   Returns the C# name of a type if possible, or the full type name otherwise
491         /// </summary>
492         static public string CSharpName (TypeSpec t)
493         {
494                 return t.GetSignatureForError ();
495         }
496
497         static public string CSharpName (IList<TypeSpec> types)
498         {
499                 if (types.Count == 0)
500                         return string.Empty;
501
502                 StringBuilder sb = new StringBuilder ();
503                 for (int i = 0; i < types.Count; ++i) {
504                         if (i > 0)
505                                 sb.Append (",");
506
507                         sb.Append (CSharpName (types [i]));
508                 }
509                 return sb.ToString ();
510         }
511
512         static public string GetFullNameSignature (MemberSpec mi)
513         {
514                 return mi.GetSignatureForError ();
515         }
516
517         static public string CSharpSignature (MemberSpec mb)
518         {
519                 return mb.GetSignatureForError ();
520         }
521
522         static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, bool optional, Location loc)
523         {
524                 var member = MemberCache.FindMember (t, filter, BindingRestriction.DeclaredOnly);
525
526                 if (member != null && member.IsAccessible (InternalType.FakeInternalType))
527                         return member;
528
529                 if (optional)
530                         return member;
531
532                 string method_args = null;
533                 if (filter.Parameters != null)
534                         method_args = filter.Parameters.GetSignatureForError ();
535
536                 RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
537                         TypeManager.CSharpName (t), filter.Name, method_args);
538
539                 return null;
540         }
541
542         //
543         // Returns the ConstructorInfo for "args"
544         //
545         public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
546         {
547                 var pc = ParametersCompiled.CreateFullyResolved (args);
548                 return GetPredefinedMember (t, MemberFilter.Constructor (pc), false, loc) as MethodSpec;
549         }
550
551         //
552         // Returns the method specification for a method named `name' defined
553         // in type `t' which takes arguments of types `args'
554         //
555         public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
556         {
557                 var pc = ParametersCompiled.CreateFullyResolved (args);
558                 return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), false, loc);
559         }
560
561         public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
562         {
563                 return GetPredefinedMethod (t, filter, false, loc);
564         }
565
566         public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, bool optional, Location loc)
567         {
568                 return GetPredefinedMember (t, filter, optional, loc) as MethodSpec;
569         }
570
571         public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
572         {
573                 return GetPredefinedMember (t, MemberFilter.Field (name, type), false, loc) as FieldSpec;
574         }
575
576         public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
577         {
578                 return GetPredefinedMember (t, MemberFilter.Property (name, type), false, loc) as PropertySpec;
579         }
580
581         /// <remarks>
582         ///   The types have to be initialized after the initial
583         ///   population of the type has happened (for example, to
584         ///   bootstrap the corlib.dll
585         /// </remarks>
586         public static bool InitCoreTypes (ModuleContainer module, BuildinTypes buildin)
587         {
588                 var ctx = module.Compiler;
589                 foreach (var p in buildin.Types) {
590                         var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity, Location.Null);
591                         if (found == null || found == p)
592                                 continue;
593
594                         if (!RootContext.StdLib) {
595                                 var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
596                                 ns.ReplaceTypeWithPredefined (found, p);
597
598                                 var tc = found.MemberDefinition as TypeContainer;
599                                 tc.SetPredefinedSpec (p);
600                                 p.SetDefinition (found);
601                         }
602                 }
603
604                 if (InternalType.Dynamic.GetMetaInfo () == null) {
605                         InternalType.Dynamic.SetMetaInfo (object_type.GetMetaInfo ());
606
607                         if (object_type.MemberDefinition.IsImported)
608                                 InternalType.Dynamic.MemberCache = object_type.MemberCache;
609
610                         InternalType.Null.SetMetaInfo (object_type.GetMetaInfo ());
611                 }
612
613                 return ctx.Report.Errors == 0;
614         }
615
616         public static bool IsBuiltinType (TypeSpec t)
617         {
618                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
619                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
620                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
621                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
622                         return true;
623                 else
624                         return false;
625         }
626
627         //
628         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
629         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
630         // 
631         public static bool IsPrimitiveType (TypeSpec t)
632         {
633                 return (t == int32_type || t == uint32_type ||
634                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
635                     t == char_type || t == short_type || t == bool_type ||
636                     t == sbyte_type || t == byte_type || t == ushort_type);
637         }
638
639         // Obsolete
640         public static bool IsDelegateType (TypeSpec t)
641         {
642                 return t.IsDelegate;
643         }
644         
645         // Obsolete
646         public static bool IsEnumType (TypeSpec t)
647         {
648                 return t.IsEnum;
649         }
650
651         public static bool IsBuiltinOrEnum (TypeSpec t)
652         {
653                 if (IsBuiltinType (t))
654                         return true;
655                 
656                 if (IsEnumType (t))
657                         return true;
658
659                 return false;
660         }
661
662         //
663         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
664         //
665         public static bool IsUnmanagedType (TypeSpec t)
666         {
667                 var ds = t.MemberDefinition as DeclSpace;
668                 if (ds != null)
669                         return ds.IsUnmanagedType ();
670
671                 // some builtins that are not unmanaged types
672                 if (t == TypeManager.object_type || t == TypeManager.string_type)
673                         return false;
674
675                 if (IsBuiltinOrEnum (t))
676                         return true;
677
678                 // Someone did the work of checking if the ElementType of t is unmanaged.  Let's not repeat it.
679                 if (t.IsPointer)
680                         return IsUnmanagedType (GetElementType (t));
681
682                 if (!IsValueType (t))
683                         return false;
684
685                 if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
686                         return false;
687
688                 return true;
689         }
690
691         //
692         // Null is considered to be a reference type
693         //                      
694         public static bool IsReferenceType (TypeSpec t)
695         {
696                 if (t.IsGenericParameter)
697                         return ((TypeParameterSpec) t).IsReferenceType;
698
699                 return !t.IsStruct && !IsEnumType (t);
700         }                       
701                 
702         public static bool IsValueType (TypeSpec t)
703         {
704                 if (t.IsGenericParameter)
705                         return ((TypeParameterSpec) t).IsValueType;
706
707                 return t.IsStruct || IsEnumType (t);
708         }
709
710         public static bool IsStruct (TypeSpec t)
711         {
712                 return t.IsStruct;
713         }
714
715         public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
716         {
717 //              TypeParameter tparam = LookupTypeParameter (type);
718 //              TypeParameter pparam = LookupTypeParameter (parent);
719
720                 if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
721                         if (type == parent)
722                                 return true;
723
724                         throw new NotImplementedException ("net");
725 //                      return tparam.IsSubclassOf (parent);
726                 }
727
728                 do {
729                         if (IsInstantiationOfSameGenericType (type, parent))
730                                 return true;
731
732                         type = type.BaseType;
733                 } while (type != null);
734
735                 return false;
736         }
737
738         //
739         // Checks whether `type' is a subclass or nested child of `base_type'.
740         //
741         public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type)
742         {
743                 do {
744                         if (IsFamilyAccessible (type, base_type))
745                                 return true;
746
747                         // Handle nested types.
748                         type = type.DeclaringType;
749                 } while (type != null);
750
751                 return false;
752         }
753
754         //
755         // Checks whether `type' is a nested child of `parent'.
756         //
757         public static bool IsNestedChildOf (TypeSpec type, TypeSpec parent)
758         {
759                 if (type == null)
760                         return false;
761
762                 type = type.GetDefinition (); // DropGenericTypeArguments (type);
763                 parent = parent.GetDefinition (); // DropGenericTypeArguments (parent);
764
765                 if (type == parent)
766                         return false;
767
768                 type = type.DeclaringType;
769                 while (type != null) {
770                         if (type.GetDefinition () == parent)
771                                 return true;
772
773                         type = type.DeclaringType;
774                 }
775
776                 return false;
777         }
778
779         public static bool IsSpecialType (TypeSpec t)
780         {
781                 return t == arg_iterator_type || t == typed_reference_type;
782         }
783
784         public static TypeSpec GetElementType (TypeSpec t)
785         {
786                 return ((ElementTypeSpec)t).Element;
787         }
788
789         /// <summary>
790         /// This method is not implemented by MS runtime for dynamic types
791         /// </summary>
792         public static bool HasElementType (TypeSpec t)
793         {
794                 return t is ElementTypeSpec;
795         }
796
797         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
798
799         // This is a custom version of Convert.ChangeType() which works
800         // with the TypeBuilder defined types when compiling corlib.
801         public static object ChangeType (object value, TypeSpec targetType, out bool error)
802         {
803                 IConvertible convert_value = value as IConvertible;
804                 
805                 if (convert_value == null){
806                         error = true;
807                         return null;
808                 }
809                 
810                 //
811                 // We cannot rely on build-in type conversions as they are
812                 // more limited than what C# supports.
813                 // See char -> float/decimal/double conversion
814                 //
815                 error = false;
816                 try {
817                         if (targetType == TypeManager.bool_type)
818                                 return convert_value.ToBoolean (nf_provider);
819                         if (targetType == TypeManager.byte_type)
820                                 return convert_value.ToByte (nf_provider);
821                         if (targetType == TypeManager.char_type)
822                                 return convert_value.ToChar (nf_provider);
823                         if (targetType == TypeManager.short_type)
824                                 return convert_value.ToInt16 (nf_provider);
825                         if (targetType == TypeManager.int32_type)
826                                 return convert_value.ToInt32 (nf_provider);
827                         if (targetType == TypeManager.int64_type)
828                                 return convert_value.ToInt64 (nf_provider);
829                         if (targetType == TypeManager.sbyte_type)
830                                 return convert_value.ToSByte (nf_provider);
831
832                         if (targetType == TypeManager.decimal_type) {
833                                 if (convert_value.GetType () == typeof (char))
834                                         return (decimal) convert_value.ToInt32 (nf_provider);
835                                 return convert_value.ToDecimal (nf_provider);
836                         }
837
838                         if (targetType == TypeManager.double_type) {
839                                 if (convert_value.GetType () == typeof (char))
840                                         return (double) convert_value.ToInt32 (nf_provider);
841                                 return convert_value.ToDouble (nf_provider);
842                         }
843
844                         if (targetType == TypeManager.float_type) {
845                                 if (convert_value.GetType () == typeof (char))
846                                         return (float)convert_value.ToInt32 (nf_provider);
847                                 return convert_value.ToSingle (nf_provider);
848                         }
849
850                         if (targetType == TypeManager.string_type)
851                                 return convert_value.ToString (nf_provider);
852                         if (targetType == TypeManager.ushort_type)
853                                 return convert_value.ToUInt16 (nf_provider);
854                         if (targetType == TypeManager.uint32_type)
855                                 return convert_value.ToUInt32 (nf_provider);
856                         if (targetType == TypeManager.uint64_type)
857                                 return convert_value.ToUInt64 (nf_provider);
858                         if (targetType == TypeManager.object_type)
859                                 return value;
860
861                         error = true;
862                 } catch {
863                         error = true;
864                 }
865                 return null;
866         }
867
868         /// <summary>
869         ///   Utility function that can be used to probe whether a type
870         ///   is managed or not.  
871         /// </summary>
872         public static bool VerifyUnmanaged (CompilerContext ctx, TypeSpec t, Location loc)
873         {
874                 while (t.IsPointer)
875                         t = GetElementType (t);
876
877                 if (IsUnmanagedType (t))
878                         return true;
879
880                 ctx.Report.SymbolRelatedToPreviousError (t);
881                 ctx.Report.Error (208, loc,
882                         "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
883                         CSharpName (t));
884
885                 return false;   
886         }
887 #region Generics
888         // This method always return false for non-generic compiler,
889         // while Type.IsGenericParameter is returned if it is supported.
890         public static bool IsGenericParameter (TypeSpec type)
891         {
892                 return type.IsGenericParameter;
893         }
894
895         public static bool IsGenericType (TypeSpec type)
896         {
897                 return type.IsGeneric;
898         }
899
900         // TODO: Implement correctly
901         public static bool ContainsGenericParameters (TypeSpec type)
902         {
903                 return type.GetMetaInfo ().ContainsGenericParameters;
904         }
905
906         public static TypeSpec[] GetTypeArguments (TypeSpec t)
907         {
908                 // TODO: return empty array !!
909                 return t.TypeArguments;
910         }
911
912         /// <summary>
913         ///   Check whether `type' and `parent' are both instantiations of the same
914         ///   generic type.  Note that we do not check the type parameters here.
915         /// </summary>
916         public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent)
917         {
918                 return type == parent || type.MemberDefinition == parent.MemberDefinition;
919         }
920
921         public static bool IsNullableType (TypeSpec t)
922         {
923                 return generic_nullable_type == t.GetDefinition ();
924         }
925 #endregion
926 }
927
928 }