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