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