74e700fe7f293a7513b6b889235e89aec03cc464
[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 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 //
11 //
12
13 //
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change 
15 // the behavior of the compilation.  This can be removed if we rework
16 // the code to get a list of namespaces available.
17 //
18 #define SIMPLE_SPEEDUP
19
20 using System;
21 using System.IO;
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Text;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
30
31 namespace Mono.CSharp {
32
33 public class TypeManager {
34         //
35         // A list of core types that the compiler requires or uses
36         //
37         static public Type object_type;
38         static public Type value_type;
39         static public Type string_type;
40         static public Type int32_type;
41         static public Type uint32_type;
42         static public Type int64_type;
43         static public Type uint64_type;
44         static public Type float_type;
45         static public Type double_type;
46         static public Type char_type;
47         static public Type char_ptr_type;
48         static public Type short_type;
49         static public Type decimal_type;
50         static public Type bool_type;
51         static public Type sbyte_type;
52         static public Type byte_type;
53         static public Type ushort_type;
54         static public Type enum_type;
55         static public Type delegate_type;
56         static public Type multicast_delegate_type;
57         static public Type void_type;
58         static public Type enumeration_type;
59         static public Type array_type;
60         static public Type runtime_handle_type;
61         static public Type icloneable_type;
62         static public Type type_type;
63         static public Type ienumerator_type;
64         static public Type ienumerable_type;
65         static public Type idisposable_type;
66         static public Type iconvertible_type;
67         static public Type default_member_type;
68         static public Type iasyncresult_type;
69         static public Type asynccallback_type;
70         static public Type intptr_type;
71         static public Type monitor_type;
72         static public Type runtime_field_handle_type;
73         static public Type runtime_argument_handle_type;
74         static public Type attribute_type;
75         static public Type attribute_usage_type;
76         static public Type dllimport_type;
77         static public Type unverifiable_code_type;
78         static public Type methodimpl_attr_type;
79         static public Type marshal_as_attr_type;
80         static public Type param_array_type;
81         static public Type guid_attr_type;
82         static public Type void_ptr_type;
83         static public Type indexer_name_type;
84         static public Type exception_type;
85         static public Type invalid_operation_exception_type;
86         static public Type not_supported_exception_type;
87         static public Type obsolete_attribute_type;
88         static public Type conditional_attribute_type;
89         static public Type in_attribute_type;
90         static public Type anonymous_method_type;
91         static public Type cls_compliant_attribute_type;
92         static public Type typed_reference_type;
93         static public Type arg_iterator_type;
94         static public Type mbr_type;
95         static public Type struct_layout_attribute_type;
96         static public Type field_offset_attribute_type;
97         static public Type security_attr_type;
98
99         //
100         // An empty array of types
101         //
102         static public Type [] NoTypes;
103         static public TypeExpr [] NoTypeExprs;
104
105
106         // 
107         // Expressions representing the internal types.  Used during declaration
108         // definition.
109         //
110         static public TypeExpr system_object_expr, system_string_expr; 
111         static public TypeExpr system_boolean_expr, system_decimal_expr;
112         static public TypeExpr system_single_expr, system_double_expr;
113         static public TypeExpr system_sbyte_expr, system_byte_expr;
114         static public TypeExpr system_int16_expr, system_uint16_expr;
115         static public TypeExpr system_int32_expr, system_uint32_expr;
116         static public TypeExpr system_int64_expr, system_uint64_expr;
117         static public TypeExpr system_char_expr, system_void_expr;
118         static public TypeExpr system_asynccallback_expr;
119         static public TypeExpr system_iasyncresult_expr;
120         static public TypeExpr system_valuetype_expr;
121         static public TypeExpr system_intptr_expr;
122
123         //
124         // This is only used when compiling corlib
125         //
126         static public Type system_int32_type;
127         static public Type system_array_type;
128         static public Type system_type_type;
129         static public Type system_assemblybuilder_type;
130         static public MethodInfo system_int_array_get_length;
131         static public MethodInfo system_int_array_get_rank;
132         static public MethodInfo system_object_array_clone;
133         static public MethodInfo system_int_array_get_length_int;
134         static public MethodInfo system_int_array_get_lower_bound_int;
135         static public MethodInfo system_int_array_get_upper_bound_int;
136         static public MethodInfo system_void_array_copyto_array_int;
137
138         
139         //
140         // Internal, not really used outside
141         //
142         static Type runtime_helpers_type;
143         
144         //
145         // These methods are called by code generated by the compiler
146         //
147         static public MethodInfo string_concat_string_string;
148         static public MethodInfo string_concat_string_string_string;
149         static public MethodInfo string_concat_string_string_string_string;
150         static public MethodInfo string_concat_string_dot_dot_dot;
151         static public MethodInfo string_concat_object_object;
152         static public MethodInfo string_concat_object_object_object;
153         static public MethodInfo string_concat_object_dot_dot_dot;
154         static public MethodInfo string_isinterneted_string;
155         static public MethodInfo system_type_get_type_from_handle;
156         static public MethodInfo object_getcurrent_void;
157         static public MethodInfo bool_movenext_void;
158         static public MethodInfo ienumerable_getenumerator_void;
159         static public MethodInfo void_reset_void;
160         static public MethodInfo void_dispose_void;
161         static public MethodInfo void_monitor_enter_object;
162         static public MethodInfo void_monitor_exit_object;
163         static public MethodInfo void_initializearray_array_fieldhandle;
164         static public MethodInfo int_getlength_int;
165         static public MethodInfo delegate_combine_delegate_delegate;
166         static public MethodInfo delegate_remove_delegate_delegate;
167         static public MethodInfo int_get_offset_to_string_data;
168         static public MethodInfo int_array_get_length;
169         static public MethodInfo int_array_get_rank;
170         static public MethodInfo object_array_clone;
171         static public MethodInfo int_array_get_length_int;
172         static public MethodInfo int_array_get_lower_bound_int;
173         static public MethodInfo int_array_get_upper_bound_int;
174         static public MethodInfo void_array_copyto_array_int;
175         
176         //
177         // The attribute constructors.
178         //
179         static public ConstructorInfo object_ctor;
180         static public ConstructorInfo cons_param_array_attribute;
181         static public ConstructorInfo void_decimal_ctor_five_args;
182         static public ConstructorInfo unverifiable_code_ctor;
183         static public ConstructorInfo invalid_operation_ctor;
184         static public ConstructorInfo default_member_ctor;
185         
186         // <remarks>
187         //   Holds the Array of Assemblies that have been loaded
188         //   (either because it is the default or the user used the
189         //   -r command line option)
190         // </remarks>
191         static Assembly [] assemblies;
192
193         // <remarks>
194         //  Keeps a list of modules. We used this to do lookups
195         //  on the module using GetType -- needed for arrays
196         // </remarks>
197         static Module [] modules;
198
199         // <remarks>
200         //   This is the type_cache from the assemblies to avoid
201         //   hitting System.Reflection on every lookup.
202         // </summary>
203         static Hashtable types;
204
205         // <remarks>
206         //  This is used to hotld the corresponding TypeContainer objects
207         //  since we need this in FindMembers
208         // </remarks>
209         static Hashtable typecontainers;
210
211         // <remarks>
212         //   Keeps track of those types that are defined by the
213         //   user's program
214         // </remarks>
215         static ArrayList user_types;
216
217         static PtrHashtable builder_to_declspace;
218
219         static PtrHashtable builder_to_member_cache;
220
221         // <remarks>
222         //   Tracks the interfaces implemented by typebuilders.  We only
223         //   enter those who do implement or or more interfaces
224         // </remarks>
225         static PtrHashtable builder_to_ifaces;
226
227         // <remarks>
228         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
229         //   the arguments to the method
230         // </remarks>
231         static Hashtable method_arguments;
232
233         // <remarks>
234         //   Maps PropertyBuilder to a Type array that contains
235         //   the arguments to the indexer
236         // </remarks>
237         static Hashtable indexer_arguments;
238
239         // <remarks>
240         //   Maybe `method_arguments' should be replaced and only
241         //   method_internal_params should be kept?
242         // <remarks>
243         static Hashtable method_internal_params;
244
245         // <remarks>
246         //  Keeps track of methods
247         // </remarks>
248
249         static Hashtable builder_to_method;
250
251         // <remarks>
252         //  Contains all public types from referenced assemblies.
253         //  This member is used only if CLS Compliance verification is required.
254         // </remarks>
255         public static Hashtable all_imported_types;
256
257         struct Signature {
258                 public string name;
259                 public Type [] args;
260         }
261         
262         public static void CleanUp ()
263         {
264                 // Lets get everything clean so that we can collect before generating code
265                 assemblies = null;
266                 modules = null;
267                 types = null;
268                 typecontainers = null;
269                 user_types = null;
270                 builder_to_declspace = null;
271                 builder_to_member_cache = null;
272                 builder_to_ifaces = null;
273                 method_arguments = null;
274                 indexer_arguments = null;
275                 method_internal_params = null;
276                 builder_to_method = null;
277                 
278                 fields = null;
279                 references = null;
280                 negative_hits = null;
281                 builder_to_constant = null;
282                 fieldbuilders_to_fields = null;
283                 events = null;
284                 priv_fields_events = null;
285                 properties = null;
286                 
287                 TypeHandle.CleanUp ();
288         }
289
290         /// <summary>
291         ///   A filter for Findmembers that uses the Signature object to
292         ///   extract objects
293         /// </summary>
294         static bool SignatureFilter (MemberInfo mi, object criteria)
295         {
296                 Signature sig = (Signature) criteria;
297
298                 if (!(mi is MethodBase))
299                         return false;
300                 
301                 if (mi.Name != sig.name)
302                         return false;
303
304                 int count = sig.args.Length;
305                 
306                 if (mi is MethodBuilder || mi is ConstructorBuilder){
307                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
308
309                         if (candidate_args.Length != count)
310                                 return false;
311                         
312                         for (int i = 0; i < count; i++)
313                                 if (candidate_args [i] != sig.args [i])
314                                         return false;
315                         
316                         return true;
317                 } else {
318                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
319
320                         if (pars.Length != count)
321                                 return false;
322
323                         for (int i = 0; i < count; i++)
324                                 if (pars [i].ParameterType != sig.args [i])
325                                         return false;
326                         return true;
327                 }
328         }
329
330         // A delegate that points to the filter above.
331         static MemberFilter signature_filter;
332
333         //
334         // These are expressions that represent some of the internal data types, used
335         // elsewhere
336         //
337         static void InitExpressionTypes ()
338         {
339                 system_object_expr  = new TypeLookupExpression ("System.Object");
340                 system_string_expr  = new TypeLookupExpression ("System.String");
341                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
342                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
343                 system_single_expr  = new TypeLookupExpression ("System.Single");
344                 system_double_expr  = new TypeLookupExpression ("System.Double");
345                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
346                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
347                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
348                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
349                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
350                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
351                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
352                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
353                 system_char_expr    = new TypeLookupExpression ("System.Char");
354                 system_void_expr    = new TypeLookupExpression ("System.Void");
355                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
356                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
357                 system_valuetype_expr  = new TypeLookupExpression ("System.ValueType");
358                 system_intptr_expr  = new TypeLookupExpression ("System.IntPtr");
359         }
360
361         static TypeManager ()
362         {
363                 assemblies = new Assembly [0];
364                 modules = null;
365                 user_types = new ArrayList ();
366                 
367                 types = new Hashtable ();
368                 typecontainers = new Hashtable ();
369                 
370                 builder_to_declspace = new PtrHashtable ();
371                 builder_to_member_cache = new PtrHashtable ();
372                 builder_to_method = new PtrHashtable ();
373                 method_arguments = new PtrHashtable ();
374                 method_internal_params = new PtrHashtable ();
375                 indexer_arguments = new PtrHashtable ();
376                 builder_to_ifaces = new PtrHashtable ();
377                 
378                 NoTypes = new Type [0];
379                 NoTypeExprs = new TypeExpr [0];
380
381                 signature_filter = new MemberFilter (SignatureFilter);
382                 InitExpressionTypes ();
383         }
384
385         public static void HandleDuplicate (string name, Type t)
386         {
387                 Type prev = (Type) types [name];
388                 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
389                 
390                 if (tc != null){
391                         //
392                         // This probably never happens, as we catch this before
393                         //
394                         Report.Error (-17, "The type `" + name + "' has already been defined.");
395                         return;
396                 }
397                 
398                 tc = builder_to_declspace [t] as TypeContainer;
399                 if (tc != null){
400                         Report.Warning (
401                                         1595, "The type `" + name + "' is defined in an existing assembly;"+
402                                         " Using the new definition from: " + tc.Location);
403                 } else {
404                         Report.Warning (
405                                         1595, "The type `" + name + "' is defined in an existing assembly;");
406                 }
407                 
408                 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
409                 
410                 types.Remove (name);
411                 types.Add (name, t);
412         }
413         
414         public static void AddUserType (string name, TypeBuilder t)
415         {
416                 try {
417                         types.Add (name, t);
418                 } catch {
419                         HandleDuplicate (name, t); 
420                 }
421                 user_types.Add (t);
422         }
423
424         //
425         // This entry point is used by types that we define under the covers
426         // 
427         public static void RegisterBuilder (Type tb, Type [] ifaces)
428         {
429                 if (ifaces != null)
430                         builder_to_ifaces [tb] = ifaces;
431         }
432         
433         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
434         {
435                 builder_to_declspace.Add (t, tc);
436                 typecontainers.Add (name, tc);
437                 AddUserType (name, t);
438         }
439
440         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
441         {
442                 try {
443                         types.Add (name, t);
444                 } catch {
445                         HandleDuplicate (name, t);
446                 }
447                 
448                 builder_to_declspace.Add (t, del);
449         }
450         
451         public static void AddEnumType (string name, TypeBuilder t, Enum en)
452         {
453                 try {
454                         types.Add (name, t);
455                 } catch {
456                         HandleDuplicate (name, t);
457                 }
458                 builder_to_declspace.Add (t, en);
459         }
460
461         public static void AddMethod (MethodBase builder, IMethodData method)
462         {
463                 builder_to_method.Add (builder, method);
464         }
465
466         public static IMethodData GetMethod (MethodBase builder)
467         {
468                 return (IMethodData) builder_to_method [builder];
469         }
470
471         /// <summary>
472         ///   Returns the DeclSpace whose Type is `t' or null if there is no
473         ///   DeclSpace for `t' (ie, the Type comes from a library)
474         /// </summary>
475         public static DeclSpace LookupDeclSpace (Type t)
476         {
477                 return builder_to_declspace [t] as DeclSpace;
478         }
479
480         /// <summary>
481         ///   Returns the TypeContainer whose Type is `t' or null if there is no
482         ///   TypeContainer for `t' (ie, the Type comes from a library)
483         /// </summary>
484         public static TypeContainer LookupTypeContainer (Type t)
485         {
486                 return builder_to_declspace [t] as TypeContainer;
487         }
488
489         public static IMemberContainer LookupMemberContainer (Type t)
490         {
491                 if (t is TypeBuilder) {
492                         IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
493                         if (container != null)
494                                 return container;
495                 }
496
497                 return TypeHandle.GetTypeHandle (t);
498         }
499
500         public static MemberCache LookupInterfaceCache (IMemberContainer container, Type t)
501         {
502                 MemberCache cache = builder_to_member_cache [t] as MemberCache;
503                 if (cache != null)
504                         return cache;
505
506                 cache = new MemberCache (container, GetInterfaces (t));
507                 builder_to_member_cache.Add (t, cache);
508                 return cache;
509         }
510
511         public static TypeContainer LookupInterface (Type t)
512         {
513                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
514                 if ((tc == null) || (tc.Kind != Kind.Interface))
515                         return null;
516
517                 return tc;
518         }
519
520         public static Delegate LookupDelegate (Type t)
521         {
522                 return builder_to_declspace [t] as Delegate;
523         }
524
525         public static Enum LookupEnum (Type t)
526         {
527                 return builder_to_declspace [t] as Enum;
528         }
529
530         public static Class LookupClass (Type t)
531         {
532                 return (Class) builder_to_declspace [t];
533         }
534         
535         /// <summary>
536         ///   Registers an assembly to load types from.
537         /// </summary>
538         public static void AddAssembly (Assembly a)
539         {
540                 foreach (Assembly assembly in assemblies) {
541                         if (a == assembly)
542                                 return;
543                 }
544
545                 int top = assemblies.Length;
546                 Assembly [] n = new Assembly [top + 1];
547
548                 assemblies.CopyTo (n, 0);
549                 
550                 n [top] = a;
551                 assemblies = n;
552         }
553
554         public static Assembly [] GetAssemblies ()
555         {
556                 return assemblies;
557         }
558
559         /// <summary>
560         ///  Registers a module builder to lookup types from
561         /// </summary>
562         public static void AddModule (Module mb)
563         {
564                 int top = modules != null ? modules.Length : 0;
565                 Module [] n = new Module [top + 1];
566
567                 if (modules != null)
568                         modules.CopyTo (n, 0);
569                 n [top] = mb;
570                 modules = n;
571         }
572
573         public static Module[] Modules {
574                 get {
575                         return modules;
576                 }
577         }
578
579         static Hashtable references = new Hashtable ();
580         
581         //
582         // Gets the reference to T version of the Type (T&)
583         //
584         public static Type GetReferenceType (Type t)
585         {
586                 string tname = t.FullName + "&";
587                 
588                 Type ret = t.Assembly.GetType (tname);
589
590                 //
591                 // If the type comes from the assembly we are building
592                 // We need the Hashtable, because .NET 1.1 will return different instance types
593                 // every time we call ModuleBuilder.GetType.
594                 //
595                 if (ret == null){
596                         if (references [t] == null)
597                                 references [t] = CodeGen.Module.Builder.GetType (tname);
598                         ret = (Type) references [t];
599                 }
600
601                 return ret;
602         }
603
604         static Hashtable pointers = new Hashtable ();
605
606         //
607         // Gets the pointer to T version of the Type  (T*)
608         //
609         public static Type GetPointerType (Type t)
610         {
611                 string tname = t.FullName + "*";
612                 
613                 Type ret = t.Assembly.GetType (tname);
614                 
615                 //
616                 // If the type comes from the assembly we are building
617                 // We need the Hashtable, because .NET 1.1 will return different instance types
618                 // every time we call ModuleBuilder.GetType.
619                 //
620                 if (ret == null){
621                         if (pointers [t] == null)
622                                 pointers [t] = CodeGen.Module.Builder.GetType (tname);
623                         
624                         ret = (Type) pointers [t];
625                 }
626
627                 return ret;
628         }
629         
630         //
631         // Low-level lookup, cache-less
632         //
633         static Type LookupTypeReflection (string name)
634         {
635                 Type t;
636
637                 foreach (Assembly a in assemblies){
638                         t = a.GetType (name);
639                         if (t == null)
640                                 continue;
641
642                         do {
643                                 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
644                                 if (ta == TypeAttributes.NotPublic ||
645                                     ta == TypeAttributes.NestedPrivate ||
646                                     ta == TypeAttributes.NestedAssembly ||
647                                     ta == TypeAttributes.NestedFamANDAssem){
648                                         
649                                         //
650                                         // In .NET pointers turn out to be private, even if their
651                                         // element type is not
652                                         //
653                                         if (t.IsPointer){
654                                                 t = t.GetElementType ();
655                                                 continue;
656                                         } else
657                                                 t = null;
658                                 } else {
659                                         return t;
660                                 }
661                         } while (t != null);
662                 }
663
664                 foreach (Module mb in modules) {
665                         t = mb.GetType (name);
666                         if (t != null) 
667                                 return t;
668                 }
669                         
670                 return null;
671         }
672
673         static Hashtable negative_hits = new Hashtable ();
674         
675         //
676         // This function is used when you want to avoid the lookups, and want to go
677         // directly to the source.  This will use the cache.
678         //
679         // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
680         // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
681         // way to test things other than doing a fullname compare
682         //
683         public static Type LookupTypeDirect (string name)
684         {
685                 Type t = (Type) types [name];
686                 if (t != null)
687                         return t;
688                 
689                 if (negative_hits.Contains (name))
690                         return null;
691                 
692                 t = LookupTypeReflection (name);
693                 
694                 if (t == null)
695                         negative_hits [name] = null;
696                 else
697                         types [name] = t;
698                 
699                 return t;
700         }
701         
702         static readonly char [] dot_array = { '.' };
703
704         /// <summary>
705         ///   Returns the Type associated with @name, takes care of the fact that
706         ///   reflection expects nested types to be separated from the main type
707         ///   with a "+" instead of a "."
708         /// </summary>
709         public static Type LookupType (string name)
710         {
711                 Type t;
712
713                 //
714                 // First lookup in user defined and cached values
715                 //
716
717                 t = (Type) types [name];
718                 if (t != null)
719                         return t;
720
721                 // Two thirds of the failures are caught here.
722                 if (negative_hits.Contains (name))
723                         return null;
724
725                 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
726                 string [] elements = name.Split (dot_array);
727                 int count = elements.Length;
728
729                 for (int n = 1; n <= count; n++){
730                         string top_level_type = String.Join (".", elements, 0, n);
731
732                         // One third of the failures are caught here.
733                         if (negative_hits.Contains (top_level_type))
734                                 continue;
735                         
736                         t = (Type) types [top_level_type];
737                         if (t == null){
738                                 t = LookupTypeReflection (top_level_type);
739                                 if (t == null){
740                                         negative_hits [top_level_type] = null;
741                                         continue;
742                                 }
743                         }
744                         
745                         if (count == n){
746                                 types [name] = t;
747                                 return t;
748                         } 
749
750                         //
751                         // We know that System.Object does not have children, and since its the parent of 
752                         // all the objects, it always gets probbed for inner classes. 
753                         //
754                         if (top_level_type == "System.Object")
755                                 return null;
756                         
757                         string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
758                         //Console.WriteLine ("Looking up: " + newt + " " + name);
759                         t = LookupTypeReflection (newt);
760                         if (t == null)
761                                 negative_hits [name] = null;
762                         else
763                                 types [name] = t;
764                         return t;
765                 }
766                 negative_hits [name] = null;
767                 return null;
768         }
769
770         /// <summary>
771         ///   Computes the namespaces that we import from the assemblies we reference.
772         /// </summary>
773         public static void ComputeNamespaces ()
774         {
775                 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
776
777                 //
778                 // First add the assembly namespaces
779                 //
780                 if (assembly_get_namespaces != null){
781                         int count = assemblies.Length;
782
783                         for (int i = 0; i < count; i++){
784                                 Assembly a = assemblies [i];
785                                 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
786                                 foreach (string ns in namespaces){
787                                         if (ns == "")
788                                                 continue;
789                                         Namespace.LookupNamespace (ns, true);
790                                 }
791                         }
792                 } else {
793                         Hashtable cache = new Hashtable ();
794                         cache.Add ("", null);
795                         foreach (Assembly a in assemblies) {
796                                 foreach (Type t in a.GetExportedTypes ()) {
797                                         string ns = t.Namespace;
798                                         if (ns == null || cache.Contains (ns))
799                                                 continue;
800
801                                         Namespace.LookupNamespace (ns, true);
802                                         cache.Add (ns, null);
803                                 }
804                         }
805                 }
806         }
807
808         /// <summary>
809         /// Fills static table with exported types from all referenced assemblies.
810         /// This information is required for CLS Compliance tests.
811         /// </summary>
812         public static void LoadAllImportedTypes ()
813         {
814                 all_imported_types = new Hashtable ();
815                 foreach (Assembly a in assemblies) {
816                         foreach (Type t in a.GetExportedTypes ()) {
817                                 all_imported_types [t.FullName] = t;
818                         }
819                 }
820         }
821
822         public static bool NamespaceClash (string name, Location loc)
823         {
824                 if (Namespace.LookupNamespace (name, false) == null)
825                         return false;
826
827                 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
828                 return true;
829         }
830
831         /// <summary>
832         ///   Returns the C# name of a type if possible, or the full type name otherwise
833         /// </summary>
834         static public string CSharpName (Type t)
835         {
836                 return Regex.Replace (t.FullName, 
837                         @"^System\." +
838                         @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
839                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
840                         @"Boolean|String|Void|Null)" +
841                         @"(\W+|\b)", 
842                         new MatchEvaluator (CSharpNameMatch));
843         }       
844         
845         static String CSharpNameMatch (Match match) 
846         {
847                 string s = match.Groups [1].Captures [0].Value;
848                 return s.ToLower ().
849                 Replace ("int32", "int").
850                 Replace ("uint32", "uint").
851                 Replace ("int16", "short").
852                 Replace ("uint16", "ushort").
853                 Replace ("int64", "long").
854                 Replace ("uint64", "ulong").
855                 Replace ("single", "float").
856                 Replace ("boolean", "bool")
857                 + match.Groups [2].Captures [0].Value;
858         }
859
860         /// <summary>
861         ///  Returns the signature of the method with full namespace classification
862         /// </summary>
863         static public string GetFullNameSignature (MemberInfo mi)
864         {
865                 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
866         }
867
868         static public string GetFullNameSignature (MethodBase mb)
869         {
870                 string name = mb.Name;
871                 if (name == ".ctor")
872                         name = mb.DeclaringType.Name;
873
874                 if (mb.IsSpecialName) {
875                         if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
876                                 name = name.Remove (0, 4);
877                         }
878
879                         if (name == "Item")
880                                 name = "this";
881                 }
882
883                 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
884         }
885
886         /// <summary>
887         ///   Returns the signature of the property and indexer
888         /// </summary>
889         static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) 
890         {
891                 if (!is_indexer) {
892                         return GetFullNameSignature (pb);
893                 }
894
895                 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
896                 string signature = GetFullNameSignature (mb);
897                 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
898                 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
899         }
900
901         /// <summary>
902         ///   Returns the signature of the method
903         /// </summary>
904         static public string CSharpSignature (MethodBase mb)
905         {
906                 StringBuilder sig = new StringBuilder ("(");
907
908                 //
909                 // FIXME: We should really have a single function to do
910                 // everything instead of the following 5 line pattern
911                 //
912                 ParameterData iparams = LookupParametersByBuilder (mb);
913
914                 if (iparams == null)
915                         iparams = new ReflectionParameters (mb);
916
917                 // Is property
918                 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
919                         return GetFullNameSignature (mb);
920                 
921                 for (int i = 0; i < iparams.Count; i++) {
922                         if (i > 0) {
923                                 sig.Append (", ");
924                         }
925                         sig.Append (iparams.ParameterDesc (i));
926                 }
927                 sig.Append (")");
928
929                 // Is indexer
930                 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
931                         sig.Replace ('(', '[');
932                         sig.Replace (')', ']');
933                 }
934
935                 return GetFullNameSignature (mb) + sig.ToString ();
936         }
937
938         /// <summary>
939         ///   Looks up a type, and aborts if it is not found.  This is used
940         ///   by types required by the compiler
941         /// </summary>
942         static Type CoreLookupType (string name)
943         {
944                 Type t = LookupTypeDirect (name);
945
946                 if (t == null){
947                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
948                         Environment.Exit (1);
949                 }
950
951                 return t;
952         }
953
954         /// <summary>
955         ///   Returns the MethodInfo for a method named `name' defined
956         ///   in type `t' which takes arguments of types `args'
957         /// </summary>
958         static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
959         {
960                 MemberList list;
961                 Signature sig;
962                 BindingFlags flags = instance_and_static | BindingFlags.Public;
963
964                 sig.name = name;
965                 sig.args = args;
966
967                 if (is_private)
968                         flags |= BindingFlags.NonPublic;
969
970                 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
971                 if (list.Count == 0) {
972                         if (report_errors)
973                                 Report.Error (-19, "Can not find the core function `" + name + "'");
974                         return null;
975                 }
976
977                 MethodInfo mi = list [0] as MethodInfo;
978                 if (mi == null) {
979                         if (report_errors)
980                                 Report.Error (-19, "Can not find the core function `" + name + "'");
981                         return null;
982                 }
983
984                 return mi;
985         }
986
987         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
988         {
989                 return GetMethod (t, name, args, false, report_errors);
990         }
991
992         static MethodInfo GetMethod (Type t, string name, Type [] args)
993         {
994                 return GetMethod (t, name, args, true);
995         }
996
997
998         /// <summary>
999         ///    Returns the ConstructorInfo for "args"
1000         /// </summary>
1001         static ConstructorInfo GetConstructor (Type t, Type [] args)
1002         {
1003                 MemberList list;
1004                 Signature sig;
1005
1006                 sig.name = ".ctor";
1007                 sig.args = args;
1008                 
1009                 list = FindMembers (t, MemberTypes.Constructor,
1010                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1011                                     signature_filter, sig);
1012                 if (list.Count == 0){
1013                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1014                         return null;
1015                 }
1016
1017                 ConstructorInfo ci = list [0] as ConstructorInfo;
1018                 if (ci == null){
1019                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1020                         return null;
1021                 }
1022
1023                 return ci;
1024         }
1025
1026         public static void InitEnumUnderlyingTypes ()
1027         {
1028
1029                 int32_type    = CoreLookupType ("System.Int32");
1030                 int64_type    = CoreLookupType ("System.Int64");
1031                 uint32_type   = CoreLookupType ("System.UInt32"); 
1032                 uint64_type   = CoreLookupType ("System.UInt64"); 
1033                 byte_type     = CoreLookupType ("System.Byte");
1034                 sbyte_type    = CoreLookupType ("System.SByte");
1035                 short_type    = CoreLookupType ("System.Int16");
1036                 ushort_type   = CoreLookupType ("System.UInt16");
1037         }
1038         
1039         /// <remarks>
1040         ///   The types have to be initialized after the initial
1041         ///   population of the type has happened (for example, to
1042         ///   bootstrap the corlib.dll
1043         /// </remarks>
1044         public static void InitCoreTypes ()
1045         {
1046                 object_type   = CoreLookupType ("System.Object");
1047                 value_type    = CoreLookupType ("System.ValueType");
1048
1049                 InitEnumUnderlyingTypes ();
1050
1051                 char_type     = CoreLookupType ("System.Char");
1052                 string_type   = CoreLookupType ("System.String");
1053                 float_type    = CoreLookupType ("System.Single");
1054                 double_type   = CoreLookupType ("System.Double");
1055                 char_ptr_type = CoreLookupType ("System.Char*");
1056                 decimal_type  = CoreLookupType ("System.Decimal");
1057                 bool_type     = CoreLookupType ("System.Boolean");
1058                 enum_type     = CoreLookupType ("System.Enum");
1059
1060                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1061                 delegate_type           = CoreLookupType ("System.Delegate");
1062
1063                 array_type    = CoreLookupType ("System.Array");
1064                 void_type     = CoreLookupType ("System.Void");
1065                 type_type     = CoreLookupType ("System.Type");
1066
1067                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1068                 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1069                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1070                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1071                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
1072                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
1073                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
1074                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
1075                 ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
1076                 idisposable_type     = CoreLookupType ("System.IDisposable");
1077                 icloneable_type      = CoreLookupType ("System.ICloneable");
1078                 iconvertible_type    = CoreLookupType ("System.IConvertible");
1079                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
1080                 intptr_type          = CoreLookupType ("System.IntPtr");
1081
1082                 attribute_type       = CoreLookupType ("System.Attribute");
1083                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1084                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1085                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1086                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1087                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
1088                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1089                 typed_reference_type = CoreLookupType ("System.TypedReference");
1090                 arg_iterator_type    = CoreLookupType ("System.ArgIterator");
1091                 mbr_type             = CoreLookupType ("System.MarshalByRefObject");
1092
1093                 //
1094                 // Sigh. Remove this before the release.  Wonder what versions of Mono
1095                 // people are running.
1096                 //
1097                 guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1098
1099                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1100
1101                 void_ptr_type         = CoreLookupType ("System.Void*");
1102
1103                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1104
1105                 exception_type        = CoreLookupType ("System.Exception");
1106                 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1107                 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1108
1109                 //
1110                 // Attribute types
1111                 //
1112                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1113                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1114                 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1115                 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1116                 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1117                 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1118
1119                 //
1120                 // When compiling corlib, store the "real" types here.
1121                 //
1122                 if (!RootContext.StdLib) {
1123                         system_int32_type = typeof (System.Int32);
1124                         system_array_type = typeof (System.Array);
1125                         system_type_type = typeof (System.Type);
1126                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1127
1128                         Type [] void_arg = {  };
1129                         system_int_array_get_length = GetMethod (
1130                                 system_array_type, "get_Length", void_arg);
1131                         system_int_array_get_rank = GetMethod (
1132                                 system_array_type, "get_Rank", void_arg);
1133                         system_object_array_clone = GetMethod (
1134                                 system_array_type, "Clone", void_arg);
1135
1136                         Type [] system_int_arg = { system_int32_type };
1137                         system_int_array_get_length_int = GetMethod (
1138                                 system_array_type, "GetLength", system_int_arg);
1139                         system_int_array_get_upper_bound_int = GetMethod (
1140                                 system_array_type, "GetUpperBound", system_int_arg);
1141                         system_int_array_get_lower_bound_int = GetMethod (
1142                                 system_array_type, "GetLowerBound", system_int_arg);
1143
1144                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
1145                         system_void_array_copyto_array_int = GetMethod (
1146                                 system_array_type, "CopyTo", system_array_int_arg);
1147
1148                         Type [] system_3_type_arg = {
1149                                 system_type_type, system_type_type, system_type_type };
1150                         Type [] system_4_type_arg = {
1151                                 system_type_type, system_type_type, system_type_type, system_type_type };
1152
1153                         MethodInfo set_corlib_type_builders = GetMethod (
1154                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1155                                 system_4_type_arg, true, false);
1156
1157                         if (set_corlib_type_builders != null) {
1158                                 object[] args = new object [4];
1159                                 args [0] = object_type;
1160                                 args [1] = value_type;
1161                                 args [2] = enum_type;
1162                                 args [3] = void_type;
1163                                 
1164                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1165                         } else {
1166                                 // Compatibility for an older version of the class libs.
1167                                 set_corlib_type_builders = GetMethod (
1168                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
1169                                         system_3_type_arg, true, true);
1170
1171                                 if (set_corlib_type_builders == null) {
1172                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1173                                         return;
1174                                 }
1175
1176                                 object[] args = new object [3];
1177                                 args [0] = object_type;
1178                                 args [1] = value_type;
1179                                 args [2] = enum_type;
1180                                 
1181                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1182                         }
1183                 }
1184
1185                 system_object_expr.Type = object_type;
1186                 system_string_expr.Type = string_type;
1187                 system_boolean_expr.Type = bool_type;
1188                 system_decimal_expr.Type = decimal_type;
1189                 system_single_expr.Type = float_type;
1190                 system_double_expr.Type = double_type;
1191                 system_sbyte_expr.Type = sbyte_type;
1192                 system_byte_expr.Type = byte_type;
1193                 system_int16_expr.Type = short_type;
1194                 system_uint16_expr.Type = ushort_type;
1195                 system_int32_expr.Type = int32_type;
1196                 system_uint32_expr.Type = uint32_type;
1197                 system_int64_expr.Type = int64_type;
1198                 system_uint64_expr.Type = uint64_type;
1199                 system_char_expr.Type = char_type;
1200                 system_void_expr.Type = void_type;
1201                 system_asynccallback_expr.Type = asynccallback_type;
1202                 system_iasyncresult_expr.Type = iasyncresult_type;
1203                 system_valuetype_expr.Type = value_type;
1204
1205                 //
1206                 // These are only used for compare purposes
1207                 //
1208                 anonymous_method_type = typeof (AnonymousMethod);
1209         }
1210
1211         //
1212         // The helper methods that are used by the compiler
1213         //
1214         public static void InitCodeHelpers ()
1215         {
1216                 //
1217                 // Now load the default methods that we use.
1218                 //
1219                 Type [] string_string = { string_type, string_type };
1220                 string_concat_string_string = GetMethod (
1221                         string_type, "Concat", string_string);
1222                 Type [] string_string_string = { string_type, string_type, string_type };
1223                 string_concat_string_string_string = GetMethod (
1224                         string_type, "Concat", string_string_string);
1225                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1226                 string_concat_string_string_string_string = GetMethod (
1227                         string_type, "Concat", string_string_string_string);
1228                 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1229                 string_concat_string_dot_dot_dot = GetMethod (
1230                         string_type, "Concat", params_string);
1231
1232                 Type [] object_object = { object_type, object_type };
1233                 string_concat_object_object = GetMethod (
1234                         string_type, "Concat", object_object);
1235                 Type [] object_object_object = { object_type, object_type, object_type };
1236                 string_concat_object_object_object = GetMethod (
1237                         string_type, "Concat", object_object_object);
1238                 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1239                 string_concat_object_dot_dot_dot = GetMethod (
1240                         string_type, "Concat", params_object);
1241
1242                 Type [] string_ = { string_type };
1243                 string_isinterneted_string = GetMethod (
1244                         string_type, "IsInterned", string_);
1245                 
1246                 Type [] runtime_type_handle = { runtime_handle_type };
1247                 system_type_get_type_from_handle = GetMethod (
1248                         type_type, "GetTypeFromHandle", runtime_type_handle);
1249
1250                 Type [] delegate_delegate = { delegate_type, delegate_type };
1251                 delegate_combine_delegate_delegate = GetMethod (
1252                                 delegate_type, "Combine", delegate_delegate);
1253
1254                 delegate_remove_delegate_delegate = GetMethod (
1255                                 delegate_type, "Remove", delegate_delegate);
1256
1257                 //
1258                 // Void arguments
1259                 //
1260                 Type [] void_arg = {  };
1261                 object_getcurrent_void = GetMethod (
1262                         ienumerator_type, "get_Current", void_arg);
1263                 bool_movenext_void = GetMethod (
1264                         ienumerator_type, "MoveNext", void_arg);
1265                 void_reset_void = GetMethod (
1266                         ienumerator_type, "Reset", void_arg);
1267                 void_dispose_void = GetMethod (
1268                         idisposable_type, "Dispose", void_arg);
1269                 int_get_offset_to_string_data = GetMethod (
1270                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
1271                 int_array_get_length = GetMethod (
1272                         array_type, "get_Length", void_arg);
1273                 int_array_get_rank = GetMethod (
1274                         array_type, "get_Rank", void_arg);
1275                 ienumerable_getenumerator_void = GetMethod (
1276                         ienumerable_type, "GetEnumerator", void_arg);
1277                 
1278                 //
1279                 // Int32 arguments
1280                 //
1281                 Type [] int_arg = { int32_type };
1282                 int_array_get_length_int = GetMethod (
1283                         array_type, "GetLength", int_arg);
1284                 int_array_get_upper_bound_int = GetMethod (
1285                         array_type, "GetUpperBound", int_arg);
1286                 int_array_get_lower_bound_int = GetMethod (
1287                         array_type, "GetLowerBound", int_arg);
1288
1289                 //
1290                 // System.Array methods
1291                 //
1292                 object_array_clone = GetMethod (
1293                         array_type, "Clone", void_arg);
1294                 Type [] array_int_arg = { array_type, int32_type };
1295                 void_array_copyto_array_int = GetMethod (
1296                         array_type, "CopyTo", array_int_arg);
1297                 
1298                 //
1299                 // object arguments
1300                 //
1301                 Type [] object_arg = { object_type };
1302                 void_monitor_enter_object = GetMethod (
1303                         monitor_type, "Enter", object_arg);
1304                 void_monitor_exit_object = GetMethod (
1305                         monitor_type, "Exit", object_arg);
1306
1307                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1308                 
1309                 void_initializearray_array_fieldhandle = GetMethod (
1310                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1311
1312                 //
1313                 // Array functions
1314                 //
1315                 int_getlength_int = GetMethod (
1316                         array_type, "GetLength", int_arg);
1317
1318                 //
1319                 // Decimal constructors
1320                 //
1321                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1322                 void_decimal_ctor_five_args = GetConstructor (
1323                         decimal_type, dec_arg);
1324                 
1325                 //
1326                 // Attributes
1327                 //
1328                 cons_param_array_attribute = GetConstructor (
1329                         param_array_type, void_arg);
1330
1331                 unverifiable_code_ctor = GetConstructor (
1332                         unverifiable_code_type, void_arg);
1333
1334                 default_member_ctor = GetConstructor (default_member_type, string_);
1335
1336                 //
1337                 // InvalidOperationException
1338                 //
1339                 invalid_operation_ctor = GetConstructor (
1340                         invalid_operation_exception_type, void_arg);
1341
1342
1343                 // Object
1344                 object_ctor = GetConstructor (object_type, void_arg);
1345
1346         }
1347
1348         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1349
1350         /// <remarks>
1351         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1352         ///   the cache here because there is no member name argument.
1353         /// </remarks>
1354         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1355                                               MemberFilter filter, object criteria)
1356         {
1357                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1358
1359                 //
1360                 // `builder_to_declspace' contains all dynamic types.
1361                 //
1362                 if (decl != null) {
1363                         MemberList list;
1364                         Timer.StartTimer (TimerType.FindMembers);
1365                         list = decl.FindMembers (mt, bf, filter, criteria);
1366                         Timer.StopTimer (TimerType.FindMembers);
1367                         return list;
1368                 }
1369
1370                 //
1371                 // We have to take care of arrays specially, because GetType on
1372                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1373                 // and we can not call FindMembers on this type.
1374                 //
1375                 if (t.IsSubclassOf (TypeManager.array_type))
1376                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1377
1378                 //
1379                 // Since FindMembers will not lookup both static and instance
1380                 // members, we emulate this behaviour here.
1381                 //
1382                 if ((bf & instance_and_static) == instance_and_static){
1383                         MemberInfo [] i_members = t.FindMembers (
1384                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1385
1386                         int i_len = i_members.Length;
1387                         if (i_len == 1){
1388                                 MemberInfo one = i_members [0];
1389
1390                                 //
1391                                 // If any of these are present, we are done!
1392                                 //
1393                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1394                                         return new MemberList (i_members);
1395                         }
1396                                 
1397                         MemberInfo [] s_members = t.FindMembers (
1398                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1399
1400                         int s_len = s_members.Length;
1401                         if (i_len > 0 || s_len > 0)
1402                                 return new MemberList (i_members, s_members);
1403                         else {
1404                                 if (i_len > 0)
1405                                         return new MemberList (i_members);
1406                                 else
1407                                         return new MemberList (s_members);
1408                         }
1409                 }
1410
1411                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1412         }
1413
1414
1415         /// <summary>
1416         ///   This method is only called from within MemberLookup.  It tries to use the member
1417         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1418         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1419         ///   our return value will already contain all inherited members and the caller don't need
1420         ///   to check base classes and interfaces anymore.
1421         /// </summary>
1422         private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1423                                                             string name, out bool used_cache)
1424         {
1425                 //
1426                 // We have to take care of arrays specially, because GetType on
1427                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1428                 // and we can not call FindMembers on this type.
1429                 //
1430                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1431                         used_cache = true;
1432                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1433                                 mt, bf, name, FilterWithClosure_delegate, null);
1434                 }
1435
1436                 //
1437                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1438                 // and we can ask the DeclSpace for the MemberCache.
1439                 //
1440                 if (t is TypeBuilder) {
1441                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1442                         MemberCache cache = decl.MemberCache;
1443
1444                         //
1445                         // If this DeclSpace has a MemberCache, use it.
1446                         //
1447
1448                         if (cache != null) {
1449                                 used_cache = true;
1450                                 return cache.FindMembers (
1451                                         mt, bf, name, FilterWithClosure_delegate, null);
1452                         }
1453
1454                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1455                         // Note, this is a VERY uncommon route!
1456                         
1457                         MemberList list;
1458                         Timer.StartTimer (TimerType.FindMembers);
1459                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1460                                                  FilterWithClosure_delegate, name);
1461                         Timer.StopTimer (TimerType.FindMembers);
1462                         used_cache = false;
1463                         
1464                         return (MemberInfo []) list;
1465                 }
1466
1467                 //
1468                 // This call will always succeed.  There is exactly one TypeHandle instance per
1469                 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1470                 // if it didn't already exist.
1471                 //
1472                 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1473
1474                 used_cache = true;
1475                 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1476         }
1477
1478         public static bool IsBuiltinType (Type t)
1479         {
1480                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1481                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1482                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1483                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1484                         return true;
1485                 else
1486                         return false;
1487         }
1488
1489         public static bool IsBuiltinType (TypeContainer tc)
1490         {
1491                 return IsBuiltinType (tc.TypeBuilder);
1492         }
1493
1494         //
1495         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1496         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1497         // 
1498         public static bool IsCLRType (Type t)
1499         {
1500                 if (t == object_type || t == int32_type || t == uint32_type ||
1501                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1502                     t == char_type || t == short_type || t == bool_type ||
1503                     t == sbyte_type || t == byte_type || t == ushort_type)
1504                         return true;
1505                 else
1506                         return false;
1507         }
1508
1509         public static bool IsDelegateType (Type t)
1510         {
1511                 if (t.IsSubclassOf (TypeManager.delegate_type))
1512                         return true;
1513                 else
1514                         return false;
1515         }
1516         
1517         public static bool IsEnumType (Type t)
1518         {
1519                 if (t.IsSubclassOf (TypeManager.enum_type))
1520                         return true;
1521                 else
1522                         return false;
1523         }
1524         public static bool IsBuiltinOrEnum (Type t)
1525         {
1526                 if (IsBuiltinType (t))
1527                         return true;
1528                 
1529                 if (IsEnumType (t))
1530                         return true;
1531
1532                 return false;
1533         }
1534
1535         //
1536         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1537         //
1538         public static bool IsUnmanagedType (Type t)
1539         {
1540                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1541                         return true;
1542
1543                 if (IsEnumType (t))
1544                         return true;
1545
1546                 if (t.IsPointer)
1547                         return true;
1548
1549                 if (IsValueType (t)){
1550                         if (t is TypeBuilder){
1551                                 TypeContainer tc = LookupTypeContainer (t);
1552
1553                                 if (tc.Fields != null){
1554                                         foreach (Field f in tc.Fields){
1555                                                 if (f.FieldBuilder.IsStatic)
1556                                                         continue;
1557                                                 if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1558                                                         return false;
1559                                         }
1560                                 } else
1561                                         return true;
1562                         } else {
1563                                 FieldInfo [] fields = t.GetFields ();
1564
1565                                 foreach (FieldInfo f in fields){
1566                                         if (f.IsStatic)
1567                                                 continue;
1568                                         if (!IsUnmanagedType (f.FieldType))
1569                                                 return false;
1570                                 }
1571                         }
1572                         return true;
1573                 }
1574
1575                 return false;
1576         }
1577                 
1578         public static bool IsValueType (Type t)
1579         {
1580                 if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
1581                         return true;
1582                 else
1583                         return false;
1584         }
1585         
1586         public static bool IsInterfaceType (Type t)
1587         {
1588                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1589                 if (tc == null)
1590                         return false;
1591
1592                 return tc.Kind == Kind.Interface;
1593         }
1594
1595         //
1596         // Checks whether `type' is a subclass or nested child of `parent'.
1597         //
1598         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1599         {
1600                 do {
1601                         if ((type == parent) || type.IsSubclassOf (parent))
1602                                 return true;
1603
1604                         // Handle nested types.
1605                         type = type.DeclaringType;
1606                 } while (type != null);
1607
1608                 return false;
1609         }
1610
1611         //
1612         // Checks whether `type' is a nested child of `parent'.
1613         //
1614         public static bool IsNestedChildOf (Type type, Type parent)
1615         {
1616                 if (type == parent)
1617                         return false;
1618
1619                 type = type.DeclaringType;
1620                 while (type != null) {
1621                         if (type == parent)
1622                                 return true;
1623
1624                         type = type.DeclaringType;
1625                 }
1626
1627                 return false;
1628         }
1629
1630         //
1631         // Do the right thing when returning the element type of an
1632         // array type based on whether we are compiling corlib or not
1633         //
1634         public static Type GetElementType (Type t)
1635         {
1636                 if (RootContext.StdLib)
1637                         return t.GetElementType ();
1638                 else
1639                         return TypeToCoreType (t.GetElementType ());
1640         }
1641
1642         /// <summary>
1643         ///   Returns the User Defined Types
1644         /// </summary>
1645         public static ArrayList UserTypes {
1646                 get {
1647                         return user_types;
1648                 }
1649         }
1650
1651         public static Hashtable TypeContainers {
1652                 get {
1653                         return typecontainers;
1654                 }
1655         }
1656
1657         static Hashtable builder_to_constant;
1658
1659         public static void RegisterConstant (FieldBuilder fb, Const c)
1660         {
1661                 if (builder_to_constant == null)
1662                         builder_to_constant = new PtrHashtable ();
1663
1664                 if (builder_to_constant.Contains (fb))
1665                         return;
1666
1667                 builder_to_constant.Add (fb, c);
1668         }
1669
1670         public static Const LookupConstant (FieldBuilder fb)
1671         {
1672                 if (builder_to_constant == null)
1673                         return null;
1674                 
1675                 return (Const) builder_to_constant [fb];
1676         }
1677         
1678         /// <summary>
1679         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1680         /// </summary>
1681         ///
1682         /// <remarks>
1683         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1684         ///   for anything which is dynamic, and we need this in a number of places,
1685         ///   we register this information here, and use it afterwards.
1686         /// </remarks>
1687         static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1688         {
1689                 if (args == null)
1690                         args = NoTypes;
1691                                 
1692                 method_arguments.Add (mb, args);
1693                 method_internal_params.Add (mb, ip);
1694         }
1695         
1696         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1697         {
1698                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1699                         return null;
1700                 
1701                 if (method_internal_params.Contains (mb))
1702                         return (InternalParameters) method_internal_params [mb];
1703                 else
1704                         throw new Exception ("Argument for Method not registered" + mb);
1705         }
1706
1707         /// <summary>
1708         ///    Returns the argument types for a method based on its methodbase
1709         ///
1710         ///    For dynamic methods, we use the compiler provided types, for
1711         ///    methods from existing assemblies we load them from GetParameters,
1712         ///    and insert them into the cache
1713         /// </summary>
1714         static public Type [] GetArgumentTypes (MethodBase mb)
1715         {
1716                 object t = method_arguments [mb];
1717                 if (t != null)
1718                         return (Type []) t;
1719
1720                 ParameterInfo [] pi = mb.GetParameters ();
1721                 int c = pi.Length;
1722                 Type [] types;
1723
1724                 if (c == 0) {
1725                         types = NoTypes;
1726                 } else {
1727                         types = new Type [c];
1728                         for (int i = 0; i < c; i++)
1729                                 types [i] = pi [i].ParameterType;
1730                 }
1731                 method_arguments.Add (mb, types);
1732                 return types;
1733         }
1734
1735         /// <summary>
1736         ///    Returns the argument types for an indexer based on its PropertyInfo
1737         ///
1738         ///    For dynamic indexers, we use the compiler provided types, for
1739         ///    indexers from existing assemblies we load them from GetParameters,
1740         ///    and insert them into the cache
1741         /// </summary>
1742         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1743         {
1744                 if (indexer_arguments.Contains (indexer))
1745                         return (Type []) indexer_arguments [indexer];
1746                 else if (indexer is PropertyBuilder)
1747                         // If we're a PropertyBuilder and not in the
1748                         // `indexer_arguments' hash, then we're a property and
1749                         // not an indexer.
1750                         return NoTypes;
1751                 else {
1752                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1753                         // Property, not an indexer.
1754                         if (pi == null)
1755                                 return NoTypes;
1756                         int c = pi.Length;
1757                         Type [] types = new Type [c];
1758                         
1759                         for (int i = 0; i < c; i++)
1760                                 types [i] = pi [i].ParameterType;
1761
1762                         indexer_arguments.Add (indexer, types);
1763                         return types;
1764                 }
1765         }
1766         
1767         // <remarks>
1768         //  This is a workaround the fact that GetValue is not
1769         //  supported for dynamic types
1770         // </remarks>
1771         static Hashtable fields = new Hashtable ();
1772         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1773         {
1774                 if (fields.Contains (fb))
1775                         return false;
1776
1777                 fields.Add (fb, value);
1778
1779                 return true;
1780         }
1781
1782         static public object GetValue (FieldBuilder fb)
1783         {
1784                 return fields [fb];
1785         }
1786
1787         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1788         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1789         {
1790                 if (fieldbuilders_to_fields.Contains (fb))
1791                         return false;
1792
1793                 fieldbuilders_to_fields.Add (fb, f);
1794                 return true;
1795         }
1796
1797         //
1798         // The return value can be null;  This will be the case for
1799         // auxiliary FieldBuilders created by the compiler that have no
1800         // real field being declared on the source code
1801         //
1802         static public FieldBase GetField (FieldInfo fb)
1803         {
1804                 return (FieldBase) fieldbuilders_to_fields [fb];
1805         }
1806         
1807         static Hashtable events;
1808
1809         static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1810         {
1811                 if (events == null)
1812                         events = new Hashtable ();
1813
1814                 if (!events.Contains (eb)) {
1815                         events.Add (eb, new Pair (add, remove));
1816                 }
1817         }
1818
1819         static public MethodInfo GetAddMethod (EventInfo ei)
1820         {
1821                 if (ei is MyEventBuilder) {
1822                         Pair pair = (Pair) events [ei];
1823
1824                         return (MethodInfo) pair.First;
1825                 }
1826                 return ei.GetAddMethod (true);
1827         }
1828
1829         static public MethodInfo GetRemoveMethod (EventInfo ei)
1830         {
1831                 if (ei is MyEventBuilder) {
1832                         Pair pair = (Pair) events [ei];
1833
1834                         return (MethodInfo) pair.Second;
1835                 }
1836                 return ei.GetRemoveMethod (true);
1837         }
1838
1839         static Hashtable priv_fields_events;
1840
1841         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1842         {
1843                 if (priv_fields_events == null)
1844                         priv_fields_events = new Hashtable ();
1845
1846                 if (priv_fields_events.Contains (einfo))
1847                         return false;
1848
1849                 priv_fields_events.Add (einfo, builder);
1850
1851                 return true;
1852         }
1853
1854         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1855         {
1856                 if (priv_fields_events == null)
1857                         return null;
1858                 else
1859                         return (MemberInfo) priv_fields_events [ei];
1860         }
1861                 
1862         static Hashtable properties;
1863         
1864         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1865         {
1866                 if (properties == null)
1867                         properties = new Hashtable ();
1868
1869                 if (properties.Contains (pb))
1870                         return false;
1871
1872                 properties.Add (pb, new Pair (get, set));
1873
1874                 return true;
1875         }
1876
1877         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
1878                                             MethodBase set, Type[] args)
1879         {
1880                 if (!RegisterProperty (pb, get,set))
1881                         return false;
1882
1883                 indexer_arguments.Add (pb, args);
1884
1885                 return true;
1886         }
1887
1888         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
1889         {
1890                 Hashtable hash = new Hashtable ();
1891                 return CheckStructCycles (tc, seen, hash);
1892         }
1893
1894         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
1895                                               Hashtable hash)
1896         {
1897                 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
1898                         return true;
1899
1900                 //
1901                 // `seen' contains all types we've already visited.
1902                 //
1903                 if (seen.Contains (tc))
1904                         return true;
1905                 seen.Add (tc, null);
1906
1907                 if (tc.Fields == null)
1908                         return true;
1909
1910                 foreach (Field field in tc.Fields) {
1911                         if (field.FieldBuilder.IsStatic)
1912                                 continue;
1913
1914                         Type ftype = field.FieldBuilder.FieldType;
1915                         TypeContainer ftc = LookupTypeContainer (ftype);
1916                         if (ftc == null)
1917                                 continue;
1918
1919                         if (hash.Contains (ftc)) {
1920                                 Report.Error (523, tc.Location,
1921                                               "Struct member `{0}.{1}' of type `{2}' " +
1922                                               "causes a cycle in the struct layout",
1923                                               tc.Name, field.Name, ftc.Name);
1924                                 return false;
1925                         }
1926
1927                         //
1928                         // `hash' contains all types in the current path.
1929                         //
1930                         hash.Add (tc, null);
1931
1932                         bool ok = CheckStructCycles (ftc, seen, hash);
1933
1934                         hash.Remove (tc);
1935
1936                         if (!ok)
1937                                 return false;
1938
1939                         if (!seen.Contains (ftc))
1940                                 seen.Add (ftc, null);
1941                 }
1942
1943                 return true;
1944         }
1945
1946         /// <summary>
1947         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1948         ///   of an interface.  
1949         /// </summary>
1950         ///
1951         /// <remarks>
1952         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1953         ///   be IA, IB, IC.
1954         /// </remarks>
1955         public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
1956         {
1957                 ArrayList new_ifaces = new ArrayList ();
1958                 
1959                 foreach (TypeExpr iface in base_interfaces){
1960                         Type itype = iface.ResolveType (ec);
1961                         if (itype == null)
1962                                 return null;
1963
1964                         if (!new_ifaces.Contains (itype))
1965                                 new_ifaces.Add (itype);
1966                         
1967                         Type [] implementing = itype.GetInterfaces ();
1968                         
1969                         foreach (Type imp in implementing){
1970                                 if (!new_ifaces.Contains (imp))
1971                                         new_ifaces.Add (imp);
1972                         }
1973                 }
1974                 Type [] ret = new Type [new_ifaces.Count];
1975                 new_ifaces.CopyTo (ret, 0);
1976                 return ret;
1977         }
1978         
1979         static PtrHashtable iface_cache = new PtrHashtable ();
1980                 
1981         /// <summary>
1982         ///   This function returns the interfaces in the type `t'.  Works with
1983         ///   both types and TypeBuilders.
1984         /// </summary>
1985         public static Type [] GetInterfaces (Type t)
1986         {
1987                 
1988                 Type [] cached = iface_cache [t] as Type [];
1989                 if (cached != null)
1990                         return cached;
1991                 
1992                 //
1993                 // The reason for catching the Array case is that Reflection.Emit
1994                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1995                 // but will still throw an exception if we try to call GetInterfaces
1996                 // on the type.
1997                 //
1998                 // Since the array interfaces are always constant, we return those for
1999                 // the System.Array
2000                 //
2001                 
2002                 if (t.IsArray)
2003                         t = TypeManager.array_type;
2004                 
2005                 if (t is TypeBuilder){
2006                         Type [] parent_ifaces;
2007                         
2008                         if (t.BaseType == null)
2009                                 parent_ifaces = NoTypes;
2010                         else
2011                                 parent_ifaces = GetInterfaces (t.BaseType);
2012                         Type [] type_ifaces = (Type []) builder_to_ifaces [t];
2013                         if (type_ifaces == null)
2014                                 type_ifaces = NoTypes;
2015
2016                         int parent_count = parent_ifaces.Length;
2017                         Type [] result = new Type [parent_count + type_ifaces.Length];
2018                         parent_ifaces.CopyTo (result, 0);
2019                         type_ifaces.CopyTo (result, parent_count);
2020
2021                         iface_cache [t] = result;
2022                         return result;
2023                 } else {
2024                         Type[] ifaces = t.GetInterfaces ();
2025                         iface_cache [t] = ifaces;
2026                         return ifaces;
2027                 }
2028         }
2029         
2030         //
2031         // gets the interfaces that are declared explicitly on t
2032         //
2033         public static Type [] GetExplicitInterfaces (TypeBuilder t)
2034         {
2035                 return (Type []) builder_to_ifaces [t];
2036         }
2037         
2038         /// <remarks>
2039         ///  The following is used to check if a given type implements an interface.
2040         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2041         /// </remarks>
2042         public static bool ImplementsInterface (Type t, Type iface)
2043         {
2044                 Type [] interfaces;
2045
2046                 //
2047                 // FIXME OPTIMIZATION:
2048                 // as soon as we hit a non-TypeBuiler in the interface
2049                 // chain, we could return, as the `Type.GetInterfaces'
2050                 // will return all the interfaces implement by the type
2051                 // or its parents.
2052                 //
2053                 do {
2054                         interfaces = GetInterfaces (t);
2055
2056                         if (interfaces != null){
2057                                 foreach (Type i in interfaces){
2058                                         if (i == iface)
2059                                                 return true;
2060                                 }
2061                         }
2062                         
2063                         t = t.BaseType;
2064                 } while (t != null);
2065                 
2066                 return false;
2067         }
2068
2069         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2070
2071         // This is a custom version of Convert.ChangeType() which works
2072         // with the TypeBuilder defined types when compiling corlib.
2073         public static object ChangeType (object value, Type conversionType, out bool error)
2074         {
2075                 IConvertible convert_value = value as IConvertible;
2076                 
2077                 if (convert_value == null){
2078                         error = true;
2079                         return null;
2080                 }
2081                 
2082                 //
2083                 // We must use Type.Equals() here since `conversionType' is
2084                 // the TypeBuilder created version of a system type and not
2085                 // the system type itself.  You cannot use Type.GetTypeCode()
2086                 // on such a type - it'd always return TypeCode.Object.
2087                 //
2088                 error = false;
2089                 try {
2090                         if (conversionType.Equals (typeof (Boolean)))
2091                                 return (object)(convert_value.ToBoolean (nf_provider));
2092                         else if (conversionType.Equals (typeof (Byte)))
2093                                 return (object)(convert_value.ToByte (nf_provider));
2094                         else if (conversionType.Equals (typeof (Char)))
2095                                 return (object)(convert_value.ToChar (nf_provider));
2096                         else if (conversionType.Equals (typeof (DateTime)))
2097                                 return (object)(convert_value.ToDateTime (nf_provider));
2098                         else if (conversionType.Equals (typeof (Decimal)))
2099                                 return (object)(convert_value.ToDecimal (nf_provider));
2100                         else if (conversionType.Equals (typeof (Double)))
2101                                 return (object)(convert_value.ToDouble (nf_provider));
2102                         else if (conversionType.Equals (typeof (Int16)))
2103                                 return (object)(convert_value.ToInt16 (nf_provider));
2104                         else if (conversionType.Equals (typeof (Int32)))
2105                                 return (object)(convert_value.ToInt32 (nf_provider));
2106                         else if (conversionType.Equals (typeof (Int64)))
2107                                 return (object)(convert_value.ToInt64 (nf_provider));
2108                         else if (conversionType.Equals (typeof (SByte)))
2109                                 return (object)(convert_value.ToSByte (nf_provider));
2110                         else if (conversionType.Equals (typeof (Single)))
2111                                 return (object)(convert_value.ToSingle (nf_provider));
2112                         else if (conversionType.Equals (typeof (String)))
2113                                 return (object)(convert_value.ToString (nf_provider));
2114                         else if (conversionType.Equals (typeof (UInt16)))
2115                                 return (object)(convert_value.ToUInt16 (nf_provider));
2116                         else if (conversionType.Equals (typeof (UInt32)))
2117                                 return (object)(convert_value.ToUInt32 (nf_provider));
2118                         else if (conversionType.Equals (typeof (UInt64)))
2119                                 return (object)(convert_value.ToUInt64 (nf_provider));
2120                         else if (conversionType.Equals (typeof (Object)))
2121                                 return (object)(value);
2122                         else 
2123                                 error = true;
2124                 } catch {
2125                         error = true;
2126                 }
2127                 return null;
2128         }
2129
2130         //
2131         // This is needed, because enumerations from assemblies
2132         // do not report their underlyingtype, but they report
2133         // themselves
2134         //
2135         public static Type EnumToUnderlying (Type t)
2136         {
2137                 if (t == TypeManager.enum_type)
2138                         return t;
2139
2140                 t = t.UnderlyingSystemType;
2141                 if (!TypeManager.IsEnumType (t))
2142                         return t;
2143         
2144                 if (t is TypeBuilder) {
2145                         // slow path needed to compile corlib
2146                         if (t == TypeManager.bool_type ||
2147                             t == TypeManager.byte_type ||
2148                             t == TypeManager.sbyte_type ||
2149                             t == TypeManager.char_type ||
2150                             t == TypeManager.short_type ||
2151                             t == TypeManager.ushort_type ||
2152                             t == TypeManager.int32_type ||
2153                             t == TypeManager.uint32_type ||
2154                             t == TypeManager.int64_type ||
2155                             t == TypeManager.uint64_type)
2156                                 return t;
2157                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2158                 }
2159                 TypeCode tc = Type.GetTypeCode (t);
2160
2161                 switch (tc){
2162                 case TypeCode.Boolean:
2163                         return TypeManager.bool_type;
2164                 case TypeCode.Byte:
2165                         return TypeManager.byte_type;
2166                 case TypeCode.SByte:
2167                         return TypeManager.sbyte_type;
2168                 case TypeCode.Char:
2169                         return TypeManager.char_type;
2170                 case TypeCode.Int16:
2171                         return TypeManager.short_type;
2172                 case TypeCode.UInt16:
2173                         return TypeManager.ushort_type;
2174                 case TypeCode.Int32:
2175                         return TypeManager.int32_type;
2176                 case TypeCode.UInt32:
2177                         return TypeManager.uint32_type;
2178                 case TypeCode.Int64:
2179                         return TypeManager.int64_type;
2180                 case TypeCode.UInt64:
2181                         return TypeManager.uint64_type;
2182                 }
2183                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2184         }
2185
2186         //
2187         // When compiling corlib and called with one of the core types, return
2188         // the corresponding typebuilder for that type.
2189         //
2190         public static Type TypeToCoreType (Type t)
2191         {
2192                 if (RootContext.StdLib || (t is TypeBuilder))
2193                         return t;
2194
2195                 TypeCode tc = Type.GetTypeCode (t);
2196
2197                 switch (tc){
2198                 case TypeCode.Boolean:
2199                         return TypeManager.bool_type;
2200                 case TypeCode.Byte:
2201                         return TypeManager.byte_type;
2202                 case TypeCode.SByte:
2203                         return TypeManager.sbyte_type;
2204                 case TypeCode.Char:
2205                         return TypeManager.char_type;
2206                 case TypeCode.Int16:
2207                         return TypeManager.short_type;
2208                 case TypeCode.UInt16:
2209                         return TypeManager.ushort_type;
2210                 case TypeCode.Int32:
2211                         return TypeManager.int32_type;
2212                 case TypeCode.UInt32:
2213                         return TypeManager.uint32_type;
2214                 case TypeCode.Int64:
2215                         return TypeManager.int64_type;
2216                 case TypeCode.UInt64:
2217                         return TypeManager.uint64_type;
2218                 case TypeCode.Single:
2219                         return TypeManager.float_type;
2220                 case TypeCode.Double:
2221                         return TypeManager.double_type;
2222                 case TypeCode.String:
2223                         return TypeManager.string_type;
2224                 default:
2225                         if (t == typeof (void))
2226                                 return TypeManager.void_type;
2227                         if (t == typeof (object))
2228                                 return TypeManager.object_type;
2229                         if (t == typeof (System.Type))
2230                                 return TypeManager.type_type;
2231                         if (t == typeof (System.IntPtr))
2232                                 return TypeManager.intptr_type;
2233                         return t;
2234                 }
2235         }
2236
2237         /// <summary>
2238         ///   Utility function that can be used to probe whether a type
2239         ///   is managed or not.  
2240         /// </summary>
2241         public static bool VerifyUnManaged (Type t, Location loc)
2242         {
2243                 if (t.IsValueType || t.IsPointer){
2244                         //
2245                         // FIXME: this is more complex, we actually need to
2246                         // make sure that the type does not contain any
2247                         // classes itself
2248                         //
2249                         return true;
2250                 }
2251
2252                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2253                         // We need this explicit check here to make it work when
2254                         // compiling corlib.
2255                         return true;
2256
2257                 Report.Error (
2258                         208, loc,
2259                         "Cannot take the address or size of a variable of a managed type ('" +
2260                         CSharpName (t) + "')");
2261                 return false;   
2262         }
2263         
2264         /// <summary>
2265         ///   Returns the name of the indexer in a given type.
2266         /// </summary>
2267         /// <remarks>
2268         ///   The default is not always `Item'.  The user can change this behaviour by
2269         ///   using the IndexerNameAttribute in the container.
2270         ///   For example, the String class indexer is named `Chars' not `Item' 
2271         /// </remarks>
2272         public static string IndexerPropertyName (Type t)
2273         {
2274                 if (t is TypeBuilder) {
2275                         TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2276                         return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2277                 }
2278                 
2279                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2280                         t, TypeManager.default_member_type);
2281                 if (attr != null){
2282                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2283                         return dma.MemberName;
2284                 }
2285
2286                 return TypeContainer.DefaultIndexerName;
2287         }
2288
2289         static MethodInfo declare_local_method = null;
2290         
2291         public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2292         {
2293                 if (declare_local_method == null){
2294                         declare_local_method = typeof (ILGenerator).GetMethod (
2295                                 "DeclareLocal",
2296                                 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2297                                 null, 
2298                                 new Type [] { typeof (Type), typeof (bool)},
2299                                 null);
2300                         if (declare_local_method == null){
2301                                 Report.Warning (-24, new Location (-1),
2302                                                 "This version of the runtime does not support making pinned local variables.  " +
2303                                                 "This code may cause errors on a runtime with a moving GC");
2304                                 return ig.DeclareLocal (t);
2305                         }
2306                 }
2307                 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2308         }
2309         
2310         //
2311         // Returns whether the array of memberinfos contains the given method
2312         //
2313         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2314         {
2315                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2316                 
2317                 foreach (MethodBase method in array) {
2318                         if (method.Name != new_method.Name)
2319                                 continue;
2320
2321                         if (method is MethodInfo && new_method is MethodInfo)
2322                                 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2323                                         continue;
2324
2325                         
2326                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2327                         int old_count = old_args.Length;
2328                         int i;
2329                         
2330                         if (new_args.Length != old_count)
2331                                 continue;
2332                         
2333                         for (i = 0; i < old_count; i++){
2334                                 if (old_args [i] != new_args [i])
2335                                         break;
2336                         }
2337                         if (i != old_count)
2338                                 continue;
2339
2340                         return true;
2341                 }
2342                 
2343                 return false;
2344         }
2345         
2346         //
2347         // We copy methods from `new_members' into `target_list' if the signature
2348         // for the method from in the new list does not exist in the target_list
2349         //
2350         // The name is assumed to be the same.
2351         //
2352         public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2353         {
2354                 if (target_list == null){
2355                         target_list = new ArrayList ();
2356
2357                         foreach (MemberInfo mi in new_members){
2358                                 if (mi is MethodBase)
2359                                         target_list.Add (mi);
2360                         }
2361                         return target_list;
2362                 }
2363                 
2364                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2365                 target_list.CopyTo (target_array, 0);
2366                 
2367                 foreach (MemberInfo mi in new_members){
2368                         MethodBase new_method = (MethodBase) mi;
2369                         
2370                         if (!ArrayContainsMethod (target_array, new_method))
2371                                 target_list.Add (new_method);
2372                 }
2373                 return target_list;
2374         }
2375
2376
2377 #region MemberLookup implementation
2378         
2379         //
2380         // Whether we allow private members in the result (since FindMembers
2381         // uses NonPublic for both protected and private), we need to distinguish.
2382         //
2383
2384         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2385         {
2386                 return true;
2387         }
2388
2389         internal class Closure {
2390                 internal bool     private_ok;
2391
2392                 // Who is invoking us and which type is being queried currently.
2393                 internal Type     invocation_type;
2394                 internal Type     qualifier_type;
2395
2396                 // The assembly that defines the type is that is calling us
2397                 internal Assembly invocation_assembly;
2398                 internal IList almost_match;
2399
2400                 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2401                 {
2402                         if (invocation_type == null)
2403                                 return false;
2404
2405                         Debug.Assert (IsSubclassOrNestedChildOf (invocation_type, m.DeclaringType));
2406
2407                         if (is_static)
2408                                 return true;
2409                         
2410                         // A nested class has access to all the protected members visible to its parent.
2411                         if (qualifier_type != null
2412                             && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2413                                 return true;
2414
2415                         if (invocation_type == m.DeclaringType
2416                             || invocation_type.IsSubclassOf (m.DeclaringType)) {
2417                                 // Although a derived class can access protected members of its base class
2418                                 // it cannot do so through an instance of the base class (CS1540).
2419                                 // => Ancestry should be: declaring_type ->* invocation_type ->*  qualified_type
2420                                 if (qualifier_type == null
2421                                     || qualifier_type == invocation_type
2422                                     || qualifier_type.IsSubclassOf (invocation_type))
2423                                         return true;
2424                         }
2425
2426                         if (almost_match != null)
2427                                 almost_match.Add (m);
2428                         return false;
2429                 }
2430                 
2431                 //
2432                 // This filter filters by name + whether it is ok to include private
2433                 // members in the search
2434                 //
2435                 internal bool Filter (MemberInfo m, object filter_criteria)
2436                 {
2437                         //
2438                         // Hack: we know that the filter criteria will always be in the `closure'
2439                         // fields. 
2440                         //
2441
2442                         if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2443                                 return false;
2444                         
2445                         if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
2446                             (m.DeclaringType == invocation_type))
2447                                 return true;
2448                         
2449                         //
2450                         // Ugly: we need to find out the type of `m', and depending
2451                         // on this, tell whether we accept or not
2452                         //
2453                         if (m is MethodBase){
2454                                 MethodBase mb = (MethodBase) m;
2455                                 MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2456
2457                                 if (ma == MethodAttributes.Private)
2458                                         return private_ok || (invocation_type == m.DeclaringType) ||
2459                                                 IsNestedChildOf (invocation_type, m.DeclaringType);
2460                                 
2461                                 // Assembly succeeds if we're in the same assembly.
2462                                 if (ma == MethodAttributes.Assembly)
2463                                         return (invocation_assembly == mb.DeclaringType.Assembly);
2464                                 
2465                                 // FamAndAssem requires that we not only derive, but we are on the same assembly.  
2466                                 if (ma == MethodAttributes.FamANDAssem){
2467                                         if (invocation_assembly != mb.DeclaringType.Assembly)
2468                                                 return false;
2469                                 }
2470                                 
2471                                 // Family and FamANDAssem require that we derive.
2472                                 if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem))
2473                                         return CheckValidFamilyAccess (mb.IsStatic, m);
2474                                 
2475                                 // Public.
2476                                 return true;
2477                         }
2478                         
2479                         if (m is FieldInfo){
2480                                 FieldInfo fi = (FieldInfo) m;
2481                                 FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2482                                 
2483                                 if (fa == FieldAttributes.Private)
2484                                         return private_ok || (invocation_type == m.DeclaringType) ||
2485                                                 IsNestedChildOf (invocation_type, m.DeclaringType);
2486                                 
2487                                 // Assembly succeeds if we're in the same assembly.
2488                                 if (fa == FieldAttributes.Assembly)
2489                                         return (invocation_assembly == fi.DeclaringType.Assembly);
2490                                                 
2491                                 // FamAndAssem requires that we not only derive, but we are on the same assembly.  
2492                                 if (fa == FieldAttributes.FamANDAssem){
2493                                         if (invocation_assembly != fi.DeclaringType.Assembly)
2494                                                 return false;
2495                                 }
2496                                 
2497                                 // Family and FamANDAssem require that we derive.
2498                                 if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem))
2499                                         return CheckValidFamilyAccess (fi.IsStatic, m);
2500                                 
2501                                 // Public.
2502                                 return true;
2503                         }
2504                         
2505                         //
2506                         // EventInfos and PropertyInfos, return true because they lack permission
2507                         // information, so we need to check later on the methods.
2508                         //
2509                         return true;
2510                 }
2511         }
2512
2513         static Closure closure = new Closure ();
2514         static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
2515
2516         //
2517         // Looks up a member called `name' in the `queried_type'.  This lookup
2518         // is done by code that is contained in the definition for `invocation_type'
2519         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2520         //
2521         // `invocation_type' is used to check whether we're allowed to access the requested
2522         // member wrt its protection level.
2523         //
2524         // When called from MemberAccess, `qualifier_type' is the type which is used to access
2525         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2526         // is B and qualifier_type is A).  This is used to do the CS1540 check.
2527         //
2528         // When resolving a SimpleName, `qualifier_type' is null.
2529         //
2530         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2531         // the same than `queried_type' - except when we're being called from BaseAccess;
2532         // in this case, `invocation_type' is the current type and `queried_type' the base
2533         // type, so this'd normally trigger a CS1540.
2534         //
2535         // The binding flags are `bf' and the kind of members being looked up are `mt'
2536         //
2537         // The return value always includes private members which code in `invocation_type'
2538         // is allowed to access (using the specified `qualifier_type' if given); only use
2539         // BindingFlags.NonPublic to bypass the permission check.
2540         //
2541         // The 'almost_match' argument is used for reporting error CS1540.
2542         //
2543         // Returns an array of a single element for everything but Methods/Constructors
2544         // that might return multiple matches.
2545         //
2546         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2547                                                   Type queried_type,  MemberTypes mt,
2548                                                   BindingFlags original_bf, string name, IList almost_match)
2549         {
2550                 Timer.StartTimer (TimerType.MemberLookup);
2551
2552                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2553                                                         queried_type, mt, original_bf, name, almost_match);
2554
2555                 Timer.StopTimer (TimerType.MemberLookup);
2556
2557                 return retval;
2558         }
2559
2560         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2561                                                Type queried_type, MemberTypes mt,
2562                                                BindingFlags original_bf, string name, IList almost_match)
2563         {
2564                 BindingFlags bf = original_bf;
2565                 
2566                 ArrayList method_list = null;
2567                 Type current_type = queried_type;
2568                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2569                 bool skip_iface_check = true, used_cache = false;
2570                 bool always_ok_flag = false;
2571
2572                 closure.invocation_type = invocation_type;
2573                 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2574                 closure.qualifier_type = qualifier_type;
2575                 closure.almost_match = almost_match;
2576
2577                 //
2578                 // If we are a nested class, we always have access to our container
2579                 // type names
2580                 //
2581                 if (invocation_type != null){
2582                         string invocation_name = invocation_type.FullName;
2583                         if (invocation_name.IndexOf ('+') != -1){
2584                                 string container = queried_type.FullName + "+";
2585                                 int container_length = container.Length;
2586
2587                                 if (invocation_name.Length > container_length){
2588                                         string shared = invocation_name.Substring (0, container_length);
2589                                 
2590                                         if (shared == container)
2591                                                 always_ok_flag = true;
2592                                 }
2593                         }
2594                 }
2595                 
2596                 // This is from the first time we find a method
2597                 // in most cases, we do not actually find a method in the base class
2598                 // so we can just ignore it, and save the arraylist allocation
2599                 MemberInfo [] first_members_list = null;
2600                 bool use_first_members_list = false;
2601                 
2602                 do {
2603                         MemberInfo [] list;
2604
2605                         //
2606                         // `NonPublic' is lame, because it includes both protected and
2607                         // private methods, so we need to control this behavior by
2608                         // explicitly tracking if a private method is ok or not.
2609                         //
2610                         // The possible cases are:
2611                         //    public, private and protected (internal does not come into the
2612                         //    equation)
2613                         //
2614                         if ((invocation_type != null) &&
2615                             ((invocation_type == current_type) ||
2616                              IsNestedChildOf (invocation_type, current_type)) ||
2617                             always_ok_flag)
2618                                 bf = original_bf | BindingFlags.NonPublic;
2619                         else
2620                                 bf = original_bf;
2621
2622                         closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2623
2624                         Timer.StopTimer (TimerType.MemberLookup);
2625
2626                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2627
2628                         Timer.StartTimer (TimerType.MemberLookup);
2629
2630                         //
2631                         // When queried for an interface type, the cache will automatically check all
2632                         // inherited members, so we don't need to do this here.  However, this only
2633                         // works if we already used the cache in the first iteration of this loop.
2634                         //
2635                         // If we used the cache in any further iteration, we can still terminate the
2636                         // loop since the cache always looks in all parent classes.
2637                         //
2638
2639                         if (used_cache)
2640                                 searching = false;
2641                         else
2642                                 skip_iface_check = false;
2643
2644                         if (current_type == TypeManager.object_type)
2645                                 searching = false;
2646                         else {
2647                                 current_type = current_type.BaseType;
2648                                 
2649                                 //
2650                                 // This happens with interfaces, they have a null
2651                                 // basetype.  Look members up in the Object class.
2652                                 //
2653                                 if (current_type == null) {
2654                                         current_type = TypeManager.object_type;
2655                                         searching = true;
2656                                 }
2657                         }
2658                         
2659                         if (list.Length == 0)
2660                                 continue;
2661
2662                         //
2663                         // Events and types are returned by both `static' and `instance'
2664                         // searches, which means that our above FindMembers will
2665                         // return two copies of the same.
2666                         //
2667                         if (list.Length == 1 && !(list [0] is MethodBase)){
2668                                 return list;
2669                         }
2670
2671                         //
2672                         // Multiple properties: we query those just to find out the indexer
2673                         // name
2674                         //
2675                         if (list [0] is PropertyInfo)
2676                                 return list;
2677
2678                         //
2679                         // We found an event: the cache lookup returns both the event and
2680                         // its private field.
2681                         //
2682                         if (list [0] is EventInfo) {
2683                                 if ((list.Length == 2) && (list [1] is FieldInfo))
2684                                         return new MemberInfo [] { list [0] };
2685
2686                                 // Oooops
2687                                 return null;
2688                         }
2689
2690                         //
2691                         // We found methods, turn the search into "method scan"
2692                         // mode.
2693                         //
2694
2695                         if (first_members_list != null) {
2696                                 if (use_first_members_list) {
2697                                         method_list = CopyNewMethods (method_list, first_members_list);
2698                                         use_first_members_list = false;
2699                                 }
2700                                 
2701                                 method_list = CopyNewMethods (method_list, list);
2702                         } else {
2703                                 first_members_list = list;
2704                                 use_first_members_list = true;
2705                                 mt &= (MemberTypes.Method | MemberTypes.Constructor);
2706                         }
2707                 } while (searching);
2708                 
2709                 if (use_first_members_list) {
2710                         foreach (MemberInfo mi in first_members_list) {
2711                                 if (! (mi is MethodBase)) {
2712                                         method_list = CopyNewMethods (method_list, first_members_list);
2713                                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2714                                 }
2715                         }
2716                         return (MemberInfo []) first_members_list;
2717                 }
2718
2719                 if (method_list != null && method_list.Count > 0)
2720                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2721                 
2722                 //
2723                 // This happens if we already used the cache in the first iteration, in this case
2724                 // the cache already looked in all interfaces.
2725                 //
2726                 if (skip_iface_check)
2727                         return null;
2728
2729                 //
2730                 // Interfaces do not list members they inherit, so we have to
2731                 // scan those.
2732                 // 
2733                 if (!queried_type.IsInterface)
2734                         return null;
2735
2736                 if (queried_type.IsArray)
2737                         queried_type = TypeManager.array_type;
2738                 
2739                 Type [] ifaces = GetInterfaces (queried_type);
2740                 if (ifaces == null)
2741                         return null;
2742                 
2743                 foreach (Type itype in ifaces){
2744                         MemberInfo [] x;
2745
2746                         x = MemberLookup (null, null, itype, mt, bf, name, null);
2747                         if (x != null)
2748                                 return x;
2749                 }
2750                                         
2751                 return null;
2752         }
2753
2754         // Tests whether external method is really special
2755         public static bool IsSpecialMethod (MethodBase mb)
2756         {
2757                 string name = mb.Name;
2758                 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
2759                         return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
2760
2761                 if (name.StartsWith ("add_"))
2762                         return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
2763
2764                 if (name.StartsWith ("remove_"))
2765                         return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
2766
2767                 if (name.StartsWith ("op_")){
2768                         foreach (string oname in Unary.oper_names) {
2769                                 if (oname == name)
2770                                         return true;
2771                         }
2772                 
2773                         foreach (string oname in Binary.oper_names) {
2774                                 if (oname == name)
2775                                         return true;
2776                         }
2777                 }
2778                 return false;
2779         }
2780                 
2781 #endregion
2782         
2783 }
2784
2785 /// <summary>
2786 ///   There is exactly one instance of this class per type.
2787 /// </summary>
2788 public sealed class TypeHandle : IMemberContainer {
2789         public readonly TypeHandle BaseType;
2790
2791         readonly int id = ++next_id;
2792         static int next_id = 0;
2793
2794         /// <summary>
2795         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2796         ///   a TypeHandle yet, a new instance of it is created.  This static method
2797         ///   ensures that we'll only have one TypeHandle instance per type.
2798         /// </summary>
2799         public static TypeHandle GetTypeHandle (Type t)
2800         {
2801                 TypeHandle handle = (TypeHandle) type_hash [t];
2802                 if (handle != null)
2803                         return handle;
2804
2805                 handle = new TypeHandle (t);
2806                 type_hash.Add (t, handle);
2807                 return handle;
2808         }
2809         
2810         public static void CleanUp ()
2811         {
2812                 type_hash = null;
2813         }
2814
2815         /// <summary>
2816         ///   Returns the TypeHandle for TypeManager.object_type.
2817         /// </summary>
2818         public static IMemberContainer ObjectType {
2819                 get {
2820                         if (object_type != null)
2821                                 return object_type;
2822
2823                         object_type = GetTypeHandle (TypeManager.object_type);
2824
2825                         return object_type;
2826                 }
2827         }
2828
2829         /// <summary>
2830         ///   Returns the TypeHandle for TypeManager.array_type.
2831         /// </summary>
2832         public static IMemberContainer ArrayType {
2833                 get {
2834                         if (array_type != null)
2835                                 return array_type;
2836
2837                         array_type = GetTypeHandle (TypeManager.array_type);
2838
2839                         return array_type;
2840                 }
2841         }
2842
2843         private static PtrHashtable type_hash = new PtrHashtable ();
2844
2845         private static TypeHandle object_type = null;
2846         private static TypeHandle array_type = null;
2847
2848         private Type type;
2849         private bool is_interface;
2850         private MemberCache member_cache;
2851         private MemberCache parent_cache;
2852
2853         private TypeHandle (Type type)
2854         {
2855                 this.type = type;
2856                 if (type.BaseType != null) {
2857                         BaseType = GetTypeHandle (type.BaseType);
2858                         parent_cache = BaseType.MemberCache;
2859                 } else if (type.IsInterface)
2860                         parent_cache = TypeManager.LookupInterfaceCache (this, type);
2861                 this.is_interface = type.IsInterface;
2862                 this.member_cache = new MemberCache (this);
2863         }
2864
2865         // IMemberContainer methods
2866
2867         public string Name {
2868                 get {
2869                         return type.FullName;
2870                 }
2871         }
2872
2873         public Type Type {
2874                 get {
2875                         return type;
2876                 }
2877         }
2878
2879         public MemberCache ParentCache {
2880                 get {
2881                         return parent_cache;
2882                 }
2883         }
2884
2885         public bool IsInterface {
2886                 get {
2887                         return is_interface;
2888                 }
2889         }
2890
2891         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2892         {
2893                 MemberInfo [] members;
2894                 if (mt == MemberTypes.Event)
2895                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
2896                 else
2897                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2898                                                     null, null);
2899                 Array.Reverse (members);
2900
2901                 return new MemberList (members);
2902         }
2903
2904         // IMemberFinder methods
2905
2906         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2907                                        MemberFilter filter, object criteria)
2908         {
2909                 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
2910         }
2911
2912         public MemberCache MemberCache {
2913                 get {
2914                         return member_cache;
2915                 }
2916         }
2917
2918         public override string ToString ()
2919         {
2920                 if (BaseType != null)
2921                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2922                 else
2923                         return "TypeHandle (" + id + "," + Name + ")";
2924         }
2925 }
2926
2927 }