2002-10-19 Rachel Hestilow <hestilow@ximian.com>
[mono.git] / mcs / mbas / 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 using System;
13 using System.Globalization;
14 using System.Collections;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Text.RegularExpressions;
18 using System.Runtime.CompilerServices;
19 using System.Diagnostics;
20
21 namespace Mono.CSharp {
22
23 public class TypeManager {
24         //
25         // A list of core types that the compiler requires or uses
26         //
27         static public Type object_type;
28         static public Type value_type;
29         static public Type string_type;
30         static public Type int32_type;
31         static public Type uint32_type;
32         static public Type int64_type;
33         static public Type uint64_type;
34         static public Type float_type;
35         static public Type double_type;
36         static public Type char_type;
37         static public Type char_ptr_type;
38         static public Type short_type;
39         static public Type decimal_type;
40         static public Type bool_type;
41         static public Type sbyte_type;
42         static public Type byte_type;
43         static public Type ushort_type;
44         static public Type enum_type;
45         static public Type delegate_type;
46         static public Type multicast_delegate_type;
47         static public Type void_type;
48         static public Type enumeration_type;
49         static public Type array_type;
50         static public Type runtime_handle_type;
51         static public Type icloneable_type;
52         static public Type type_type;
53         static public Type ienumerator_type;
54         static public Type idisposable_type;
55         static public Type default_member_type;
56         static public Type iasyncresult_type;
57         static public Type asynccallback_type;
58         static public Type intptr_type;
59         static public Type monitor_type;
60         static public Type runtime_field_handle_type;
61         static public Type attribute_type;
62         static public Type attribute_usage_type;
63         static public Type dllimport_type;
64         static public Type unverifiable_code_type;
65         static public Type methodimpl_attr_type;
66         static public Type marshal_as_attr_type;
67         static public Type param_array_type;
68         static public Type void_ptr_type;
69         static public Type indexer_name_type;
70         static public Type exception_type;
71         static public object obsolete_attribute_type;
72         static public object conditional_attribute_type;
73
74         //
75         // An empty array of types
76         //
77         static public Type [] NoTypes;
78
79
80         // 
81         // Expressions representing the internal types.  Used during declaration
82         // definition.
83         //
84         static public Expression system_object_expr, system_string_expr; 
85         static public Expression system_boolean_expr, system_decimal_expr;
86         static public Expression system_single_expr, system_double_expr;
87         static public Expression system_sbyte_expr, system_byte_expr;
88         static public Expression system_int16_expr, system_uint16_expr;
89         static public Expression system_int32_expr, system_uint32_expr;
90         static public Expression system_int64_expr, system_uint64_expr;
91         static public Expression system_char_expr, system_void_expr;
92         static public Expression system_asynccallback_expr;
93         static public Expression system_iasyncresult_expr;
94
95         //
96         // This is only used when compiling corlib
97         //
98         static public Type system_int32_type;
99         static public Type system_array_type;
100         static public Type system_type_type;
101         static public Type system_assemblybuilder_type;
102         static public MethodInfo system_int_array_get_length;
103         static public MethodInfo system_int_array_get_rank;
104         static public MethodInfo system_object_array_clone;
105         static public MethodInfo system_int_array_get_length_int;
106         static public MethodInfo system_int_array_get_lower_bound_int;
107         static public MethodInfo system_int_array_get_upper_bound_int;
108         static public MethodInfo system_void_array_copyto_array_int;
109         static public MethodInfo system_void_set_corlib_type_builders;
110
111         
112         //
113         // Internal, not really used outside
114         //
115         static Type runtime_helpers_type;
116         
117         //
118         // These methods are called by code generated by the compiler
119         //
120         static public MethodInfo string_concat_string_string;
121         static public MethodInfo string_concat_object_object;
122         static public MethodInfo string_isinterneted_string;
123         static public MethodInfo system_type_get_type_from_handle;
124         static public MethodInfo object_getcurrent_void;
125         static public MethodInfo bool_movenext_void;
126         static public MethodInfo void_dispose_void;
127         static public MethodInfo void_monitor_enter_object;
128         static public MethodInfo void_monitor_exit_object;
129         static public MethodInfo void_initializearray_array_fieldhandle;
130         static public MethodInfo int_getlength_int;
131         static public MethodInfo delegate_combine_delegate_delegate;
132         static public MethodInfo delegate_remove_delegate_delegate;
133         static public MethodInfo int_get_offset_to_string_data;
134         static public MethodInfo int_array_get_length;
135         static public MethodInfo int_array_get_rank;
136         static public MethodInfo object_array_clone;
137         static public MethodInfo int_array_get_length_int;
138         static public MethodInfo int_array_get_lower_bound_int;
139         static public MethodInfo int_array_get_upper_bound_int;
140         static public MethodInfo void_array_copyto_array_int;
141         
142         //
143         // The attribute constructors.
144         //
145         static public ConstructorInfo cons_param_array_attribute;
146         static public ConstructorInfo void_decimal_ctor_five_args;
147         static public ConstructorInfo unverifiable_code_ctor;
148         
149         // <remarks>
150         //   Holds the Array of Assemblies that have been loaded
151         //   (either because it is the default or the user used the
152         //   -r command line option)
153         // </remarks>
154         static Assembly [] assemblies;
155
156         // <remarks>
157         //  Keeps a list of module builders. We used this to do lookups
158         //  on the modulebuilder using GetType -- needed for arrays
159         // </remarks>
160         static ModuleBuilder [] modules;
161
162         // <remarks>
163         //   This is the type_cache from the assemblies to avoid
164         //   hitting System.Reflection on every lookup.
165         // </summary>
166         static Hashtable types;
167
168         // <remarks>
169         //  This is used to hotld the corresponding TypeContainer objects
170         //  since we need this in FindMembers
171         // </remarks>
172         static Hashtable typecontainers;
173
174         // <remarks>
175         //   Keeps track of those types that are defined by the
176         //   user's program
177         // </remarks>
178         static ArrayList user_types;
179
180         static PtrHashtable builder_to_declspace;
181
182         // <remarks>
183         //   Tracks the interfaces implemented by typebuilders.  We only
184         //   enter those who do implement or or more interfaces
185         // </remarks>
186         static PtrHashtable builder_to_ifaces;
187
188         // <remarks>
189         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
190         //   the arguments to the method
191         // </remarks>
192         static Hashtable method_arguments;
193
194         // <remarks>
195         //   Maps PropertyBuilder to a Type array that contains
196         //   the arguments to the indexer
197         // </remarks>
198         static Hashtable indexer_arguments;
199
200         // <remarks>
201         //   Maybe `method_arguments' should be replaced and only
202         //   method_internal_params should be kept?
203         // <remarks>
204         static Hashtable method_internal_params;
205
206         // <remarks>
207         //  Keeps track of attribute types
208         // </remarks>
209
210         static Hashtable builder_to_attr;
211
212         // <remarks>
213         //  Keeps track of methods
214         // </remarks>
215
216         static Hashtable builder_to_method;
217
218         struct Signature {
219                 public string name;
220                 public Type [] args;
221         }
222
223         /// <summary>
224         ///   A filter for Findmembers that uses the Signature object to
225         ///   extract objects
226         /// </summary>
227         static bool SignatureFilter (MemberInfo mi, object criteria)
228         {
229                 Signature sig = (Signature) criteria;
230
231                 if (!(mi is MethodBase))
232                         return false;
233                 
234                 if (mi.Name != sig.name)
235                         return false;
236
237                 int count = sig.args.Length;
238                 
239                 if (mi is MethodBuilder || mi is ConstructorBuilder){
240                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
241
242                         if (candidate_args.Length != count)
243                                 return false;
244                         
245                         for (int i = 0; i < count; i++)
246                                 if (candidate_args [i] != sig.args [i])
247                                         return false;
248                         
249                         return true;
250                 } else {
251                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
252
253                         if (pars.Length != count)
254                                 return false;
255
256                         for (int i = 0; i < count; i++)
257                                 if (pars [i].ParameterType != sig.args [i])
258                                         return false;
259                         return true;
260                 }
261         }
262
263         // A delegate that points to the filter above.
264         static MemberFilter signature_filter;
265
266         //
267         // These are expressions that represent some of the internal data types, used
268         // elsewhere
269         //
270         static void InitExpressionTypes ()
271         {
272                 system_object_expr  = new TypeLookupExpression ("System.Object");
273                 system_string_expr  = new TypeLookupExpression ("System.String");
274                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
275                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
276                 system_single_expr  = new TypeLookupExpression ("System.Single");
277                 system_double_expr  = new TypeLookupExpression ("System.Double");
278                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
279                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
280                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
281                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
282                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
283                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
284                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
285                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
286                 system_char_expr    = new TypeLookupExpression ("System.Char");
287                 system_void_expr    = new TypeLookupExpression ("System.Void");
288                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
289                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
290         }
291         
292         static TypeManager ()
293         {
294                 assemblies = new Assembly [0];
295                 modules = null;
296                 user_types = new ArrayList ();
297                 
298                 types = new Hashtable ();
299                 typecontainers = new Hashtable ();
300                 
301                 builder_to_declspace = new PtrHashtable ();
302                 builder_to_attr = new PtrHashtable ();
303                 builder_to_method = new PtrHashtable ();
304                 method_arguments = new PtrHashtable ();
305                 method_internal_params = new PtrHashtable ();
306                 indexer_arguments = new PtrHashtable ();
307                 builder_to_ifaces = new PtrHashtable ();
308                 
309                 NoTypes = new Type [0];
310
311                 signature_filter = new MemberFilter (SignatureFilter);
312                 InitExpressionTypes ();
313         }
314
315         public static void AddUserType (string name, TypeBuilder t, Type [] ifaces)
316         {
317                 try {
318                         types.Add (name, t);
319                 } catch {
320                         Type prev = (Type) types [name];
321                         TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
322
323                         if (tc != null){
324                                 //
325                                 // This probably never happens, as we catch this before
326                                 //
327                                 Report.Error (-17, "The type `" + name + "' has already been defined.");
328                                 return;
329                         }
330
331                         tc = builder_to_declspace [t] as TypeContainer;
332                         
333                         Report.Warning (
334                                 1595, "The type `" + name + "' is defined in an existing assembly;"+
335                                 " Using the new definition from: " + tc.Location);
336                         Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
337                         
338                         types.Remove (name);
339                         types.Add (name, t);
340                 }
341                 user_types.Add (t);
342                         
343                 if (ifaces != null)
344                         builder_to_ifaces [t] = ifaces;
345         }
346
347         //
348         // This entry point is used by types that we define under the covers
349         // 
350         public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces)
351         {
352                 if (ifaces != null)
353                         builder_to_ifaces [tb] = ifaces;
354         }
355         
356         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
357         {
358                 builder_to_declspace.Add (t, tc);
359                 typecontainers.Add (name, tc);
360                 AddUserType (name, t, ifaces);
361         }
362
363         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
364         {
365                 types.Add (name, t);
366                 builder_to_declspace.Add (t, del);
367         }
368         
369         public static void AddEnumType (string name, TypeBuilder t, Enum en)
370         {
371                 types.Add (name, t);
372                 builder_to_declspace.Add (t, en);
373         }
374
375         public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
376         {
377                 AddUserType (name, t, ifaces);
378                 builder_to_declspace.Add (t, i);
379         }
380
381         public static void AddMethod (MethodBuilder builder, MethodData method)
382         {
383                 builder_to_method.Add (builder, method);
384         }
385
386         public static void RegisterAttrType (Type t, TypeContainer tc)
387         {
388                 builder_to_attr.Add (t, tc);
389         }
390
391         /// <summary>
392         ///   Returns the TypeContainer whose Type is `t' or null if there is no
393         ///   TypeContainer for `t' (ie, the Type comes from a library)
394         /// </summary>
395         public static TypeContainer LookupTypeContainer (Type t)
396         {
397                 return builder_to_declspace [t] as TypeContainer;
398         }
399
400         public static IMemberContainer LookupMemberContainer (Type t)
401         {
402                 if (t is TypeBuilder) {
403                         IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
404                         if (container != null)
405                                 return container;
406                 }
407
408                 return TypeHandle.GetTypeHandle (t);
409         }
410
411         public static Interface LookupInterface (Type t)
412         {
413                 return builder_to_declspace [t] as Interface;
414         }
415
416         public static Delegate LookupDelegate (Type t)
417         {
418                 return builder_to_declspace [t] as Delegate;
419         }
420
421         public static Enum LookupEnum (Type t)
422         {
423                 return builder_to_declspace [t] as Enum;
424         }
425         
426         public static TypeContainer LookupAttr (Type t)
427         {
428                 return (TypeContainer) builder_to_attr [t];
429         }
430         
431         /// <summary>
432         ///   Registers an assembly to load types from.
433         /// </summary>
434         public static void AddAssembly (Assembly a)
435         {
436                 int top = assemblies.Length;
437                 Assembly [] n = new Assembly [top + 1];
438
439                 assemblies.CopyTo (n, 0);
440                 
441                 n [top] = a;
442                 assemblies = n;
443         }
444
445         /// <summary>
446         ///  Registers a module builder to lookup types from
447         /// </summary>
448         public static void AddModule (ModuleBuilder mb)
449         {
450                 int top = modules != null ? modules.Length : 0;
451                 ModuleBuilder [] n = new ModuleBuilder [top + 1];
452
453                 if (modules != null)
454                         modules.CopyTo (n, 0);
455                 n [top] = mb;
456                 modules = n;
457         }
458
459         //
460         // Low-level lookup, cache-less
461         //
462         static Type LookupTypeReflection (string name)
463         {
464                 Type t;
465
466                 foreach (Assembly a in assemblies){
467                         t = a.GetType (name);
468                         if (t != null)
469                                 return t;
470                 }
471
472                 foreach (ModuleBuilder mb in modules) {
473                         t = mb.GetType (name);
474                         if (t != null){
475                                 return t;
476                         }
477                 }
478                 return null;
479         }
480
481         //
482         // This function is used when you want to avoid the lookups, and want to go
483         // directly to the source.  This will use the cache.
484         //
485         // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
486         // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
487         // way to test things other than doing a fullname compare
488         //
489         public static Type LookupTypeDirect (string name)
490         {
491                 Type t = (Type) types [name];
492                 if (t != null)
493                         return t;
494
495                 t = LookupTypeReflection (name);
496                 if (t == null)
497                         return null;
498
499                 types [name] = t;
500                 return t;
501         }
502         
503         /// <summary>
504         ///   Returns the Type associated with @name, takes care of the fact that
505         ///   reflection expects nested types to be separated from the main type
506         ///   with a "+" instead of a "."
507         /// </summary>
508         public static Type LookupType (string name)
509         {
510                 Type t;
511
512                 //
513                 // First lookup in user defined and cached values
514                 //
515
516                 t = (Type) types [name];
517                 if (t != null)
518                         return t;
519
520                 //
521                 // Optimization: ComposedCast will work with an existing type, and might already have the
522                 // full name of the type, so the full system lookup can probably be avoided.
523                 //
524                 
525                 string [] elements = name.Split ('.');
526                 int count = elements.Length;
527
528                 for (int n = 1; n <= count; n++){
529                         string top_level_type = String.Join (".", elements, 0, n);
530
531                         t = (Type) types [top_level_type];
532                         if (t == null){
533                                 t = LookupTypeReflection (top_level_type);
534                                 if (t == null)
535                                         continue;
536                         }
537                         
538                         if (count == n){
539                                 types [name] = t;
540                                 return t;
541                         } 
542                         
543                         string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
544                         t = LookupTypeDirect (newt);
545                         if (t != null)
546                                 types [newt] = t;
547                         return t;
548                 }
549                 return null;
550         }
551
552         //
553         // Returns a list of all namespaces in the assemblies and types loaded.
554         //
555         public static Hashtable GetNamespaces ()
556         {
557                 Hashtable namespaces = new Hashtable ();
558
559                 foreach (Assembly a in assemblies){
560                         foreach (Type t in a.GetTypes ()){
561                                 string ns = t.Namespace;
562
563                                 if (namespaces.Contains (ns))
564                                         continue;
565                                 namespaces [ns] = ns;
566                         }
567                 }
568
569                 foreach (ModuleBuilder mb in modules){
570                         foreach (Type t in mb.GetTypes ()){
571                                 string ns = t.Namespace;
572
573                                 if (namespaces.Contains (ns))
574                                         continue;
575                                 namespaces [ns] = ns;
576                         }
577                 }
578                 return namespaces;
579         }
580         
581         /// <summary>
582         ///   Returns the C# name of a type if possible, or the full type name otherwise
583         /// </summary>
584         static public string CSharpName (Type t)
585         {
586                 return Regex.Replace (t.FullName, 
587                         @"^System\." +
588                         @"(Int32|UInt32|Int16|Uint16|Int64|UInt64|" +
589                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
590                         @"Boolean|String|Void)" +
591                         @"(\W+|\b)", 
592                         new MatchEvaluator (CSharpNameMatch));
593         }       
594         
595         static String CSharpNameMatch (Match match) 
596         {
597                 string s = match.Groups [1].Captures [0].Value;
598                 return s.ToLower ().
599                 Replace ("int32", "int").
600                 Replace ("uint32", "uint").
601                 Replace ("int16", "short").
602                 Replace ("uint16", "ushort").
603                 Replace ("int64", "long").
604                 Replace ("uint64", "ulong").
605                 Replace ("single", "float").
606                 Replace ("boolean", "bool")
607                 + match.Groups [2].Captures [0].Value;
608         }
609
610         /// <summary>
611         ///   Returns the signature of the method
612         /// </summary>
613         static public string CSharpSignature (MethodBase mb)
614         {
615                 string sig = "(";
616
617                 //
618                 // FIXME: We should really have a single function to do
619                 // everything instead of the following 5 line pattern
620                 //
621                 ParameterData iparams = LookupParametersByBuilder (mb);
622
623                 if (iparams == null){
624                         ParameterInfo [] pi = mb.GetParameters ();
625                         iparams = new ReflectionParameters (pi);
626                 }
627                 
628                 for (int i = 0; i < iparams.Count; i++) {
629                         if (i > 0) {
630                                 sig += ", ";
631                         }
632                         sig += iparams.ParameterDesc(i);
633                 }
634                 sig += ")";
635
636                 return mb.DeclaringType.Name + "." + mb.Name + sig;
637         }
638
639         /// <summary>
640         ///   Looks up a type, and aborts if it is not found.  This is used
641         ///   by types required by the compiler
642         /// </summary>
643         static Type CoreLookupType (string name)
644         {
645                 Type t = LookupType (name);
646
647                 if (t == null){
648                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
649                         Environment.Exit (0);
650                 }
651
652                 return t;
653         }
654
655         /// <summary>
656         ///   Returns the MethodInfo for a method named `name' defined
657         ///   in type `t' which takes arguments of types `args'
658         /// </summary>
659         static MethodInfo GetMethod (Type t, string name, Type [] args)
660         {
661                 MemberList list;
662                 Signature sig;
663
664                 sig.name = name;
665                 sig.args = args;
666                 
667                 list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public,
668                                     signature_filter, sig);
669                 if (list.Count == 0) {
670                         Report.Error (-19, "Can not find the core function `" + name + "'");
671                         return null;
672                 }
673
674                 MethodInfo mi = list [0] as MethodInfo;
675                 if (mi == null) {
676                         Report.Error (-19, "Can not find the core function `" + name + "'");
677                         return null;
678                 }
679
680                 return mi;
681         }
682
683         /// <summary>
684         ///    Returns the ConstructorInfo for "args"
685         /// </summary>
686         static ConstructorInfo GetConstructor (Type t, Type [] args)
687         {
688                 MemberList list;
689                 Signature sig;
690
691                 sig.name = ".ctor";
692                 sig.args = args;
693                 
694                 list = FindMembers (t, MemberTypes.Constructor,
695                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
696                                     signature_filter, sig);
697                 if (list.Count == 0){
698                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
699                         return null;
700                 }
701
702                 ConstructorInfo ci = list [0] as ConstructorInfo;
703                 if (ci == null){
704                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
705                         return null;
706                 }
707
708                 return ci;
709         }
710
711         public static void InitEnumUnderlyingTypes ()
712         {
713
714                 int32_type    = CoreLookupType ("System.Int32");
715                 int64_type    = CoreLookupType ("System.Int64");
716                 uint32_type   = CoreLookupType ("System.UInt32"); 
717                 uint64_type   = CoreLookupType ("System.UInt64"); 
718                 byte_type     = CoreLookupType ("System.Byte");
719                 sbyte_type    = CoreLookupType ("System.SByte");
720                 short_type    = CoreLookupType ("System.Int16");
721                 ushort_type   = CoreLookupType ("System.UInt16");
722         }
723         
724         /// <remarks>
725         ///   The types have to be initialized after the initial
726         ///   population of the type has happened (for example, to
727         ///   bootstrap the corlib.dll
728         /// </remarks>
729         public static void InitCoreTypes ()
730         {
731                 object_type   = CoreLookupType ("System.Object");
732                 value_type    = CoreLookupType ("System.ValueType");
733
734                 InitEnumUnderlyingTypes ();
735
736                 char_type     = CoreLookupType ("System.Char");
737                 string_type   = CoreLookupType ("System.String");
738                 float_type    = CoreLookupType ("System.Single");
739                 double_type   = CoreLookupType ("System.Double");
740                 char_ptr_type = CoreLookupType ("System.Char*");
741                 decimal_type  = CoreLookupType ("System.Decimal");
742                 bool_type     = CoreLookupType ("System.Boolean");
743                 enum_type     = CoreLookupType ("System.Enum");
744
745                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
746                 delegate_type           = CoreLookupType ("System.Delegate");
747
748                 array_type    = CoreLookupType ("System.Array");
749                 void_type     = CoreLookupType ("System.Void");
750                 type_type     = CoreLookupType ("System.Type");
751
752                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
753                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
754                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
755                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
756                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
757                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
758                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
759                 idisposable_type     = CoreLookupType ("System.IDisposable");
760                 icloneable_type      = CoreLookupType ("System.ICloneable");
761                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
762                 intptr_type          = CoreLookupType ("System.IntPtr");
763
764                 attribute_type       = CoreLookupType ("System.Attribute");
765                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
766                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
767                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
768                 marshal_as_attr_type  = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
769                 param_array_type      = CoreLookupType ("System.ParamArrayAttribute");
770
771                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
772
773                 void_ptr_type         = CoreLookupType ("System.Void*");
774
775                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
776
777                 exception_type        = CoreLookupType ("System.Exception");
778
779                 //
780                 // Attribute types
781                 //
782                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
783                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
784
785                 //
786                 // When compiling corlib, store the "real" types here.
787                 //
788                 if (!RootContext.StdLib) {
789                         system_int32_type = typeof (System.Int32);
790                         system_array_type = typeof (System.Array);
791                         system_type_type = typeof (System.Type);
792                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
793
794                         Type [] void_arg = {  };
795                         system_int_array_get_length = GetMethod (
796                                 system_array_type, "get_Length", void_arg);
797                         system_int_array_get_rank = GetMethod (
798                                 system_array_type, "get_Rank", void_arg);
799                         system_object_array_clone = GetMethod (
800                                 system_array_type, "Clone", void_arg);
801
802                         Type [] system_int_arg = { system_int32_type };
803                         system_int_array_get_length_int = GetMethod (
804                                 system_array_type, "GetLength", system_int_arg);
805                         system_int_array_get_upper_bound_int = GetMethod (
806                                 system_array_type, "GetUpperBound", system_int_arg);
807                         system_int_array_get_lower_bound_int = GetMethod (
808                                 system_array_type, "GetLowerBound", system_int_arg);
809
810                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
811                         system_void_array_copyto_array_int = GetMethod (
812                                 system_array_type, "CopyTo", system_array_int_arg);
813
814                         Type [] system_type_type_arg = { system_type_type, system_type_type, system_type_type };
815
816                         try {
817                         system_void_set_corlib_type_builders = GetMethod (
818                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
819                                 system_type_type_arg);
820
821                         object[] args = new object [3];
822                         args [0] = object_type;
823                         args [1] = value_type;
824                         args [2] = enum_type;
825
826                         system_void_set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
827                         } catch {
828                                 Console.WriteLine ("Corlib compilation is not supported in Microsoft.NET due to bugs in it");
829                         }
830                 }
831         }
832
833         //
834         // The helper methods that are used by the compiler
835         //
836         public static void InitCodeHelpers ()
837         {
838                 //
839                 // Now load the default methods that we use.
840                 //
841                 Type [] string_string = { string_type, string_type };
842                 string_concat_string_string = GetMethod (
843                         string_type, "Concat", string_string);
844
845                 Type [] object_object = { object_type, object_type };
846                 string_concat_object_object = GetMethod (
847                         string_type, "Concat", object_object);
848
849                 Type [] string_ = { string_type };
850                 string_isinterneted_string = GetMethod (
851                         string_type, "IsInterned", string_);
852                 
853                 Type [] runtime_type_handle = { runtime_handle_type };
854                 system_type_get_type_from_handle = GetMethod (
855                         type_type, "GetTypeFromHandle", runtime_type_handle);
856
857                 Type [] delegate_delegate = { delegate_type, delegate_type };
858                 delegate_combine_delegate_delegate = GetMethod (
859                                 delegate_type, "Combine", delegate_delegate);
860
861                 delegate_remove_delegate_delegate = GetMethod (
862                                 delegate_type, "Remove", delegate_delegate);
863
864                 //
865                 // Void arguments
866                 //
867                 Type [] void_arg = {  };
868                 object_getcurrent_void = GetMethod (
869                         ienumerator_type, "get_Current", void_arg);
870                 bool_movenext_void = GetMethod (
871                         ienumerator_type, "MoveNext", void_arg);
872                 void_dispose_void = GetMethod (
873                         idisposable_type, "Dispose", void_arg);
874                 int_get_offset_to_string_data = GetMethod (
875                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
876                 int_array_get_length = GetMethod (
877                         array_type, "get_Length", void_arg);
878                 int_array_get_rank = GetMethod (
879                         array_type, "get_Rank", void_arg);
880
881                 //
882                 // Int32 arguments
883                 //
884                 Type [] int_arg = { int32_type };
885                 int_array_get_length_int = GetMethod (
886                         array_type, "GetLength", int_arg);
887                 int_array_get_upper_bound_int = GetMethod (
888                         array_type, "GetUpperBound", int_arg);
889                 int_array_get_lower_bound_int = GetMethod (
890                         array_type, "GetLowerBound", int_arg);
891
892                 //
893                 // System.Array methods
894                 //
895                 object_array_clone = GetMethod (
896                         array_type, "Clone", void_arg);
897                 Type [] array_int_arg = { array_type, int32_type };
898                 void_array_copyto_array_int = GetMethod (
899                         array_type, "CopyTo", array_int_arg);
900                 
901                 //
902                 // object arguments
903                 //
904                 Type [] object_arg = { object_type };
905                 void_monitor_enter_object = GetMethod (
906                         monitor_type, "Enter", object_arg);
907                 void_monitor_exit_object = GetMethod (
908                         monitor_type, "Exit", object_arg);
909
910                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
911                 
912                 void_initializearray_array_fieldhandle = GetMethod (
913                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
914
915                 //
916                 // Array functions
917                 //
918                 int_getlength_int = GetMethod (
919                         array_type, "GetLength", int_arg);
920
921                 //
922                 // Decimal constructors
923                 //
924                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
925                 void_decimal_ctor_five_args = GetConstructor (
926                         decimal_type, dec_arg);
927                 
928                 //
929                 // Attributes
930                 //
931                 cons_param_array_attribute = GetConstructor (
932                         param_array_type, void_arg);
933
934                 unverifiable_code_ctor = GetConstructor (
935                         unverifiable_code_type, void_arg);
936                 
937         }
938
939         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
940
941         static Hashtable type_hash = new Hashtable ();
942
943         /// <remarks>
944         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
945         ///   the cache here because there is no member name argument.
946         /// </remarks>
947         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
948                                               MemberFilter filter, object criteria)
949         {
950                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
951
952                 //
953                 // `builder_to_declspace' contains all dynamic types.
954                 //
955                 if (decl != null) {
956                         MemberList list;
957                         Timer.StartTimer (TimerType.FindMembers);
958                         list = decl.FindMembers (mt, bf, filter, criteria);
959                         Timer.StopTimer (TimerType.FindMembers);
960                         return list;
961                 }
962
963                 //
964                 // We have to take care of arrays specially, because GetType on
965                 // a TypeBuilder array will return a Type, not a TypeBuilder,
966                 // and we can not call FindMembers on this type.
967                 //
968                 if (t.IsSubclassOf (TypeManager.array_type))
969                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
970
971                 //
972                 // Since FindMembers will not lookup both static and instance
973                 // members, we emulate this behaviour here.
974                 //
975                 if ((bf & instance_and_static) == instance_and_static){
976                         MemberInfo [] i_members = t.FindMembers (
977                                 mt, bf & ~BindingFlags.Static, filter, criteria);
978
979                         int i_len = i_members.Length;
980                         if (i_len == 1){
981                                 MemberInfo one = i_members [0];
982
983                                 //
984                                 // If any of these are present, we are done!
985                                 //
986                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
987                                         return new MemberList (i_members);
988                         }
989                                 
990                         MemberInfo [] s_members = t.FindMembers (
991                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
992
993                         int s_len = s_members.Length;
994                         if (i_len > 0 || s_len > 0)
995                                 return new MemberList (i_members, s_members);
996                         else {
997                                 if (i_len > 0)
998                                         return new MemberList (i_members);
999                                 else
1000                                         return new MemberList (s_members);
1001                         }
1002                 }
1003
1004                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1005         }
1006
1007
1008         /// <summary>
1009         ///   This method is only called from within MemberLookup.  It tries to use the member
1010         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1011         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1012         ///   our return value will already contain all inherited members and the caller don't need
1013         ///   to check base classes and interfaces anymore.
1014         /// </summary>
1015         private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1016                                                             string name, out bool used_cache)
1017         {
1018                 //
1019                 // We have to take care of arrays specially, because GetType on
1020                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1021                 // and we can not call FindMembers on this type.
1022                 //
1023                 if (t.IsSubclassOf (TypeManager.array_type)) {
1024                         used_cache = true;
1025                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1026                                 mt, bf, name, FilterWithClosure_delegate, null);
1027                 }
1028
1029                 //
1030                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1031                 // and we can ask the DeclSpace for the MemberCache.
1032                 //
1033                 if (t is TypeBuilder) {
1034                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1035                         MemberCache cache = decl.MemberCache;
1036
1037                         //
1038                         // If this DeclSpace has a MemberCache, use it.
1039                         //
1040
1041                         if (cache != null) {
1042                                 used_cache = true;
1043                                 return cache.FindMembers (
1044                                         mt, bf, name, FilterWithClosure_delegate, null);
1045                         }
1046
1047                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1048
1049                         MemberList list;
1050                         Timer.StartTimer (TimerType.FindMembers);
1051                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1052                                                  FilterWithClosure_delegate, name);
1053                         Timer.StopTimer (TimerType.FindMembers);
1054                         used_cache = false;
1055                         return list;
1056                 }
1057
1058                 //
1059                 // This call will always succeed.  There is exactly one TypeHandle instance per
1060                 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1061                 // if it didn't already exist.
1062                 //
1063                 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1064
1065                 used_cache = true;
1066                 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1067         }
1068
1069         public static bool IsBuiltinType (Type t)
1070         {
1071                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1072                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1073                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1074                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1075                         return true;
1076                 else
1077                         return false;
1078         }
1079
1080         public static bool IsDelegateType (Type t)
1081         {
1082                 if (t.IsSubclassOf (TypeManager.delegate_type))
1083                         return true;
1084                 else
1085                         return false;
1086         }
1087         
1088         public static bool IsEnumType (Type t)
1089         {
1090                 if (t.IsSubclassOf (TypeManager.enum_type))
1091                         return true;
1092                 else
1093                         return false;
1094         }
1095
1096         //
1097         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1098         //
1099         public static bool IsUnmanagedType (Type t)
1100         {
1101                 if (IsBuiltinType (t))
1102                         return true;
1103                 if (IsEnumType (t))
1104                         return true;
1105                 if (t.IsPointer)
1106                         return true;
1107
1108                 if (IsValueType (t)){
1109                         //
1110                         // FIXME: Check that every field in the struct is Unmanaged
1111                         //
1112
1113                         return true;
1114                 }
1115                 
1116                 return false;
1117         }
1118                 
1119         public static bool IsValueType (Type t)
1120         {
1121                 if (t.IsSubclassOf (TypeManager.value_type))
1122                         return true;
1123                 else
1124                         return false;
1125         }
1126         
1127         public static bool IsInterfaceType (Type t)
1128         {
1129                 Interface iface = builder_to_declspace [t] as Interface;
1130
1131                 if (iface != null)
1132                         return true;
1133                 else
1134                         return false;
1135         }
1136
1137         //
1138         // Checks whether `type' is a subclass or nested child of `parent'.
1139         //
1140         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1141         {
1142                 do {
1143                         if ((type == parent) || type.IsSubclassOf (parent))
1144                                 return true;
1145
1146                         // Handle nested types.
1147                         type = type.DeclaringType;
1148                 } while (type != null);
1149
1150                 return false;
1151         }
1152
1153         //
1154         // Checks whether `type' is a nested child of `parent'.
1155         //
1156         public static bool IsNestedChildOf (Type type, Type parent)
1157         {
1158                 if ((type == parent) || type.IsSubclassOf (parent))
1159                         return false;
1160                 else
1161                         return IsSubclassOrNestedChildOf (type, parent);
1162         }
1163
1164         /// <summary>
1165         ///   Returns the User Defined Types
1166         /// </summary>
1167         public static ArrayList UserTypes {
1168                 get {
1169                         return user_types;
1170                 }
1171         }
1172
1173         public static Hashtable TypeContainers {
1174                 get {
1175                         return typecontainers;
1176                 }
1177         }
1178
1179         static Hashtable builder_to_constant;
1180
1181         public static void RegisterConstant (FieldBuilder fb, Const c)
1182         {
1183                 if (builder_to_constant == null)
1184                         builder_to_constant = new PtrHashtable ();
1185
1186                 if (builder_to_constant.Contains (fb))
1187                         return;
1188
1189                 builder_to_constant.Add (fb, c);
1190         }
1191
1192         public static Const LookupConstant (FieldBuilder fb)
1193         {
1194                 if (builder_to_constant == null)
1195                         return null;
1196                 
1197                 return (Const) builder_to_constant [fb];
1198         }
1199         
1200         /// <summary>
1201         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1202         /// </summary>
1203         ///
1204         /// <remarks>
1205         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1206         ///   for anything which is dynamic, and we need this in a number of places,
1207         ///   we register this information here, and use it afterwards.
1208         /// </remarks>
1209         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1210         {
1211                 if (args == null)
1212                         args = NoTypes;
1213                                 
1214                 method_arguments.Add (mb, args);
1215                 method_internal_params.Add (mb, ip);
1216                 
1217                 return true;
1218         }
1219         
1220         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1221         {
1222                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1223                         return null;
1224                 
1225                 if (method_internal_params.Contains (mb))
1226                         return (InternalParameters) method_internal_params [mb];
1227                 else
1228                         throw new Exception ("Argument for Method not registered" + mb);
1229         }
1230
1231         /// <summary>
1232         ///    Returns the argument types for a method based on its methodbase
1233         ///
1234         ///    For dynamic methods, we use the compiler provided types, for
1235         ///    methods from existing assemblies we load them from GetParameters,
1236         ///    and insert them into the cache
1237         /// </summary>
1238         static public Type [] GetArgumentTypes (MethodBase mb)
1239         {
1240                 if (method_arguments.Contains (mb))
1241                         return (Type []) method_arguments [mb];
1242                 else {
1243                         ParameterInfo [] pi = mb.GetParameters ();
1244                         int c = pi.Length;
1245                         Type [] types = new Type [c];
1246                         
1247                         for (int i = 0; i < c; i++)
1248                                 types [i] = pi [i].ParameterType;
1249
1250                         method_arguments.Add (mb, types);
1251                         return types;
1252                 }
1253         }
1254
1255         /// <summary>
1256         ///    Returns the argument types for an indexer based on its PropertyInfo
1257         ///
1258         ///    For dynamic indexers, we use the compiler provided types, for
1259         ///    indexers from existing assemblies we load them from GetParameters,
1260         ///    and insert them into the cache
1261         /// </summary>
1262         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1263         {
1264                 if (indexer_arguments.Contains (indexer))
1265                         return (Type []) indexer_arguments [indexer];
1266                 else if (indexer is PropertyBuilder)
1267                         // If we're a PropertyBuilder and not in the
1268                         // `indexer_arguments' hash, then we're a property and
1269                         // not an indexer.
1270                         return NoTypes;
1271                 else {
1272                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1273                         // Property, not an indexer.
1274                         if (pi == null)
1275                                 return NoTypes;
1276                         int c = pi.Length;
1277                         Type [] types = new Type [c];
1278                         
1279                         for (int i = 0; i < c; i++)
1280                                 types [i] = pi [i].ParameterType;
1281
1282                         indexer_arguments.Add (indexer, types);
1283                         return types;
1284                 }
1285         }
1286         
1287         // <remarks>
1288         //  This is a workaround the fact that GetValue is not
1289         //  supported for dynamic types
1290         // </remarks>
1291         static Hashtable fields = new Hashtable ();
1292         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1293         {
1294                 if (fields.Contains (fb))
1295                         return false;
1296
1297                 fields.Add (fb, value);
1298
1299                 return true;
1300         }
1301
1302         static public object GetValue (FieldBuilder fb)
1303         {
1304                 return fields [fb];
1305         }
1306
1307         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1308         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1309         {
1310                 if (fieldbuilders_to_fields.Contains (fb))
1311                         return false;
1312
1313                 fieldbuilders_to_fields.Add (fb, f);
1314                 return true;
1315         }
1316
1317         static public FieldBase GetField (FieldInfo fb)
1318         {
1319                 return (FieldBase) fieldbuilders_to_fields [fb];
1320         }
1321         
1322         static Hashtable events;
1323
1324         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1325         {
1326                 if (events == null)
1327                         events = new Hashtable ();
1328
1329                 if (events.Contains (eb))
1330                         return false;
1331
1332                 events.Add (eb, new Pair (add, remove));
1333
1334                 return true;
1335         }
1336
1337         static public MethodInfo GetAddMethod (EventInfo ei)
1338         {
1339                 if (ei is MyEventBuilder) {
1340                         Pair pair = (Pair) events [ei];
1341
1342                         return (MethodInfo) pair.First;
1343                 } else
1344                         return ei.GetAddMethod ();
1345         }
1346
1347         static public MethodInfo GetRemoveMethod (EventInfo ei)
1348         {
1349                 if (ei is MyEventBuilder) {
1350                         Pair pair = (Pair) events [ei];
1351
1352                         return (MethodInfo) pair.Second;
1353                 } else
1354                         return ei.GetAddMethod ();
1355         }
1356
1357         static Hashtable priv_fields_events;
1358
1359         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1360         {
1361                 if (priv_fields_events == null)
1362                         priv_fields_events = new Hashtable ();
1363
1364                 if (priv_fields_events.Contains (einfo))
1365                         return false;
1366
1367                 priv_fields_events.Add (einfo, builder);
1368
1369                 return true;
1370         }
1371
1372         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1373         {
1374                 return (MemberInfo) priv_fields_events [ei];
1375         }
1376                 
1377         static Hashtable properties;
1378         
1379         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1380         {
1381                 if (properties == null)
1382                         properties = new Hashtable ();
1383
1384                 if (properties.Contains (pb))
1385                         return false;
1386
1387                 properties.Add (pb, new Pair (get, set));
1388
1389                 return true;
1390         }
1391
1392         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get, MethodBase set, Type[] args)
1393         {
1394                 if (!RegisterProperty (pb, get,set))
1395                         return false;
1396
1397                 indexer_arguments.Add (pb, args);
1398
1399                 return true;
1400         }
1401
1402         //
1403         // FIXME: we need to return the accessors depending on whether
1404         // they are visible or not.
1405         //
1406         static public MethodInfo [] GetAccessors (PropertyInfo pi)
1407         {
1408                 MethodInfo [] ret;
1409
1410                 if (pi is PropertyBuilder){
1411                         Pair pair = (Pair) properties [pi];
1412
1413                         ret = new MethodInfo [2];
1414                         ret [0] = (MethodInfo) pair.First;
1415                         ret [1] = (MethodInfo) pair.Second;
1416
1417                         return ret;
1418                 } else {
1419                         MethodInfo [] mi = new MethodInfo [2];
1420
1421                         //
1422                         // Why this and not pi.GetAccessors?
1423                         // Because sometimes index 0 is the getter
1424                         // sometimes it is 1
1425                         //
1426                         mi [0] = pi.GetGetMethod (true);
1427                         mi [1] = pi.GetSetMethod (true);
1428
1429                         return mi;
1430                 }
1431         }
1432
1433         static public MethodInfo GetPropertyGetter (PropertyInfo pi)
1434         {
1435                 if (pi is PropertyBuilder){
1436                         Pair de = (Pair) properties [pi];
1437
1438                         return (MethodInfo) de.Second;
1439                 } else
1440                         return pi.GetSetMethod ();
1441         }
1442
1443         static public MethodInfo GetPropertySetter (PropertyInfo pi)
1444         {
1445                 if (pi is PropertyBuilder){
1446                         Pair de = (Pair) properties [pi];
1447
1448                         return (MethodInfo) de.First;
1449                 } else
1450                         return pi.GetGetMethod ();
1451         }
1452
1453         /// <summary>
1454         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1455         ///   of an interface.  
1456         /// </summary>
1457         ///
1458         /// <remarks>
1459         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1460         ///   be IA, IB, IC.
1461         /// </remarks>
1462         public static Type [] ExpandInterfaces (Type [] base_interfaces)
1463         {
1464                 ArrayList new_ifaces = new ArrayList ();
1465                 
1466                 foreach (Type iface in base_interfaces){
1467                         if (!new_ifaces.Contains (iface))
1468                                 new_ifaces.Add (iface);
1469                         
1470                         Type [] implementing = TypeManager.GetInterfaces (iface);
1471                         
1472                         foreach (Type imp in implementing){
1473                                 if (!new_ifaces.Contains (imp))
1474                                         new_ifaces.Add (imp);
1475                         }
1476                 }
1477                 Type [] ret = new Type [new_ifaces.Count];
1478                 new_ifaces.CopyTo (ret, 0);
1479                 return ret;
1480         }
1481                 
1482         /// <summary>
1483         ///   This function returns the interfaces in the type `t'.  Works with
1484         ///   both types and TypeBuilders.
1485         /// </summary>
1486         public static Type [] GetInterfaces (Type t)
1487         {
1488                 //
1489                 // The reason for catching the Array case is that Reflection.Emit
1490                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1491                 // but will still throw an exception if we try to call GetInterfaces
1492                 // on the type.
1493                 //
1494                 // Since the array interfaces are always constant, we return those for
1495                 // the System.Array
1496                 //
1497                 
1498                 if (t.IsArray)
1499                         t = TypeManager.array_type;
1500                 
1501                 if (t is TypeBuilder){
1502                         Type [] parent_ifaces;
1503                         
1504                         if (t.BaseType == null)
1505                                 parent_ifaces = NoTypes;
1506                         else
1507                                 parent_ifaces = GetInterfaces (t.BaseType);
1508                         Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1509                         if (type_ifaces == null)
1510                                 type_ifaces = NoTypes;
1511
1512                         int parent_count = parent_ifaces.Length;
1513                         Type [] result = new Type [parent_count + type_ifaces.Length];
1514                         parent_ifaces.CopyTo (result, 0);
1515                         type_ifaces.CopyTo (result, parent_count);
1516
1517                         return result;
1518                 } else
1519                         return t.GetInterfaces ();
1520         }
1521         
1522         /// <remarks>
1523         ///  The following is used to check if a given type implements an interface.
1524         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1525         /// </remarks>
1526         public static bool ImplementsInterface (Type t, Type iface)
1527         {
1528                 Type [] interfaces;
1529
1530                 //
1531                 // FIXME OPTIMIZATION:
1532                 // as soon as we hit a non-TypeBuiler in the interface
1533                 // chain, we could return, as the `Type.GetInterfaces'
1534                 // will return all the interfaces implement by the type
1535                 // or its parents.
1536                 //
1537                 do {
1538                         interfaces = GetInterfaces (t);
1539
1540                         if (interfaces != null){
1541                                 foreach (Type i in interfaces){
1542                                         if (i == iface)
1543                                                 return true;
1544                                 }
1545                         }
1546                         
1547                         t = t.BaseType;
1548                 } while (t != null);
1549                 
1550                 return false;
1551         }
1552
1553         // This is a custom version of Convert.ChangeType() which works
1554         // with the TypeBuilder defined types when compiling corlib.
1555         public static object ChangeType (object value, Type conversionType)
1556         {
1557                 if (!(value is IConvertible))
1558                         throw new ArgumentException ();
1559
1560                 IConvertible convertValue = (IConvertible) value;
1561                 CultureInfo ci = CultureInfo.CurrentCulture;
1562                 NumberFormatInfo provider = ci.NumberFormat;
1563
1564                 //
1565                 // We must use Type.Equals() here since `conversionType' is
1566                 // the TypeBuilder created version of a system type and not
1567                 // the system type itself.  You cannot use Type.GetTypeCode()
1568                 // on such a type - it'd always return TypeCode.Object.
1569                 //
1570                 if (conversionType.Equals (typeof (Boolean)))
1571                         return (object)(convertValue.ToBoolean (provider));
1572                 else if (conversionType.Equals (typeof (Byte)))
1573                         return (object)(convertValue.ToByte (provider));
1574                 else if (conversionType.Equals (typeof (Char)))
1575                         return (object)(convertValue.ToChar (provider));
1576                 else if (conversionType.Equals (typeof (DateTime)))
1577                         return (object)(convertValue.ToDateTime (provider));
1578                 else if (conversionType.Equals (typeof (Decimal)))
1579                         return (object)(convertValue.ToDecimal (provider));
1580                 else if (conversionType.Equals (typeof (Double)))
1581                         return (object)(convertValue.ToDouble (provider));
1582                 else if (conversionType.Equals (typeof (Int16)))
1583                         return (object)(convertValue.ToInt16 (provider));
1584                 else if (conversionType.Equals (typeof (Int32)))
1585                         return (object)(convertValue.ToInt32 (provider));
1586                 else if (conversionType.Equals (typeof (Int64)))
1587                         return (object)(convertValue.ToInt64 (provider));
1588                 else if (conversionType.Equals (typeof (SByte)))
1589                         return (object)(convertValue.ToSByte (provider));
1590                 else if (conversionType.Equals (typeof (Single)))
1591                         return (object)(convertValue.ToSingle (provider));
1592                 else if (conversionType.Equals (typeof (String)))
1593                         return (object)(convertValue.ToString (provider));
1594                 else if (conversionType.Equals (typeof (UInt16)))
1595                         return (object)(convertValue.ToUInt16 (provider));
1596                 else if (conversionType.Equals (typeof (UInt32)))
1597                         return (object)(convertValue.ToUInt32 (provider));
1598                 else if (conversionType.Equals (typeof (UInt64)))
1599                         return (object)(convertValue.ToUInt64 (provider));
1600                 else if (conversionType.Equals (typeof (Object)))
1601                         return (object)(value);
1602                 else 
1603                         throw new InvalidCastException ();
1604         }
1605
1606         //
1607         // This is needed, because enumerations from assemblies
1608         // do not report their underlyingtype, but they report
1609         // themselves
1610         //
1611         public static Type EnumToUnderlying (Type t)
1612         {
1613                 if (t == TypeManager.enum_type)
1614                         return t;
1615
1616                 t = t.UnderlyingSystemType;
1617                 if (!TypeManager.IsEnumType (t))
1618                         return t;
1619         
1620                 if (t is TypeBuilder) {
1621                         // slow path needed to compile corlib
1622                         if (t == TypeManager.bool_type ||
1623                                         t == TypeManager.byte_type ||
1624                                         t == TypeManager.sbyte_type ||
1625                                         t == TypeManager.char_type ||
1626                                         t == TypeManager.short_type ||
1627                                         t == TypeManager.ushort_type ||
1628                                         t == TypeManager.int32_type ||
1629                                         t == TypeManager.uint32_type ||
1630                                         t == TypeManager.int64_type ||
1631                                         t == TypeManager.uint64_type)
1632                                 return t;
1633                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1634                 }
1635                 TypeCode tc = Type.GetTypeCode (t);
1636
1637                 switch (tc){
1638                 case TypeCode.Boolean:
1639                         return TypeManager.bool_type;
1640                 case TypeCode.Byte:
1641                         return TypeManager.byte_type;
1642                 case TypeCode.SByte:
1643                         return TypeManager.sbyte_type;
1644                 case TypeCode.Char:
1645                         return TypeManager.char_type;
1646                 case TypeCode.Int16:
1647                         return TypeManager.short_type;
1648                 case TypeCode.UInt16:
1649                         return TypeManager.ushort_type;
1650                 case TypeCode.Int32:
1651                         return TypeManager.int32_type;
1652                 case TypeCode.UInt32:
1653                         return TypeManager.uint32_type;
1654                 case TypeCode.Int64:
1655                         return TypeManager.int64_type;
1656                 case TypeCode.UInt64:
1657                         return TypeManager.uint64_type;
1658                 }
1659                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1660         }
1661
1662         //
1663         // When compiling corlib and called with one of the core types, return
1664         // the corresponding typebuilder for that type.
1665         //
1666         public static Type TypeToCoreType (Type t)
1667         {
1668                 if (RootContext.StdLib || (t is TypeBuilder))
1669                         return t;
1670
1671                 TypeCode tc = Type.GetTypeCode (t);
1672
1673                 switch (tc){
1674                 case TypeCode.Boolean:
1675                         return TypeManager.bool_type;
1676                 case TypeCode.Byte:
1677                         return TypeManager.byte_type;
1678                 case TypeCode.SByte:
1679                         return TypeManager.sbyte_type;
1680                 case TypeCode.Char:
1681                         return TypeManager.char_type;
1682                 case TypeCode.Int16:
1683                         return TypeManager.short_type;
1684                 case TypeCode.UInt16:
1685                         return TypeManager.ushort_type;
1686                 case TypeCode.Int32:
1687                         return TypeManager.int32_type;
1688                 case TypeCode.UInt32:
1689                         return TypeManager.uint32_type;
1690                 case TypeCode.Int64:
1691                         return TypeManager.int64_type;
1692                 case TypeCode.UInt64:
1693                         return TypeManager.uint64_type;
1694                 case TypeCode.String:
1695                         return TypeManager.string_type;
1696                 default:
1697                         if (t == typeof (void))
1698                                 return TypeManager.void_type;
1699                         if (t == typeof (object))
1700                                 return TypeManager.object_type;
1701                         if (t == typeof (System.Type))
1702                                 return TypeManager.type_type;
1703                         return t;
1704                 }
1705         }
1706
1707         /// <summary>
1708         ///   Utility function that can be used to probe whether a type
1709         ///   is managed or not.  
1710         /// </summary>
1711         public static bool VerifyUnManaged (Type t, Location loc)
1712         {
1713                 if (t.IsValueType || t.IsPointer){
1714                         //
1715                         // FIXME: this is more complex, we actually need to
1716                         // make sure that the type does not contain any
1717                         // classes itself
1718                         //
1719                         return true;
1720                 }
1721
1722                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1723                         // We need this explicit check here to make it work when
1724                         // compiling corlib.
1725                         return true;
1726
1727                 Report.Error (
1728                         208, loc,
1729                         "Cannot take the address or size of a variable of a managed type ('" +
1730                         CSharpName (t) + "')");
1731                 return false;   
1732         }
1733         
1734         /// <summary>
1735         ///   Returns the name of the indexer in a given type.
1736         /// </summary>
1737         /// <remarks>
1738         ///   The default is not always `Item'.  The user can change this behaviour by
1739         ///   using the DefaultMemberAttribute in the class.
1740         ///
1741         ///   For example, the String class indexer is named `Chars' not `Item' 
1742         /// </remarks>
1743         public static string IndexerPropertyName (Type t)
1744         {
1745                 if (t is TypeBuilder) {
1746                         if (t.IsInterface) {
1747                                 Interface i = LookupInterface (t);
1748
1749                                 if ((i == null) || (i.IndexerName == null))
1750                                         return "Item";
1751
1752                                 return i.IndexerName;
1753                         } else {
1754                                 TypeContainer tc = LookupTypeContainer (t);
1755
1756                                 if ((tc == null) || (tc.IndexerName == null))
1757                                         return "Item";
1758
1759                                 return tc.IndexerName;
1760                         }
1761                 }
1762                 
1763                 System.Attribute attr = System.Attribute.GetCustomAttribute (
1764                         t, TypeManager.default_member_type);
1765                 if (attr != null){
1766                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
1767                         return dma.MemberName;
1768                 }
1769
1770                 return "Item";
1771         }
1772
1773         public static void MakePinned (LocalBuilder builder)
1774         {
1775                 //
1776                 // FIXME: Flag the "LocalBuilder" type as being
1777                 // pinned.  Figure out API.
1778                 //
1779         }
1780
1781
1782         //
1783         // Returns whether the array of memberinfos contains the given method
1784         //
1785         static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
1786         {
1787                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
1788                 
1789                 foreach (MethodBase method in array){
1790                         if (method.Name != new_method.Name)
1791                                 continue;
1792                         
1793                         Type [] old_args = TypeManager.GetArgumentTypes (method);
1794                         int old_count = old_args.Length;
1795                         int i;
1796                         
1797                         if (new_args.Length != old_count)
1798                                 continue;
1799                         
1800                         for (i = 0; i < old_count; i++){
1801                                 if (old_args [i] != new_args [i])
1802                                         break;
1803                         }
1804                         if (i != old_count)
1805                                 continue;
1806
1807                         return true;
1808                 }
1809                 return false;
1810         }
1811         
1812         //
1813         // We copy methods from `new_members' into `target_list' if the signature
1814         // for the method from in the new list does not exist in the target_list
1815         //
1816         // The name is assumed to be the same.
1817         //
1818         public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
1819         {
1820                 if (target_list == null){
1821                         target_list = new ArrayList ();
1822
1823                         foreach (MemberInfo mi in new_members){
1824                                 if (mi is MethodBase)
1825                                         target_list.Add (mi);
1826                         }
1827                         return target_list;
1828                 }
1829                 
1830                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
1831                 target_list.CopyTo (target_array, 0);
1832                 
1833                 foreach (MemberInfo mi in new_members){
1834                         MethodBase new_method = (MethodBase) mi;
1835                         
1836                         if (!ArrayContainsMethod (target_array, new_method))
1837                                 target_list.Add (new_method);
1838                 }
1839                 return target_list;
1840         }
1841
1842         [Flags]
1843         public enum MethodFlags {
1844                 IsObsolete = 1,
1845                 IsObsoleteError = 2,
1846                 ShouldIgnore = 3
1847         }
1848         
1849         //
1850         // Returns the TypeManager.MethodFlags for this method.
1851         // This emits an error 619 / warning 618 if the method is obsolete.
1852         // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
1853         //
1854         static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
1855         {
1856                 MethodFlags flags = 0;
1857                 
1858                 if (mb.DeclaringType is TypeBuilder){
1859                         MethodData method = (MethodData) builder_to_method [mb];
1860                         if (method == null) {
1861                                 // FIXME: implement Obsolete attribute on Property,
1862                                 //        Indexer and Event.
1863                                 return 0;
1864                         }
1865
1866                         return method.GetMethodFlags (loc);
1867                 }
1868
1869                 object [] attrs = mb.GetCustomAttributes (true);
1870                 foreach (object ta in attrs){
1871                         if (!(ta is System.Attribute)){
1872                                 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
1873                                 continue;
1874                         }
1875                         System.Attribute a = (System.Attribute) ta;
1876                         if (a.TypeId == TypeManager.obsolete_attribute_type){
1877                                 ObsoleteAttribute oa = (ObsoleteAttribute) a;
1878
1879                                 string method_desc = TypeManager.CSharpSignature (mb);
1880
1881                                 if (oa.IsError) {
1882                                         Report.Error (619, loc, "Method `" + method_desc +
1883                                                       "' is obsolete: `" + oa.Message + "'");
1884                                         return MethodFlags.IsObsoleteError;
1885                                 } else
1886                                         Report.Warning (618, loc, "Method `" + method_desc +
1887                                                         "' is obsolete: `" + oa.Message + "'");
1888
1889                                 flags |= MethodFlags.IsObsolete;
1890
1891                                 continue;
1892                         }
1893                         
1894                         //
1895                         // Skip over conditional code.
1896                         //
1897                         if (a.TypeId == TypeManager.conditional_attribute_type){
1898                                 ConditionalAttribute ca = (ConditionalAttribute) a;
1899
1900                                 if (RootContext.AllDefines [ca.ConditionString] == null)
1901                                         flags |= MethodFlags.ShouldIgnore;
1902                         }
1903                 }
1904
1905                 return flags;
1906         }
1907         
1908 #region MemberLookup implementation
1909         
1910         //
1911         // Name of the member
1912         //
1913         static string   closure_name;
1914
1915         //
1916         // Whether we allow private members in the result (since FindMembers
1917         // uses NonPublic for both protected and private), we need to distinguish.
1918         //
1919         static bool     closure_private_ok;
1920
1921         //
1922         // Who is invoking us and which type is being queried currently.
1923         //
1924         static Type     closure_invocation_type;
1925         static Type     closure_queried_type;
1926         static Type     closure_start_type;
1927
1928         //
1929         // The assembly that defines the type is that is calling us
1930         //
1931         static Assembly closure_invocation_assembly;
1932
1933         //
1934         // This filter filters by name + whether it is ok to include private
1935         // members in the search
1936         //
1937         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
1938         {
1939                 //
1940                 // Hack: we know that the filter criteria will always be in the `closure'
1941                 // fields. 
1942                 //
1943
1944                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
1945                                 return false;
1946
1947                 if ((closure_start_type == closure_invocation_type) &&
1948                     (m.DeclaringType == closure_invocation_type))
1949                         return true;
1950
1951                 //
1952                 // Ugly: we need to find out the type of `m', and depending
1953                 // on this, tell whether we accept or not
1954                 //
1955                 if (m is MethodBase){
1956                         MethodBase mb = (MethodBase) m;
1957                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
1958
1959                         if (ma == MethodAttributes.Private)
1960                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType);
1961
1962                         //
1963                         // FamAndAssem requires that we not only derivate, but we are on the
1964                         // same assembly.  
1965                         //
1966                         if (ma == MethodAttributes.FamANDAssem){
1967                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
1968                                         return false;
1969                         }
1970
1971                         // Assembly and FamORAssem succeed if we're in the same assembly.
1972                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
1973                                 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
1974                                         return true;
1975                         }
1976
1977                         // We already know that we aren't in the same assembly.
1978                         if (ma == MethodAttributes.Assembly)
1979                                 return false;
1980
1981                         // Family and FamANDAssem require that we derive.
1982                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
1983                                 if (closure_invocation_type == null)
1984                                         return false;
1985
1986                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
1987                                         return false;
1988
1989                                 // Although a derived class can access protected members of its base class
1990                                 // it cannot do so through an instance of the base class (CS1540).
1991                                 if ((closure_invocation_type != closure_start_type) &&
1992                                     closure_invocation_type.IsSubclassOf (closure_start_type))
1993                                         return false;
1994
1995                                 return true;
1996                         }
1997
1998                         // Public.
1999                         return true;
2000                 }
2001
2002                 if (m is FieldInfo){
2003                         FieldInfo fi = (FieldInfo) m;
2004                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2005
2006                         if (fa == FieldAttributes.Private)
2007                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType);
2008
2009                         //
2010                         // FamAndAssem requires that we not only derivate, but we are on the
2011                         // same assembly.  
2012                         //
2013                         if (fa == FieldAttributes.FamANDAssem){
2014                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2015                                         return false;
2016                         }
2017
2018                         // Assembly and FamORAssem succeed if we're in the same assembly.
2019                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2020                                 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2021                                         return true;
2022                         }
2023
2024                         // We already know that we aren't in the same assembly.
2025                         if (fa == FieldAttributes.Assembly)
2026                                 return false;
2027
2028                         // Family and FamANDAssem require that we derive.
2029                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2030                                 if (closure_invocation_type == null)
2031                                         return false;
2032
2033                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2034                                         return false;
2035
2036                                 // Although a derived class can access protected members of its base class
2037                                 // it cannot do so through an instance of the base class (CS1540).
2038                                 if ((closure_invocation_type != closure_start_type) &&
2039                                     closure_invocation_type.IsSubclassOf (closure_start_type))
2040                                         return false;
2041
2042                                 return true;
2043                         }
2044
2045                         // Public.
2046                         return true;
2047                 }
2048
2049                 //
2050                 // EventInfos and PropertyInfos, return true
2051                 //
2052                 return true;
2053         }
2054
2055         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2056
2057         //
2058         // Looks up a member called `name' in the `queried_type'.  This lookup
2059         // is done by code that is contained in the definition for `invocation_type'.
2060         //
2061         // The binding flags are `bf' and the kind of members being looked up are `mt'
2062         //
2063         // Returns an array of a single element for everything but Methods/Constructors
2064         // that might return multiple matches.
2065         //
2066         public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type, 
2067                                                   MemberTypes mt, BindingFlags original_bf, string name)
2068         {
2069                 Timer.StartTimer (TimerType.MemberLookup);
2070
2071                 MemberInfo[] retval = RealMemberLookup (invocation_type, queried_type,
2072                                                         mt, original_bf, name);
2073
2074                 Timer.StopTimer (TimerType.MemberLookup);
2075
2076                 return retval;
2077         }
2078
2079         static MemberInfo [] RealMemberLookup (Type invocation_type, Type queried_type, 
2080                                                MemberTypes mt, BindingFlags original_bf, string name)
2081         {
2082                 BindingFlags bf = original_bf;
2083                 
2084                 ArrayList method_list = null;
2085                 Type current_type = queried_type;
2086                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2087                 bool private_ok;
2088                 bool always_ok_flag = false;
2089                 bool skip_iface_check = true, used_cache = false;
2090
2091                 closure_name = name;
2092                 closure_invocation_type = invocation_type;
2093                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2094                 closure_start_type = queried_type;
2095
2096                 //
2097                 // If we are a nested class, we always have access to our container
2098                 // type names
2099                 //
2100                 if (invocation_type != null){
2101                         string invocation_name = invocation_type.FullName;
2102                         if (invocation_name.IndexOf ('+') != -1){
2103                                 string container = queried_type.FullName + "+";
2104                                 int container_length = container.Length;
2105                                 
2106                                 if (invocation_name.Length > container_length){
2107                                         string shared = invocation_name.Substring (0, container_length);
2108                                 
2109                                         if (shared == container)
2110                                                 always_ok_flag = true;
2111                                 }
2112                         }
2113                 }
2114                 
2115                 do {
2116                         MemberList list;
2117
2118                         //
2119                         // `NonPublic' is lame, because it includes both protected and
2120                         // private methods, so we need to control this behavior by
2121                         // explicitly tracking if a private method is ok or not.
2122                         //
2123                         // The possible cases are:
2124                         //    public, private and protected (internal does not come into the
2125                         //    equation)
2126                         //
2127                         if (invocation_type != null){
2128                                 if (invocation_type == current_type){
2129                                         private_ok = (bf & BindingFlags.NonPublic) != 0;
2130                                 } else
2131                                         private_ok = always_ok_flag;
2132
2133                                 if (private_ok || invocation_type.IsSubclassOf (current_type))
2134                                         bf = original_bf | BindingFlags.NonPublic;
2135                         } else {
2136                                 private_ok = false;
2137                                 bf = original_bf & ~BindingFlags.NonPublic;
2138                         }
2139
2140                         closure_private_ok = private_ok;
2141                         closure_queried_type = current_type;
2142
2143                         Timer.StopTimer (TimerType.MemberLookup);
2144
2145                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2146
2147                         Timer.StartTimer (TimerType.MemberLookup);
2148
2149                         //
2150                         // When queried for an interface type, the cache will automatically check all
2151                         // inherited members, so we don't need to do this here.  However, this only
2152                         // works if we already used the cache in the first iteration of this loop.
2153                         //
2154                         // If we used the cache in any further iteration, we can still terminate the
2155                         // loop since the cache always looks in all parent classes.
2156                         //
2157
2158                         if (used_cache)
2159                                 searching = false;
2160                         else
2161                                 skip_iface_check = false;
2162
2163                         if (current_type == TypeManager.object_type)
2164                                 searching = false;
2165                         else {
2166                                 current_type = current_type.BaseType;
2167                                 
2168                                 //
2169                                 // This happens with interfaces, they have a null
2170                                 // basetype.  Look members up in the Object class.
2171                                 //
2172                                 if (current_type == null)
2173                                         current_type = TypeManager.object_type;
2174                         }
2175                         
2176                         if (list.Count == 0)
2177                                 continue;
2178                         
2179                         //
2180                         // Events and types are returned by both `static' and `instance'
2181                         // searches, which means that our above FindMembers will
2182                         // return two copies of the same.
2183                         //
2184                         if (list.Count == 1 && !(list [0] is MethodBase)){
2185                                 return (MemberInfo []) list;
2186                         }
2187
2188                         //
2189                         // Multiple properties: we query those just to find out the indexer
2190                         // name
2191                         //
2192                         if (list [0] is PropertyInfo)
2193                                 return (MemberInfo []) list;
2194
2195                         //
2196                         // We found methods, turn the search into "method scan"
2197                         // mode.
2198                         //
2199                         
2200                         method_list = CopyNewMethods (method_list, list);
2201                         mt &= (MemberTypes.Method | MemberTypes.Constructor);
2202                 } while (searching);
2203
2204                 if (method_list != null && method_list.Count > 0)
2205                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2206
2207                 //
2208                 // This happens if we already used the cache in the first iteration, in this case
2209                 // the cache already looked in all interfaces.
2210                 //
2211                 if (skip_iface_check)
2212                         return null;
2213
2214                 //
2215                 // Interfaces do not list members they inherit, so we have to
2216                 // scan those.
2217                 // 
2218                 if (!queried_type.IsInterface)
2219                         return null;
2220
2221                 if (queried_type.IsArray)
2222                         queried_type = TypeManager.array_type;
2223                 
2224                 Type [] ifaces = GetInterfaces (queried_type);
2225                 if (ifaces == null)
2226                         return null;
2227                 
2228                 foreach (Type itype in ifaces){
2229                         MemberInfo [] x;
2230
2231                         x = MemberLookup (null, itype, mt, bf, name);
2232                         if (x != null)
2233                                 return x;
2234                 }
2235                                         
2236                 return null;
2237         }
2238 #endregion
2239         
2240 }
2241
2242 /// <summary>
2243 ///   There is exactly one instance of this class per type.
2244 /// </summary>
2245 public sealed class TypeHandle : IMemberContainer {
2246         public readonly TypeHandle BaseType;
2247
2248         readonly int id = ++next_id;
2249         static int next_id = 0;
2250
2251         /// <summary>
2252         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2253         ///   a TypeHandle yet, a new instance of it is created.  This static method
2254         ///   ensures that we'll only have one TypeHandle instance per type.
2255         /// </summary>
2256         public static TypeHandle GetTypeHandle (Type t)
2257         {
2258                 TypeHandle handle = (TypeHandle) type_hash [t];
2259                 if (handle != null)
2260                         return handle;
2261
2262                 handle = new TypeHandle (t);
2263                 type_hash.Add (t, handle);
2264                 return handle;
2265         }
2266
2267         /// <summary>
2268         ///   Returns the TypeHandle for TypeManager.object_type.
2269         /// </summary>
2270         public static IMemberContainer ObjectType {
2271                 get {
2272                         if (object_type != null)
2273                                 return object_type;
2274
2275                         object_type = GetTypeHandle (TypeManager.object_type);
2276
2277                         return object_type;
2278                 }
2279         }
2280
2281         /// <summary>
2282         ///   Returns the TypeHandle for TypeManager.array_type.
2283         /// </summary>
2284         public static IMemberContainer ArrayType {
2285                 get {
2286                         if (array_type != null)
2287                                 return array_type;
2288
2289                         array_type = GetTypeHandle (TypeManager.array_type);
2290
2291                         return array_type;
2292                 }
2293         }
2294
2295         private static PtrHashtable type_hash = new PtrHashtable ();
2296
2297         private static TypeHandle object_type = null;
2298         private static TypeHandle array_type = null;
2299
2300         private Type type;
2301         private bool is_interface;
2302         private MemberCache member_cache;
2303
2304         private TypeHandle (Type type)
2305         {
2306                 this.type = type;
2307                 if (type.BaseType != null)
2308                         BaseType = GetTypeHandle (type.BaseType);
2309                 else if ((type != TypeManager.object_type) && (type != typeof (object)))
2310                         is_interface = true;
2311                 this.member_cache = new MemberCache (this);
2312         }
2313
2314         // IMemberContainer methods
2315
2316         public string Name {
2317                 get {
2318                         return type.FullName;
2319                 }
2320         }
2321
2322         public Type Type {
2323                 get {
2324                         return type;
2325                 }
2326         }
2327
2328         public IMemberContainer Parent {
2329                 get {
2330                         return BaseType;
2331                 }
2332         }
2333
2334         public bool IsInterface {
2335                 get {
2336                         return is_interface;
2337                 }
2338         }
2339
2340         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2341         {
2342                 if (mt == MemberTypes.Event)
2343                         return new MemberList (type.GetEvents (bf | BindingFlags.DeclaredOnly));
2344                 else
2345                         return new MemberList (type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2346                                                                  null, null));
2347         }
2348
2349         // IMemberFinder methods
2350
2351         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2352                                        MemberFilter filter, object criteria)
2353         {
2354                 return member_cache.FindMembers (mt, bf, name, filter, criteria);
2355         }
2356
2357         public MemberCache MemberCache {
2358                 get {
2359                         return member_cache;
2360                 }
2361         }
2362
2363         public override string ToString ()
2364         {
2365                 if (BaseType != null)
2366                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2367                 else
2368                         return "TypeHandle (" + id + "," + Name + ")";
2369         }
2370 }
2371
2372 }