2002-10-21 Miguel de Icaza <miguel@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) && t != TypeManager.string_type)
1102                         return true;
1103
1104                 if (IsEnumType (t))
1105                         return true;
1106
1107                 if (t.IsPointer)
1108                         return true;
1109
1110                 if (IsValueType (t)){
1111                         if (t is TypeBuilder){
1112                                 TypeContainer tc = LookupTypeContainer (t);
1113
1114                                 foreach (Field f in tc.Fields){
1115                                         if (f.FieldBuilder.IsStatic)
1116                                                 continue;
1117                                         if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1118                                                 return false;
1119                                 }
1120                         } else {
1121                                 FieldInfo [] fields = t.GetFields ();
1122
1123                                 foreach (FieldInfo f in fields){
1124                                         if (f.IsStatic)
1125                                                 continue;
1126                                         if (!IsUnmanagedType (f.FieldType))
1127                                                 return false;
1128                                 }
1129                         }
1130                         return true;
1131                 }
1132
1133                 return false;
1134         }
1135                 
1136         public static bool IsValueType (Type t)
1137         {
1138                 if (t.IsSubclassOf (TypeManager.value_type))
1139                         return true;
1140                 else
1141                         return false;
1142         }
1143         
1144         public static bool IsInterfaceType (Type t)
1145         {
1146                 Interface iface = builder_to_declspace [t] as Interface;
1147
1148                 if (iface != null)
1149                         return true;
1150                 else
1151                         return false;
1152         }
1153
1154         //
1155         // Checks whether `type' is a subclass or nested child of `parent'.
1156         //
1157         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1158         {
1159                 do {
1160                         if ((type == parent) || type.IsSubclassOf (parent))
1161                                 return true;
1162
1163                         // Handle nested types.
1164                         type = type.DeclaringType;
1165                 } while (type != null);
1166
1167                 return false;
1168         }
1169
1170         //
1171         // Checks whether `type' is a nested child of `parent'.
1172         //
1173         public static bool IsNestedChildOf (Type type, Type parent)
1174         {
1175                 if ((type == parent) || type.IsSubclassOf (parent))
1176                         return false;
1177                 else
1178                         return IsSubclassOrNestedChildOf (type, parent);
1179         }
1180
1181         /// <summary>
1182         ///   Returns the User Defined Types
1183         /// </summary>
1184         public static ArrayList UserTypes {
1185                 get {
1186                         return user_types;
1187                 }
1188         }
1189
1190         public static Hashtable TypeContainers {
1191                 get {
1192                         return typecontainers;
1193                 }
1194         }
1195
1196         static Hashtable builder_to_constant;
1197
1198         public static void RegisterConstant (FieldBuilder fb, Const c)
1199         {
1200                 if (builder_to_constant == null)
1201                         builder_to_constant = new PtrHashtable ();
1202
1203                 if (builder_to_constant.Contains (fb))
1204                         return;
1205
1206                 builder_to_constant.Add (fb, c);
1207         }
1208
1209         public static Const LookupConstant (FieldBuilder fb)
1210         {
1211                 if (builder_to_constant == null)
1212                         return null;
1213                 
1214                 return (Const) builder_to_constant [fb];
1215         }
1216         
1217         /// <summary>
1218         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1219         /// </summary>
1220         ///
1221         /// <remarks>
1222         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1223         ///   for anything which is dynamic, and we need this in a number of places,
1224         ///   we register this information here, and use it afterwards.
1225         /// </remarks>
1226         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1227         {
1228                 if (args == null)
1229                         args = NoTypes;
1230                                 
1231                 method_arguments.Add (mb, args);
1232                 method_internal_params.Add (mb, ip);
1233                 
1234                 return true;
1235         }
1236         
1237         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1238         {
1239                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1240                         return null;
1241                 
1242                 if (method_internal_params.Contains (mb))
1243                         return (InternalParameters) method_internal_params [mb];
1244                 else
1245                         throw new Exception ("Argument for Method not registered" + mb);
1246         }
1247
1248         /// <summary>
1249         ///    Returns the argument types for a method based on its methodbase
1250         ///
1251         ///    For dynamic methods, we use the compiler provided types, for
1252         ///    methods from existing assemblies we load them from GetParameters,
1253         ///    and insert them into the cache
1254         /// </summary>
1255         static public Type [] GetArgumentTypes (MethodBase mb)
1256         {
1257                 if (method_arguments.Contains (mb))
1258                         return (Type []) method_arguments [mb];
1259                 else {
1260                         ParameterInfo [] pi = mb.GetParameters ();
1261                         int c = pi.Length;
1262                         Type [] types = new Type [c];
1263                         
1264                         for (int i = 0; i < c; i++)
1265                                 types [i] = pi [i].ParameterType;
1266
1267                         method_arguments.Add (mb, types);
1268                         return types;
1269                 }
1270         }
1271
1272         /// <summary>
1273         ///    Returns the argument types for an indexer based on its PropertyInfo
1274         ///
1275         ///    For dynamic indexers, we use the compiler provided types, for
1276         ///    indexers from existing assemblies we load them from GetParameters,
1277         ///    and insert them into the cache
1278         /// </summary>
1279         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1280         {
1281                 if (indexer_arguments.Contains (indexer))
1282                         return (Type []) indexer_arguments [indexer];
1283                 else if (indexer is PropertyBuilder)
1284                         // If we're a PropertyBuilder and not in the
1285                         // `indexer_arguments' hash, then we're a property and
1286                         // not an indexer.
1287                         return NoTypes;
1288                 else {
1289                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1290                         // Property, not an indexer.
1291                         if (pi == null)
1292                                 return NoTypes;
1293                         int c = pi.Length;
1294                         Type [] types = new Type [c];
1295                         
1296                         for (int i = 0; i < c; i++)
1297                                 types [i] = pi [i].ParameterType;
1298
1299                         indexer_arguments.Add (indexer, types);
1300                         return types;
1301                 }
1302         }
1303         
1304         // <remarks>
1305         //  This is a workaround the fact that GetValue is not
1306         //  supported for dynamic types
1307         // </remarks>
1308         static Hashtable fields = new Hashtable ();
1309         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1310         {
1311                 if (fields.Contains (fb))
1312                         return false;
1313
1314                 fields.Add (fb, value);
1315
1316                 return true;
1317         }
1318
1319         static public object GetValue (FieldBuilder fb)
1320         {
1321                 return fields [fb];
1322         }
1323
1324         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1325         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1326         {
1327                 if (fieldbuilders_to_fields.Contains (fb))
1328                         return false;
1329
1330                 fieldbuilders_to_fields.Add (fb, f);
1331                 return true;
1332         }
1333
1334         static public FieldBase GetField (FieldInfo fb)
1335         {
1336                 return (FieldBase) fieldbuilders_to_fields [fb];
1337         }
1338         
1339         static Hashtable events;
1340
1341         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1342         {
1343                 if (events == null)
1344                         events = new Hashtable ();
1345
1346                 if (events.Contains (eb))
1347                         return false;
1348
1349                 events.Add (eb, new Pair (add, remove));
1350
1351                 return true;
1352         }
1353
1354         static public MethodInfo GetAddMethod (EventInfo ei)
1355         {
1356                 if (ei is MyEventBuilder) {
1357                         Pair pair = (Pair) events [ei];
1358
1359                         return (MethodInfo) pair.First;
1360                 } else
1361                         return ei.GetAddMethod ();
1362         }
1363
1364         static public MethodInfo GetRemoveMethod (EventInfo ei)
1365         {
1366                 if (ei is MyEventBuilder) {
1367                         Pair pair = (Pair) events [ei];
1368
1369                         return (MethodInfo) pair.Second;
1370                 } else
1371                         return ei.GetAddMethod ();
1372         }
1373
1374         static Hashtable priv_fields_events;
1375
1376         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1377         {
1378                 if (priv_fields_events == null)
1379                         priv_fields_events = new Hashtable ();
1380
1381                 if (priv_fields_events.Contains (einfo))
1382                         return false;
1383
1384                 priv_fields_events.Add (einfo, builder);
1385
1386                 return true;
1387         }
1388
1389         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1390         {
1391                 return (MemberInfo) priv_fields_events [ei];
1392         }
1393                 
1394         static Hashtable properties;
1395         
1396         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1397         {
1398                 if (properties == null)
1399                         properties = new Hashtable ();
1400
1401                 if (properties.Contains (pb))
1402                         return false;
1403
1404                 properties.Add (pb, new Pair (get, set));
1405
1406                 return true;
1407         }
1408
1409         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get, MethodBase set, Type[] args)
1410         {
1411                 if (!RegisterProperty (pb, get,set))
1412                         return false;
1413
1414                 indexer_arguments.Add (pb, args);
1415
1416                 return true;
1417         }
1418
1419         //
1420         // FIXME: we need to return the accessors depending on whether
1421         // they are visible or not.
1422         //
1423         static public MethodInfo [] GetAccessors (PropertyInfo pi)
1424         {
1425                 MethodInfo [] ret;
1426
1427                 if (pi is PropertyBuilder){
1428                         Pair pair = (Pair) properties [pi];
1429
1430                         ret = new MethodInfo [2];
1431                         ret [0] = (MethodInfo) pair.First;
1432                         ret [1] = (MethodInfo) pair.Second;
1433
1434                         return ret;
1435                 } else {
1436                         MethodInfo [] mi = new MethodInfo [2];
1437
1438                         //
1439                         // Why this and not pi.GetAccessors?
1440                         // Because sometimes index 0 is the getter
1441                         // sometimes it is 1
1442                         //
1443                         mi [0] = pi.GetGetMethod (true);
1444                         mi [1] = pi.GetSetMethod (true);
1445
1446                         return mi;
1447                 }
1448         }
1449
1450         static public MethodInfo GetPropertyGetter (PropertyInfo pi)
1451         {
1452                 if (pi is PropertyBuilder){
1453                         Pair de = (Pair) properties [pi];
1454
1455                         return (MethodInfo) de.Second;
1456                 } else
1457                         return pi.GetSetMethod ();
1458         }
1459
1460         static public MethodInfo GetPropertySetter (PropertyInfo pi)
1461         {
1462                 if (pi is PropertyBuilder){
1463                         Pair de = (Pair) properties [pi];
1464
1465                         return (MethodInfo) de.First;
1466                 } else
1467                         return pi.GetGetMethod ();
1468         }
1469
1470         /// <summary>
1471         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1472         ///   of an interface.  
1473         /// </summary>
1474         ///
1475         /// <remarks>
1476         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1477         ///   be IA, IB, IC.
1478         /// </remarks>
1479         public static Type [] ExpandInterfaces (Type [] base_interfaces)
1480         {
1481                 ArrayList new_ifaces = new ArrayList ();
1482                 
1483                 foreach (Type iface in base_interfaces){
1484                         if (!new_ifaces.Contains (iface))
1485                                 new_ifaces.Add (iface);
1486                         
1487                         Type [] implementing = TypeManager.GetInterfaces (iface);
1488                         
1489                         foreach (Type imp in implementing){
1490                                 if (!new_ifaces.Contains (imp))
1491                                         new_ifaces.Add (imp);
1492                         }
1493                 }
1494                 Type [] ret = new Type [new_ifaces.Count];
1495                 new_ifaces.CopyTo (ret, 0);
1496                 return ret;
1497         }
1498                 
1499         /// <summary>
1500         ///   This function returns the interfaces in the type `t'.  Works with
1501         ///   both types and TypeBuilders.
1502         /// </summary>
1503         public static Type [] GetInterfaces (Type t)
1504         {
1505                 //
1506                 // The reason for catching the Array case is that Reflection.Emit
1507                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1508                 // but will still throw an exception if we try to call GetInterfaces
1509                 // on the type.
1510                 //
1511                 // Since the array interfaces are always constant, we return those for
1512                 // the System.Array
1513                 //
1514                 
1515                 if (t.IsArray)
1516                         t = TypeManager.array_type;
1517                 
1518                 if (t is TypeBuilder){
1519                         Type [] parent_ifaces;
1520                         
1521                         if (t.BaseType == null)
1522                                 parent_ifaces = NoTypes;
1523                         else
1524                                 parent_ifaces = GetInterfaces (t.BaseType);
1525                         Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1526                         if (type_ifaces == null)
1527                                 type_ifaces = NoTypes;
1528
1529                         int parent_count = parent_ifaces.Length;
1530                         Type [] result = new Type [parent_count + type_ifaces.Length];
1531                         parent_ifaces.CopyTo (result, 0);
1532                         type_ifaces.CopyTo (result, parent_count);
1533
1534                         return result;
1535                 } else
1536                         return t.GetInterfaces ();
1537         }
1538         
1539         /// <remarks>
1540         ///  The following is used to check if a given type implements an interface.
1541         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1542         /// </remarks>
1543         public static bool ImplementsInterface (Type t, Type iface)
1544         {
1545                 Type [] interfaces;
1546
1547                 //
1548                 // FIXME OPTIMIZATION:
1549                 // as soon as we hit a non-TypeBuiler in the interface
1550                 // chain, we could return, as the `Type.GetInterfaces'
1551                 // will return all the interfaces implement by the type
1552                 // or its parents.
1553                 //
1554                 do {
1555                         interfaces = GetInterfaces (t);
1556
1557                         if (interfaces != null){
1558                                 foreach (Type i in interfaces){
1559                                         if (i == iface)
1560                                                 return true;
1561                                 }
1562                         }
1563                         
1564                         t = t.BaseType;
1565                 } while (t != null);
1566                 
1567                 return false;
1568         }
1569
1570         // This is a custom version of Convert.ChangeType() which works
1571         // with the TypeBuilder defined types when compiling corlib.
1572         public static object ChangeType (object value, Type conversionType)
1573         {
1574                 if (!(value is IConvertible))
1575                         throw new ArgumentException ();
1576
1577                 IConvertible convertValue = (IConvertible) value;
1578                 CultureInfo ci = CultureInfo.CurrentCulture;
1579                 NumberFormatInfo provider = ci.NumberFormat;
1580
1581                 //
1582                 // We must use Type.Equals() here since `conversionType' is
1583                 // the TypeBuilder created version of a system type and not
1584                 // the system type itself.  You cannot use Type.GetTypeCode()
1585                 // on such a type - it'd always return TypeCode.Object.
1586                 //
1587                 if (conversionType.Equals (typeof (Boolean)))
1588                         return (object)(convertValue.ToBoolean (provider));
1589                 else if (conversionType.Equals (typeof (Byte)))
1590                         return (object)(convertValue.ToByte (provider));
1591                 else if (conversionType.Equals (typeof (Char)))
1592                         return (object)(convertValue.ToChar (provider));
1593                 else if (conversionType.Equals (typeof (DateTime)))
1594                         return (object)(convertValue.ToDateTime (provider));
1595                 else if (conversionType.Equals (typeof (Decimal)))
1596                         return (object)(convertValue.ToDecimal (provider));
1597                 else if (conversionType.Equals (typeof (Double)))
1598                         return (object)(convertValue.ToDouble (provider));
1599                 else if (conversionType.Equals (typeof (Int16)))
1600                         return (object)(convertValue.ToInt16 (provider));
1601                 else if (conversionType.Equals (typeof (Int32)))
1602                         return (object)(convertValue.ToInt32 (provider));
1603                 else if (conversionType.Equals (typeof (Int64)))
1604                         return (object)(convertValue.ToInt64 (provider));
1605                 else if (conversionType.Equals (typeof (SByte)))
1606                         return (object)(convertValue.ToSByte (provider));
1607                 else if (conversionType.Equals (typeof (Single)))
1608                         return (object)(convertValue.ToSingle (provider));
1609                 else if (conversionType.Equals (typeof (String)))
1610                         return (object)(convertValue.ToString (provider));
1611                 else if (conversionType.Equals (typeof (UInt16)))
1612                         return (object)(convertValue.ToUInt16 (provider));
1613                 else if (conversionType.Equals (typeof (UInt32)))
1614                         return (object)(convertValue.ToUInt32 (provider));
1615                 else if (conversionType.Equals (typeof (UInt64)))
1616                         return (object)(convertValue.ToUInt64 (provider));
1617                 else if (conversionType.Equals (typeof (Object)))
1618                         return (object)(value);
1619                 else 
1620                         throw new InvalidCastException ();
1621         }
1622
1623         //
1624         // This is needed, because enumerations from assemblies
1625         // do not report their underlyingtype, but they report
1626         // themselves
1627         //
1628         public static Type EnumToUnderlying (Type t)
1629         {
1630                 if (t == TypeManager.enum_type)
1631                         return t;
1632
1633                 t = t.UnderlyingSystemType;
1634                 if (!TypeManager.IsEnumType (t))
1635                         return t;
1636         
1637                 if (t is TypeBuilder) {
1638                         // slow path needed to compile corlib
1639                         if (t == TypeManager.bool_type ||
1640                                         t == TypeManager.byte_type ||
1641                                         t == TypeManager.sbyte_type ||
1642                                         t == TypeManager.char_type ||
1643                                         t == TypeManager.short_type ||
1644                                         t == TypeManager.ushort_type ||
1645                                         t == TypeManager.int32_type ||
1646                                         t == TypeManager.uint32_type ||
1647                                         t == TypeManager.int64_type ||
1648                                         t == TypeManager.uint64_type)
1649                                 return t;
1650                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1651                 }
1652                 TypeCode tc = Type.GetTypeCode (t);
1653
1654                 switch (tc){
1655                 case TypeCode.Boolean:
1656                         return TypeManager.bool_type;
1657                 case TypeCode.Byte:
1658                         return TypeManager.byte_type;
1659                 case TypeCode.SByte:
1660                         return TypeManager.sbyte_type;
1661                 case TypeCode.Char:
1662                         return TypeManager.char_type;
1663                 case TypeCode.Int16:
1664                         return TypeManager.short_type;
1665                 case TypeCode.UInt16:
1666                         return TypeManager.ushort_type;
1667                 case TypeCode.Int32:
1668                         return TypeManager.int32_type;
1669                 case TypeCode.UInt32:
1670                         return TypeManager.uint32_type;
1671                 case TypeCode.Int64:
1672                         return TypeManager.int64_type;
1673                 case TypeCode.UInt64:
1674                         return TypeManager.uint64_type;
1675                 }
1676                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1677         }
1678
1679         //
1680         // When compiling corlib and called with one of the core types, return
1681         // the corresponding typebuilder for that type.
1682         //
1683         public static Type TypeToCoreType (Type t)
1684         {
1685                 if (RootContext.StdLib || (t is TypeBuilder))
1686                         return t;
1687
1688                 TypeCode tc = Type.GetTypeCode (t);
1689
1690                 switch (tc){
1691                 case TypeCode.Boolean:
1692                         return TypeManager.bool_type;
1693                 case TypeCode.Byte:
1694                         return TypeManager.byte_type;
1695                 case TypeCode.SByte:
1696                         return TypeManager.sbyte_type;
1697                 case TypeCode.Char:
1698                         return TypeManager.char_type;
1699                 case TypeCode.Int16:
1700                         return TypeManager.short_type;
1701                 case TypeCode.UInt16:
1702                         return TypeManager.ushort_type;
1703                 case TypeCode.Int32:
1704                         return TypeManager.int32_type;
1705                 case TypeCode.UInt32:
1706                         return TypeManager.uint32_type;
1707                 case TypeCode.Int64:
1708                         return TypeManager.int64_type;
1709                 case TypeCode.UInt64:
1710                         return TypeManager.uint64_type;
1711                 case TypeCode.String:
1712                         return TypeManager.string_type;
1713                 default:
1714                         if (t == typeof (void))
1715                                 return TypeManager.void_type;
1716                         if (t == typeof (object))
1717                                 return TypeManager.object_type;
1718                         if (t == typeof (System.Type))
1719                                 return TypeManager.type_type;
1720                         return t;
1721                 }
1722         }
1723
1724         /// <summary>
1725         ///   Utility function that can be used to probe whether a type
1726         ///   is managed or not.  
1727         /// </summary>
1728         public static bool VerifyUnManaged (Type t, Location loc)
1729         {
1730                 if (t.IsValueType || t.IsPointer){
1731                         //
1732                         // FIXME: this is more complex, we actually need to
1733                         // make sure that the type does not contain any
1734                         // classes itself
1735                         //
1736                         return true;
1737                 }
1738
1739                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1740                         // We need this explicit check here to make it work when
1741                         // compiling corlib.
1742                         return true;
1743
1744                 Report.Error (
1745                         208, loc,
1746                         "Cannot take the address or size of a variable of a managed type ('" +
1747                         CSharpName (t) + "')");
1748                 return false;   
1749         }
1750         
1751         /// <summary>
1752         ///   Returns the name of the indexer in a given type.
1753         /// </summary>
1754         /// <remarks>
1755         ///   The default is not always `Item'.  The user can change this behaviour by
1756         ///   using the DefaultMemberAttribute in the class.
1757         ///
1758         ///   For example, the String class indexer is named `Chars' not `Item' 
1759         /// </remarks>
1760         public static string IndexerPropertyName (Type t)
1761         {
1762                 if (t is TypeBuilder) {
1763                         if (t.IsInterface) {
1764                                 Interface i = LookupInterface (t);
1765
1766                                 if ((i == null) || (i.IndexerName == null))
1767                                         return "Item";
1768
1769                                 return i.IndexerName;
1770                         } else {
1771                                 TypeContainer tc = LookupTypeContainer (t);
1772
1773                                 if ((tc == null) || (tc.IndexerName == null))
1774                                         return "Item";
1775
1776                                 return tc.IndexerName;
1777                         }
1778                 }
1779                 
1780                 System.Attribute attr = System.Attribute.GetCustomAttribute (
1781                         t, TypeManager.default_member_type);
1782                 if (attr != null){
1783                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
1784                         return dma.MemberName;
1785                 }
1786
1787                 return "Item";
1788         }
1789
1790         public static void MakePinned (LocalBuilder builder)
1791         {
1792                 //
1793                 // FIXME: Flag the "LocalBuilder" type as being
1794                 // pinned.  Figure out API.
1795                 //
1796         }
1797
1798
1799         //
1800         // Returns whether the array of memberinfos contains the given method
1801         //
1802         static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
1803         {
1804                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
1805                 
1806                 foreach (MethodBase method in array){
1807                         if (method.Name != new_method.Name)
1808                                 continue;
1809                         
1810                         Type [] old_args = TypeManager.GetArgumentTypes (method);
1811                         int old_count = old_args.Length;
1812                         int i;
1813                         
1814                         if (new_args.Length != old_count)
1815                                 continue;
1816                         
1817                         for (i = 0; i < old_count; i++){
1818                                 if (old_args [i] != new_args [i])
1819                                         break;
1820                         }
1821                         if (i != old_count)
1822                                 continue;
1823
1824                         return true;
1825                 }
1826                 return false;
1827         }
1828         
1829         //
1830         // We copy methods from `new_members' into `target_list' if the signature
1831         // for the method from in the new list does not exist in the target_list
1832         //
1833         // The name is assumed to be the same.
1834         //
1835         public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
1836         {
1837                 if (target_list == null){
1838                         target_list = new ArrayList ();
1839
1840                         foreach (MemberInfo mi in new_members){
1841                                 if (mi is MethodBase)
1842                                         target_list.Add (mi);
1843                         }
1844                         return target_list;
1845                 }
1846                 
1847                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
1848                 target_list.CopyTo (target_array, 0);
1849                 
1850                 foreach (MemberInfo mi in new_members){
1851                         MethodBase new_method = (MethodBase) mi;
1852                         
1853                         if (!ArrayContainsMethod (target_array, new_method))
1854                                 target_list.Add (new_method);
1855                 }
1856                 return target_list;
1857         }
1858
1859         [Flags]
1860         public enum MethodFlags {
1861                 IsObsolete = 1,
1862                 IsObsoleteError = 2,
1863                 ShouldIgnore = 3
1864         }
1865         
1866         //
1867         // Returns the TypeManager.MethodFlags for this method.
1868         // This emits an error 619 / warning 618 if the method is obsolete.
1869         // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
1870         //
1871         static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
1872         {
1873                 MethodFlags flags = 0;
1874                 
1875                 if (mb.DeclaringType is TypeBuilder){
1876                         MethodData method = (MethodData) builder_to_method [mb];
1877                         if (method == null) {
1878                                 // FIXME: implement Obsolete attribute on Property,
1879                                 //        Indexer and Event.
1880                                 return 0;
1881                         }
1882
1883                         return method.GetMethodFlags (loc);
1884                 }
1885
1886                 object [] attrs = mb.GetCustomAttributes (true);
1887                 foreach (object ta in attrs){
1888                         if (!(ta is System.Attribute)){
1889                                 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
1890                                 continue;
1891                         }
1892                         System.Attribute a = (System.Attribute) ta;
1893                         if (a.TypeId == TypeManager.obsolete_attribute_type){
1894                                 ObsoleteAttribute oa = (ObsoleteAttribute) a;
1895
1896                                 string method_desc = TypeManager.CSharpSignature (mb);
1897
1898                                 if (oa.IsError) {
1899                                         Report.Error (619, loc, "Method `" + method_desc +
1900                                                       "' is obsolete: `" + oa.Message + "'");
1901                                         return MethodFlags.IsObsoleteError;
1902                                 } else
1903                                         Report.Warning (618, loc, "Method `" + method_desc +
1904                                                         "' is obsolete: `" + oa.Message + "'");
1905
1906                                 flags |= MethodFlags.IsObsolete;
1907
1908                                 continue;
1909                         }
1910                         
1911                         //
1912                         // Skip over conditional code.
1913                         //
1914                         if (a.TypeId == TypeManager.conditional_attribute_type){
1915                                 ConditionalAttribute ca = (ConditionalAttribute) a;
1916
1917                                 if (RootContext.AllDefines [ca.ConditionString] == null)
1918                                         flags |= MethodFlags.ShouldIgnore;
1919                         }
1920                 }
1921
1922                 return flags;
1923         }
1924         
1925 #region MemberLookup implementation
1926         
1927         //
1928         // Name of the member
1929         //
1930         static string   closure_name;
1931
1932         //
1933         // Whether we allow private members in the result (since FindMembers
1934         // uses NonPublic for both protected and private), we need to distinguish.
1935         //
1936         static bool     closure_private_ok;
1937
1938         //
1939         // Who is invoking us and which type is being queried currently.
1940         //
1941         static Type     closure_invocation_type;
1942         static Type     closure_queried_type;
1943         static Type     closure_start_type;
1944
1945         //
1946         // The assembly that defines the type is that is calling us
1947         //
1948         static Assembly closure_invocation_assembly;
1949
1950         //
1951         // This filter filters by name + whether it is ok to include private
1952         // members in the search
1953         //
1954         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
1955         {
1956                 //
1957                 // Hack: we know that the filter criteria will always be in the `closure'
1958                 // fields. 
1959                 //
1960
1961                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
1962                                 return false;
1963
1964                 if ((closure_start_type == closure_invocation_type) &&
1965                     (m.DeclaringType == closure_invocation_type))
1966                         return true;
1967
1968                 //
1969                 // Ugly: we need to find out the type of `m', and depending
1970                 // on this, tell whether we accept or not
1971                 //
1972                 if (m is MethodBase){
1973                         MethodBase mb = (MethodBase) m;
1974                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
1975
1976                         if (ma == MethodAttributes.Private)
1977                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType);
1978
1979                         //
1980                         // FamAndAssem requires that we not only derivate, but we are on the
1981                         // same assembly.  
1982                         //
1983                         if (ma == MethodAttributes.FamANDAssem){
1984                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
1985                                         return false;
1986                         }
1987
1988                         // Assembly and FamORAssem succeed if we're in the same assembly.
1989                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
1990                                 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
1991                                         return true;
1992                         }
1993
1994                         // We already know that we aren't in the same assembly.
1995                         if (ma == MethodAttributes.Assembly)
1996                                 return false;
1997
1998                         // Family and FamANDAssem require that we derive.
1999                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2000                                 if (closure_invocation_type == null)
2001                                         return false;
2002
2003                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2004                                         return false;
2005
2006                                 // Although a derived class can access protected members of its base class
2007                                 // it cannot do so through an instance of the base class (CS1540).
2008                                 if ((closure_invocation_type != closure_start_type) &&
2009                                     closure_invocation_type.IsSubclassOf (closure_start_type))
2010                                         return false;
2011
2012                                 return true;
2013                         }
2014
2015                         // Public.
2016                         return true;
2017                 }
2018
2019                 if (m is FieldInfo){
2020                         FieldInfo fi = (FieldInfo) m;
2021                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2022
2023                         if (fa == FieldAttributes.Private)
2024                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType);
2025
2026                         //
2027                         // FamAndAssem requires that we not only derivate, but we are on the
2028                         // same assembly.  
2029                         //
2030                         if (fa == FieldAttributes.FamANDAssem){
2031                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2032                                         return false;
2033                         }
2034
2035                         // Assembly and FamORAssem succeed if we're in the same assembly.
2036                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2037                                 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2038                                         return true;
2039                         }
2040
2041                         // We already know that we aren't in the same assembly.
2042                         if (fa == FieldAttributes.Assembly)
2043                                 return false;
2044
2045                         // Family and FamANDAssem require that we derive.
2046                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2047                                 if (closure_invocation_type == null)
2048                                         return false;
2049
2050                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2051                                         return false;
2052
2053                                 // Although a derived class can access protected members of its base class
2054                                 // it cannot do so through an instance of the base class (CS1540).
2055                                 if ((closure_invocation_type != closure_start_type) &&
2056                                     closure_invocation_type.IsSubclassOf (closure_start_type))
2057                                         return false;
2058
2059                                 return true;
2060                         }
2061
2062                         // Public.
2063                         return true;
2064                 }
2065
2066                 //
2067                 // EventInfos and PropertyInfos, return true
2068                 //
2069                 return true;
2070         }
2071
2072         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2073
2074         //
2075         // Looks up a member called `name' in the `queried_type'.  This lookup
2076         // is done by code that is contained in the definition for `invocation_type'.
2077         //
2078         // The binding flags are `bf' and the kind of members being looked up are `mt'
2079         //
2080         // Returns an array of a single element for everything but Methods/Constructors
2081         // that might return multiple matches.
2082         //
2083         public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type, 
2084                                                   MemberTypes mt, BindingFlags original_bf, string name)
2085         {
2086                 Timer.StartTimer (TimerType.MemberLookup);
2087
2088                 MemberInfo[] retval = RealMemberLookup (invocation_type, queried_type,
2089                                                         mt, original_bf, name);
2090
2091                 Timer.StopTimer (TimerType.MemberLookup);
2092
2093                 return retval;
2094         }
2095
2096         static MemberInfo [] RealMemberLookup (Type invocation_type, Type queried_type, 
2097                                                MemberTypes mt, BindingFlags original_bf, string name)
2098         {
2099                 BindingFlags bf = original_bf;
2100                 
2101                 ArrayList method_list = null;
2102                 Type current_type = queried_type;
2103                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2104                 bool private_ok;
2105                 bool always_ok_flag = false;
2106                 bool skip_iface_check = true, used_cache = false;
2107
2108                 closure_name = name;
2109                 closure_invocation_type = invocation_type;
2110                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2111                 closure_start_type = queried_type;
2112
2113                 //
2114                 // If we are a nested class, we always have access to our container
2115                 // type names
2116                 //
2117                 if (invocation_type != null){
2118                         string invocation_name = invocation_type.FullName;
2119                         if (invocation_name.IndexOf ('+') != -1){
2120                                 string container = queried_type.FullName + "+";
2121                                 int container_length = container.Length;
2122                                 
2123                                 if (invocation_name.Length > container_length){
2124                                         string shared = invocation_name.Substring (0, container_length);
2125                                 
2126                                         if (shared == container)
2127                                                 always_ok_flag = true;
2128                                 }
2129                         }
2130                 }
2131                 
2132                 do {
2133                         MemberList list;
2134
2135                         //
2136                         // `NonPublic' is lame, because it includes both protected and
2137                         // private methods, so we need to control this behavior by
2138                         // explicitly tracking if a private method is ok or not.
2139                         //
2140                         // The possible cases are:
2141                         //    public, private and protected (internal does not come into the
2142                         //    equation)
2143                         //
2144                         if (invocation_type != null){
2145                                 if (invocation_type == current_type){
2146                                         private_ok = (bf & BindingFlags.NonPublic) != 0;
2147                                 } else
2148                                         private_ok = always_ok_flag;
2149
2150                                 if (private_ok || invocation_type.IsSubclassOf (current_type))
2151                                         bf = original_bf | BindingFlags.NonPublic;
2152                         } else {
2153                                 private_ok = false;
2154                                 bf = original_bf & ~BindingFlags.NonPublic;
2155                         }
2156
2157                         closure_private_ok = private_ok;
2158                         closure_queried_type = current_type;
2159
2160                         Timer.StopTimer (TimerType.MemberLookup);
2161
2162                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2163
2164                         Timer.StartTimer (TimerType.MemberLookup);
2165
2166                         //
2167                         // When queried for an interface type, the cache will automatically check all
2168                         // inherited members, so we don't need to do this here.  However, this only
2169                         // works if we already used the cache in the first iteration of this loop.
2170                         //
2171                         // If we used the cache in any further iteration, we can still terminate the
2172                         // loop since the cache always looks in all parent classes.
2173                         //
2174
2175                         if (used_cache)
2176                                 searching = false;
2177                         else
2178                                 skip_iface_check = false;
2179
2180                         if (current_type == TypeManager.object_type)
2181                                 searching = false;
2182                         else {
2183                                 current_type = current_type.BaseType;
2184                                 
2185                                 //
2186                                 // This happens with interfaces, they have a null
2187                                 // basetype.  Look members up in the Object class.
2188                                 //
2189                                 if (current_type == null)
2190                                         current_type = TypeManager.object_type;
2191                         }
2192                         
2193                         if (list.Count == 0)
2194                                 continue;
2195                         
2196                         //
2197                         // Events and types are returned by both `static' and `instance'
2198                         // searches, which means that our above FindMembers will
2199                         // return two copies of the same.
2200                         //
2201                         if (list.Count == 1 && !(list [0] is MethodBase)){
2202                                 return (MemberInfo []) list;
2203                         }
2204
2205                         //
2206                         // Multiple properties: we query those just to find out the indexer
2207                         // name
2208                         //
2209                         if (list [0] is PropertyInfo)
2210                                 return (MemberInfo []) list;
2211
2212                         //
2213                         // We found methods, turn the search into "method scan"
2214                         // mode.
2215                         //
2216                         
2217                         method_list = CopyNewMethods (method_list, list);
2218                         mt &= (MemberTypes.Method | MemberTypes.Constructor);
2219                 } while (searching);
2220
2221                 if (method_list != null && method_list.Count > 0)
2222                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2223
2224                 //
2225                 // This happens if we already used the cache in the first iteration, in this case
2226                 // the cache already looked in all interfaces.
2227                 //
2228                 if (skip_iface_check)
2229                         return null;
2230
2231                 //
2232                 // Interfaces do not list members they inherit, so we have to
2233                 // scan those.
2234                 // 
2235                 if (!queried_type.IsInterface)
2236                         return null;
2237
2238                 if (queried_type.IsArray)
2239                         queried_type = TypeManager.array_type;
2240                 
2241                 Type [] ifaces = GetInterfaces (queried_type);
2242                 if (ifaces == null)
2243                         return null;
2244                 
2245                 foreach (Type itype in ifaces){
2246                         MemberInfo [] x;
2247
2248                         x = MemberLookup (null, itype, mt, bf, name);
2249                         if (x != null)
2250                                 return x;
2251                 }
2252                                         
2253                 return null;
2254         }
2255 #endregion
2256         
2257 }
2258
2259 /// <summary>
2260 ///   There is exactly one instance of this class per type.
2261 /// </summary>
2262 public sealed class TypeHandle : IMemberContainer {
2263         public readonly TypeHandle BaseType;
2264
2265         readonly int id = ++next_id;
2266         static int next_id = 0;
2267
2268         /// <summary>
2269         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2270         ///   a TypeHandle yet, a new instance of it is created.  This static method
2271         ///   ensures that we'll only have one TypeHandle instance per type.
2272         /// </summary>
2273         public static TypeHandle GetTypeHandle (Type t)
2274         {
2275                 TypeHandle handle = (TypeHandle) type_hash [t];
2276                 if (handle != null)
2277                         return handle;
2278
2279                 handle = new TypeHandle (t);
2280                 type_hash.Add (t, handle);
2281                 return handle;
2282         }
2283
2284         /// <summary>
2285         ///   Returns the TypeHandle for TypeManager.object_type.
2286         /// </summary>
2287         public static IMemberContainer ObjectType {
2288                 get {
2289                         if (object_type != null)
2290                                 return object_type;
2291
2292                         object_type = GetTypeHandle (TypeManager.object_type);
2293
2294                         return object_type;
2295                 }
2296         }
2297
2298         /// <summary>
2299         ///   Returns the TypeHandle for TypeManager.array_type.
2300         /// </summary>
2301         public static IMemberContainer ArrayType {
2302                 get {
2303                         if (array_type != null)
2304                                 return array_type;
2305
2306                         array_type = GetTypeHandle (TypeManager.array_type);
2307
2308                         return array_type;
2309                 }
2310         }
2311
2312         private static PtrHashtable type_hash = new PtrHashtable ();
2313
2314         private static TypeHandle object_type = null;
2315         private static TypeHandle array_type = null;
2316
2317         private Type type;
2318         private bool is_interface;
2319         private MemberCache member_cache;
2320
2321         private TypeHandle (Type type)
2322         {
2323                 this.type = type;
2324                 if (type.BaseType != null)
2325                         BaseType = GetTypeHandle (type.BaseType);
2326                 else if ((type != TypeManager.object_type) && (type != typeof (object)))
2327                         is_interface = true;
2328                 this.member_cache = new MemberCache (this);
2329         }
2330
2331         // IMemberContainer methods
2332
2333         public string Name {
2334                 get {
2335                         return type.FullName;
2336                 }
2337         }
2338
2339         public Type Type {
2340                 get {
2341                         return type;
2342                 }
2343         }
2344
2345         public IMemberContainer Parent {
2346                 get {
2347                         return BaseType;
2348                 }
2349         }
2350
2351         public bool IsInterface {
2352                 get {
2353                         return is_interface;
2354                 }
2355         }
2356
2357         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2358         {
2359                 if (mt == MemberTypes.Event)
2360                         return new MemberList (type.GetEvents (bf | BindingFlags.DeclaredOnly));
2361                 else
2362                         return new MemberList (type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
2363                                                                  null, null));
2364         }
2365
2366         // IMemberFinder methods
2367
2368         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2369                                        MemberFilter filter, object criteria)
2370         {
2371                 return member_cache.FindMembers (mt, bf, name, filter, criteria);
2372         }
2373
2374         public MemberCache MemberCache {
2375                 get {
2376                         return member_cache;
2377                 }
2378         }
2379
2380         public override string ToString ()
2381         {
2382                 if (BaseType != null)
2383                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2384                 else
2385                         return "TypeHandle (" + id + "," + Name + ")";
2386         }
2387 }
2388
2389 }