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