2002-06-15 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / mbas / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 //
11 //
12 #define CACHE
13
14 using System;
15 using System.Globalization;
16 using System.Collections;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Text.RegularExpressions;
20 using System.Runtime.CompilerServices;
21
22 namespace Mono.CSharp {
23
24 public class TypeManager {
25         //
26         // A list of core types that the compiler requires or uses
27         //
28         static public Type object_type;
29         static public Type value_type;
30         static public Type string_type;
31         static public Type int32_type;
32         static public Type uint32_type;
33         static public Type int64_type;
34         static public Type uint64_type;
35         static public Type float_type;
36         static public Type double_type;
37         static public Type char_type;
38         static public Type char_ptr_type;
39         static public Type short_type;
40         static public Type decimal_type;
41         static public Type bool_type;
42         static public Type sbyte_type;
43         static public Type byte_type;
44         static public Type ushort_type;
45         static public Type enum_type;
46         static public Type delegate_type;
47         static public Type multicast_delegate_type;
48         static public Type void_type;
49         static public Type enumeration_type;
50         static public Type array_type;
51         static public Type runtime_handle_type;
52         static public Type icloneable_type;
53         static public Type type_type;
54         static public Type ienumerator_type;
55         static public Type idisposable_type;
56         static public Type default_member_type;
57         static public Type iasyncresult_type;
58         static public Type asynccallback_type;
59         static public Type intptr_type;
60         static public Type monitor_type;
61         static public Type runtime_field_handle_type;
62         static public Type attribute_type;
63         static public Type attribute_usage_type;
64         static public Type dllimport_type;
65         static public Type unverifiable_code_type;
66         static public Type methodimpl_attr_type;
67         static public Type marshal_as_attr_type;
68         static public Type param_array_type;
69         static public Type void_ptr_type;
70         static public Type indexer_name_type;
71         static public Type trace_type;
72         static public Type debug_type;
73         
74         static public Type [] NoTypes;
75         
76         //
77         // Internal, not really used outside
78         //
79         static Type runtime_helpers_type;
80         
81         //
82         // These methods are called by code generated by the compiler
83         //
84         static public MethodInfo string_concat_string_string;
85         static public MethodInfo string_concat_object_object;
86         static public MethodInfo string_isinterneted_string;
87         static public MethodInfo system_type_get_type_from_handle;
88         static public MethodInfo object_getcurrent_void;
89         static public MethodInfo bool_movenext_void;
90         static public MethodInfo void_dispose_void;
91         static public MethodInfo void_monitor_enter_object;
92         static public MethodInfo void_monitor_exit_object;
93         static public MethodInfo void_initializearray_array_fieldhandle;
94         static public MethodInfo int_getlength_int;
95         static public MethodInfo delegate_combine_delegate_delegate;
96         static public MethodInfo delegate_remove_delegate_delegate;
97         static public MethodInfo int_get_offset_to_string_data;
98         static public MethodInfo int_array_get_length;
99         
100         //
101         // The attribute constructors.
102         //
103         static public ConstructorInfo cons_param_array_attribute;
104         static public ConstructorInfo void_decimal_ctor_five_args;
105         
106         // <remarks>
107         //   Holds the Array of Assemblies that have been loaded
108         //   (either because it is the default or the user used the
109         //   -r command line option)
110         // </remarks>
111         static Assembly [] assemblies;
112
113         // <remarks>
114         //  Keeps a list of module builders. We used this to do lookups
115         //  on the modulebuilder using GetType -- needed for arrays
116         // </remarks>
117         static ModuleBuilder [] modules;
118
119         // <remarks>
120         //   This is the type_cache from the assemblies to avoid
121         //   hitting System.Reflection on every lookup.
122         // </summary>
123         static Hashtable types;
124
125         // <remarks>
126         //  This is used to hotld the corresponding TypeContainer objects
127         //  since we need this in FindMembers
128         // </remarks>
129         static Hashtable typecontainers;
130
131         // <remarks>
132         //   Keeps track of those types that are defined by the
133         //   user's program
134         // </remarks>
135         static ArrayList user_types;
136
137         // <remarks>
138         //   Keeps a mapping between TypeBuilders and their TypeContainers
139         // </remarks>
140         static PtrHashtable builder_to_container;
141
142         // <remarks>
143         //   Tracks the interfaces implemented by typebuilders.  We only
144         //   enter those who do implement or or more interfaces
145         // </remarks>
146         static PtrHashtable builder_to_ifaces;
147
148         // <remarks>
149         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
150         //   the arguments to the method
151         // </remarks>
152         static Hashtable method_arguments;
153
154         // <remarks>
155         //   Maybe `method_arguments' should be replaced and only
156         //   method_internal_params should be kept?
157         // <remarks>
158         static Hashtable method_internal_params;
159
160         static PtrHashtable builder_to_interface;
161
162         // <remarks>
163         //  Keeps track of delegate types
164         // </remarks>
165
166         static Hashtable builder_to_delegate;
167
168         // <remarks>
169         //  Keeps track of enum types
170         // </remarks>
171
172         static Hashtable builder_to_enum;
173
174         // <remarks>
175         //  Keeps track of attribute types
176         // </remarks>
177
178         static Hashtable builder_to_attr;
179
180         struct Signature {
181                 public string name;
182                 public Type [] args;
183         }
184
185         /// <summary>
186         ///   A filter for Findmembers that uses the Signature object to
187         ///   extract objects
188         /// </summary>
189         static bool SignatureFilter (MemberInfo mi, object criteria)
190         {
191                 Signature sig = (Signature) criteria;
192
193                 if (!(mi is MethodBase))
194                         return false;
195                 
196                 if (mi.Name != sig.name)
197                         return false;
198
199                 int count = sig.args.Length;
200                 
201                 if (mi is MethodBuilder || mi is ConstructorBuilder){
202                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
203
204                         if (candidate_args.Length != count)
205                                 return false;
206                         
207                         for (int i = 0; i < count; i++)
208                                 if (candidate_args [i] != sig.args [i])
209                                         return false;
210                         
211                         return true;
212                 } else {
213                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
214
215                         if (pars.Length != count)
216                                 return false;
217
218                         for (int i = 0; i < count; i++)
219                                 if (pars [i].ParameterType != sig.args [i])
220                                         return false;
221                         return true;
222                 }
223         }
224
225         // A delegate that points to the filter above.
226         static MemberFilter signature_filter;
227
228         static TypeManager ()
229         {
230                 assemblies = new Assembly [0];
231                 modules = null;
232                 user_types = new ArrayList ();
233                 
234                 types = new Hashtable ();
235                 typecontainers = new Hashtable ();
236                 
237                 builder_to_interface = new PtrHashtable ();
238                 builder_to_delegate = new PtrHashtable ();
239                 builder_to_enum  = new PtrHashtable ();
240                 builder_to_attr = new PtrHashtable ();
241                 method_arguments = new PtrHashtable ();
242                 method_internal_params = new PtrHashtable ();
243                 builder_to_container = new PtrHashtable ();
244                 builder_to_ifaces = new PtrHashtable ();
245                 
246                 NoTypes = new Type [0];
247
248                 signature_filter = new MemberFilter (SignatureFilter);
249         }
250
251         public static void AddUserType (string name, TypeBuilder t, Type [] ifaces)
252         {
253                 try {
254                         types.Add (name, t);
255                 } catch {
256                         Type prev = (Type) types [name];
257                         TypeContainer tc = (TypeContainer) builder_to_container [prev];
258
259                         if (tc != null){
260                                 //
261                                 // This probably never happens, as we catch this before
262                                 //
263                                 Report.Error (-17, "The type `" + name + "' has already been defined.");
264                                 return;
265                         }
266
267                         tc = (TypeContainer) builder_to_container [t];
268                         
269                         Report.Warning (
270                                 1595, "The type `" + name + "' is defined in an existing assembly;"+
271                                 " Using the new definition from: " + tc.Location);
272                         Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
273                         
274                         types.Remove (name);
275                         types.Add (name, t);
276                 }
277                 user_types.Add (t);
278                         
279                 if (ifaces != null)
280                         builder_to_ifaces [t] = ifaces;
281         }
282
283         //
284         // This entry point is used by types that we define under the covers
285         // 
286         public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces)
287         {
288                 if (ifaces != null)
289                         builder_to_ifaces [tb] = ifaces;
290         }
291         
292         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
293         {
294                 builder_to_container.Add (t, tc);
295                 typecontainers.Add (name, tc);
296                 AddUserType (name, t, ifaces);
297         }
298
299         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
300         {
301                 types.Add (name, t);
302                 builder_to_delegate.Add (t, del);
303         }
304         
305         public static void AddEnumType (string name, TypeBuilder t, Enum en)
306         {
307                 types.Add (name, t);
308                 builder_to_enum.Add (t, en);
309         }
310
311         public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
312         {
313                 AddUserType (name, t, ifaces);
314                 builder_to_interface.Add (t, i);
315         }
316
317         public static void RegisterAttrType (Type t, TypeContainer tc)
318         {
319                 builder_to_attr.Add (t, tc);
320         }
321                 
322         /// <summary>
323         ///   Returns the TypeContainer whose Type is `t' or null if there is no
324         ///   TypeContainer for `t' (ie, the Type comes from a library)
325         /// </summary>
326         public static TypeContainer LookupTypeContainer (Type t)
327         {
328                 return (TypeContainer) builder_to_container [t];
329         }
330
331         public static Interface LookupInterface (Type t)
332         {
333                 return (Interface) builder_to_interface [t];
334         }
335
336         public static Delegate LookupDelegate (Type t)
337         {
338                 return (Delegate) builder_to_delegate [t];
339         }
340
341         public static Enum LookupEnum (Type t)
342         {
343                 return (Enum) builder_to_enum [t];
344         }
345         
346         public static TypeContainer LookupAttr (Type t)
347         {
348                 return (TypeContainer) builder_to_attr [t];
349         }
350         
351         /// <summary>
352         ///   Registers an assembly to load types from.
353         /// </summary>
354         public static void AddAssembly (Assembly a)
355         {
356                 int top = assemblies.Length;
357                 Assembly [] n = new Assembly [top + 1];
358
359                 assemblies.CopyTo (n, 0);
360                 
361                 n [top] = a;
362                 assemblies = n;
363         }
364
365         /// <summary>
366         ///  Registers a module builder to lookup types from
367         /// </summary>
368         public static void AddModule (ModuleBuilder mb)
369         {
370                 int top = modules != null ? modules.Length : 0;
371                 ModuleBuilder [] n = new ModuleBuilder [top + 1];
372
373                 if (modules != null)
374                         modules.CopyTo (n, 0);
375                 n [top] = mb;
376                 modules = n;
377         }
378
379         /// <summary>
380         ///   Returns the Type associated with @name
381         /// </summary>
382         public static Type LookupType (string name)
383         {
384                 Type t;
385
386                 //
387                 // First lookup in user defined and cached values
388                 //
389
390                 t = (Type) types [name];
391                 if (t != null)
392                         return t;
393
394                 foreach (Assembly a in assemblies){
395                         t = a.GetType (name);
396                         if (t != null){
397                                 types [name] = t;
398
399                                 return t;
400                         }
401                 }
402
403                 foreach (ModuleBuilder mb in modules) {
404                         t = mb.GetType (name);
405                         if (t != null) {
406                                 types [name] = t;
407                                 return t;
408                         }
409                 }
410                 
411                 return null;
412         }
413
414         /// <summary>
415         ///   Returns the C# name of a type if possible, or the full type name otherwise
416         /// </summary>
417         static public string CSharpName (Type t)
418         {
419                 return Regex.Replace (t.FullName, 
420                         @"^System\." +
421                         @"(Int32|UInt32|Int16|Uint16|Int64|UInt64|" +
422                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
423                         @"Boolean|String|Void)" +
424                         @"(\W+|\b)", 
425                         new MatchEvaluator (CSharpNameMatch));
426         }       
427         
428         static String CSharpNameMatch (Match match) 
429         {
430                 string s = match.Groups [1].Captures [0].Value;
431                 return s.ToLower ().
432                 Replace ("int32", "int").
433                 Replace ("uint32", "uint").
434                 Replace ("int16", "short").
435                 Replace ("uint16", "ushort").
436                 Replace ("int64", "long").
437                 Replace ("uint64", "ulong").
438                 Replace ("single", "float").
439                 Replace ("boolean", "bool")
440                 + match.Groups [2].Captures [0].Value;
441         }
442
443         /// <summary>
444         ///   Returns the signature of the method
445         /// </summary>
446         static public string CSharpSignature (MethodBase mb)
447         {
448                 string sig = "(";
449
450                 //
451                 // FIXME: We should really have a single function to do
452                 // everything instead of the following 5 line pattern
453                 //
454                 ParameterData iparams = LookupParametersByBuilder (mb);
455
456                 if (iparams == null){
457                         ParameterInfo [] pi = mb.GetParameters ();
458                         iparams = new ReflectionParameters (pi);
459                 }
460                 
461                 for (int i = 0; i < iparams.Count; i++) {
462                         if (i > 0) {
463                                 sig += ", ";
464                         }
465                         sig += iparams.ParameterDesc(i);
466                 }
467                 sig += ")";
468
469                 return mb.DeclaringType.Name + "." + mb.Name + sig;
470         }
471
472         /// <summary>
473         ///   Looks up a type, and aborts if it is not found.  This is used
474         ///   by types required by the compiler
475         /// </summary>
476         static Type CoreLookupType (string name)
477         {
478                 Type t = LookupType (name);
479
480                 if (t == null){
481                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
482                         Environment.Exit (0);
483                 }
484
485                 return t;
486         }
487
488         /// <summary>
489         ///   Returns the MethodInfo for a method named `name' defined
490         ///   in type `t' which takes arguments of types `args'
491         /// </summary>
492         static MethodInfo GetMethod (Type t, string name, Type [] args)
493         {
494                 MemberInfo [] mi;
495                 Signature sig;
496
497                 sig.name = name;
498                 sig.args = args;
499                 
500                 mi = FindMembers (
501                         t, MemberTypes.Method,
502                         instance_and_static | BindingFlags.Public, signature_filter, sig);
503                 if (mi == null || mi.Length == 0 || !(mi [0] is MethodInfo)){
504                         Report.Error (-19, "Can not find the core function `" + name + "'");
505                         return null;
506                 }
507
508                 return (MethodInfo) mi [0];
509         }
510
511         /// <summary>
512         ///    Returns the ConstructorInfo for "args"
513         /// </summary>
514         static ConstructorInfo GetConstructor (Type t, Type [] args)
515         {
516                 MemberInfo [] mi;
517                 Signature sig;
518
519                 sig.name = ".ctor";
520                 sig.args = args;
521                 
522                 mi = FindMembers (t, MemberTypes.Constructor,
523                                   instance_and_static | BindingFlags.Public, signature_filter, sig);
524                 if (mi == null || mi.Length == 0 || !(mi [0] is ConstructorInfo)){
525                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
526                         return null;
527                 }
528
529                 return (ConstructorInfo) mi [0];
530         }
531
532         public static void InitEnumUnderlyingTypes ()
533         {
534
535                 int32_type    = CoreLookupType ("System.Int32");
536                 int64_type    = CoreLookupType ("System.Int64");
537                 uint32_type   = CoreLookupType ("System.UInt32"); 
538                 uint64_type   = CoreLookupType ("System.UInt64"); 
539                 byte_type     = CoreLookupType ("System.Byte");
540                 sbyte_type    = CoreLookupType ("System.SByte");
541                 short_type    = CoreLookupType ("System.Int16");
542                 ushort_type   = CoreLookupType ("System.UInt16");
543         }
544         
545         /// <remarks>
546         ///   The types have to be initialized after the initial
547         ///   population of the type has happened (for example, to
548         ///   bootstrap the corlib.dll
549         /// </remarks>
550         public static void InitCoreTypes ()
551         {
552                 object_type   = CoreLookupType ("System.Object");
553                 value_type    = CoreLookupType ("System.ValueType");
554
555                 InitEnumUnderlyingTypes ();
556
557                 char_type     = CoreLookupType ("System.Char");
558                 string_type   = CoreLookupType ("System.String");
559                 float_type    = CoreLookupType ("System.Single");
560                 double_type   = CoreLookupType ("System.Double");
561                 char_ptr_type = CoreLookupType ("System.Char*");
562                 decimal_type  = CoreLookupType ("System.Decimal");
563                 bool_type     = CoreLookupType ("System.Boolean");
564                 enum_type     = CoreLookupType ("System.Enum");
565
566                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
567                 delegate_type           = CoreLookupType ("System.Delegate");
568
569                 array_type    = CoreLookupType ("System.Array");
570                 void_type     = CoreLookupType ("System.Void");
571                 type_type     = CoreLookupType ("System.Type");
572
573                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
574                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
575                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
576                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
577                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
578                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
579                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
580                 idisposable_type     = CoreLookupType ("System.IDisposable");
581                 icloneable_type      = CoreLookupType ("System.ICloneable");
582                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
583                 intptr_type          = CoreLookupType ("System.IntPtr");
584
585                 attribute_type       = CoreLookupType ("System.Attribute");
586                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
587                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
588                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
589                 marshal_as_attr_type  = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
590                 param_array_type      = CoreLookupType ("System.ParamArrayAttribute");
591
592                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
593
594                 void_ptr_type         = CoreLookupType ("System.Void*");
595
596                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
597                 if (RootContext.StdLib) {
598                         trace_type    = CoreLookupType ("System.Diagnostics.Trace");
599                         debug_type    = CoreLookupType ("System.Diagnostics.Debug");
600                 }
601         }
602
603         //
604         // The helper methods that are used by the compiler
605         //
606         public static void InitCodeHelpers ()
607         {
608                 //
609                 // Now load the default methods that we use.
610                 //
611                 Type [] string_string = { string_type, string_type };
612                 string_concat_string_string = GetMethod (
613                         string_type, "Concat", string_string);
614
615                 Type [] object_object = { object_type, object_type };
616                 string_concat_object_object = GetMethod (
617                         string_type, "Concat", object_object);
618
619                 Type [] string_ = { string_type };
620                 string_isinterneted_string = GetMethod (
621                         string_type, "IsInterned", string_);
622                 
623                 Type [] runtime_type_handle = { runtime_handle_type };
624                 system_type_get_type_from_handle = GetMethod (
625                         type_type, "GetTypeFromHandle", runtime_type_handle);
626
627                 Type [] delegate_delegate = { delegate_type, delegate_type };
628                 delegate_combine_delegate_delegate = GetMethod (
629                                 delegate_type, "Combine", delegate_delegate);
630
631                 delegate_remove_delegate_delegate = GetMethod (
632                                 delegate_type, "Remove", delegate_delegate);
633
634                 //
635                 // Void arguments
636                 //
637                 Type [] void_arg = {  };
638                 object_getcurrent_void = GetMethod (
639                         ienumerator_type, "get_Current", void_arg);
640                 bool_movenext_void = GetMethod (
641                         ienumerator_type, "MoveNext", void_arg);
642                 void_dispose_void = GetMethod (
643                         idisposable_type, "Dispose", void_arg);
644                 int_get_offset_to_string_data = GetMethod (
645                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
646                 int_array_get_length = GetMethod (
647                         array_type, "get_Length", void_arg);
648                 
649                 //
650                 // object arguments
651                 //
652                 Type [] object_arg = { object_type };
653                 void_monitor_enter_object = GetMethod (
654                         monitor_type, "Enter", object_arg);
655                 void_monitor_exit_object = GetMethod (
656                         monitor_type, "Exit", object_arg);
657
658                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
659                 
660                 void_initializearray_array_fieldhandle = GetMethod (
661                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
662
663                 //
664                 // Array functions
665                 //
666                 Type [] int_arg = { int32_type };
667                 int_getlength_int = GetMethod (
668                         array_type, "GetLength", int_arg);
669
670                 //
671                 // Decimal constructors
672                 //
673                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
674                 void_decimal_ctor_five_args = GetConstructor (
675                         decimal_type, dec_arg);
676                 
677                 //
678                 // Attributes
679                 //
680                 cons_param_array_attribute = GetConstructor (
681                         param_array_type, void_arg);
682                 
683         }
684
685         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
686
687         //
688         // FIXME: This can be optimized easily.  speedup by having a single builder mapping
689         //
690         public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
691                                                  MemberFilter filter, object criteria)
692         {
693                 //
694                 // We have to take care of arrays specially, because GetType on
695                 // a TypeBuilder array will return a Type, not a TypeBuilder,
696                 // and we can not call FindMembers on this type.
697                 //
698                 if (t.IsSubclassOf (TypeManager.array_type))
699                         return TypeManager.array_type.FindMembers (mt, bf, filter, criteria);
700                 
701                 if (!(t is TypeBuilder)){
702                         //
703                         // Since FindMembers will not lookup both static and instance
704                         // members, we emulate this behaviour here.
705                         //
706                         if ((bf & instance_and_static) == instance_and_static){
707                                 MemberInfo [] i_members = t.FindMembers (
708                                         mt, bf & ~BindingFlags.Static, filter, criteria);
709
710                                 int i_len = i_members.Length;
711                                 if (i_len == 1){
712                                         MemberInfo one = i_members [0];
713
714                                         //
715                                         // If any of these are present, we are done!
716                                         //
717                                         if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
718                                                 return i_members;
719                                 }
720                                 
721                                 MemberInfo [] s_members = t.FindMembers (
722                                         mt, bf & ~BindingFlags.Instance, filter, criteria);
723
724                                 int s_len = s_members.Length;
725                                 if (i_len > 0 || s_len > 0){
726                                         MemberInfo [] both = new MemberInfo [i_len + s_len];
727
728                                         i_members.CopyTo (both, 0);
729                                         s_members.CopyTo (both, i_len);
730
731                                         return both;
732                                 } else {
733                                         if (i_len > 0)
734                                                 return i_members;
735                                         else
736                                                 return s_members;
737                                 }
738                         }
739                         return t.FindMembers (mt, bf, filter, criteria);
740                 }
741
742                 //
743                 // FIXME: We should not have builder_to_blah everywhere,
744                 // we should just have a builder_to_findmemberizable
745                 // and have them implement a new ICanFindMembers interface
746                 //
747                 Enum e = (Enum) builder_to_enum [t];
748
749                 if (e != null)
750                         return e.FindMembers (mt, bf, filter, criteria);
751                 
752                 Delegate del = (Delegate) builder_to_delegate [t];
753
754                 if (del != null)
755                         return del.FindMembers (mt, bf, filter, criteria);
756
757                 Interface iface = (Interface) builder_to_interface [t];
758
759                 if (iface != null) 
760                         return iface.FindMembers (mt, bf, filter, criteria);
761                 
762                 TypeContainer tc = (TypeContainer) builder_to_container [t];
763
764                 if (tc != null)
765                         return tc.FindMembers (mt, bf, filter, criteria);
766
767                 return null;
768         }
769
770         public static bool IsBuiltinType (Type t)
771         {
772                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
773                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
774                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
775                     t == sbyte_type || t == byte_type || t == ushort_type)
776                         return true;
777                 else
778                         return false;
779         }
780
781         public static bool IsDelegateType (Type t)
782         {
783                 if (t.IsSubclassOf (TypeManager.delegate_type))
784                         return true;
785                 else
786                         return false;
787         }
788         
789         public static bool IsEnumType (Type t)
790         {
791                 if (t.IsSubclassOf (TypeManager.enum_type))
792                         return true;
793                 else
794                         return false;
795         }
796         
797         public static bool IsInterfaceType (Type t)
798         {
799                 Interface iface = (Interface) builder_to_interface [t];
800
801                 if (iface != null)
802                         return true;
803                 else
804                         return false;
805         }
806
807         /// <summary>
808         ///   Returns the User Defined Types
809         /// </summary>
810         public static ArrayList UserTypes {
811                 get {
812                         return user_types;
813                 }
814         }
815
816         public static Hashtable TypeContainers {
817                 get {
818                         return typecontainers;
819                 }
820         }
821
822         static Hashtable builder_to_constant;
823
824         public static void RegisterConstant (FieldBuilder fb, Const c)
825         {
826                 if (builder_to_constant == null)
827                         builder_to_constant = new PtrHashtable ();
828
829                 if (builder_to_constant.Contains (fb))
830                         return;
831
832                 builder_to_constant.Add (fb, c);
833         }
834
835         public static Const LookupConstant (FieldBuilder fb)
836         {
837                 if (builder_to_constant == null)
838                         return null;
839                 
840                 return (Const) builder_to_constant [fb];
841         }
842         
843         /// <summary>
844         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
845         /// </summary>
846         ///
847         /// <remarks>
848         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
849         ///   for anything which is dynamic, and we need this in a number of places,
850         ///   we register this information here, and use it afterwards.
851         /// </remarks>
852         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
853         {
854                 if (args == null)
855                         args = NoTypes;
856                                 
857                 method_arguments.Add (mb, args);
858                 method_internal_params.Add (mb, ip);
859                 
860                 return true;
861         }
862         
863         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
864         {
865                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
866                         return null;
867                 
868                 if (method_internal_params.Contains (mb))
869                         return (InternalParameters) method_internal_params [mb];
870                 else
871                         throw new Exception ("Argument for Method not registered" + mb);
872         }
873
874         /// <summary>
875         ///    Returns the argument types for a method based on its methodbase
876         ///
877         ///    For dynamic methods, we use the compiler provided types, for
878         ///    methods from existing assemblies we load them from GetParameters,
879         ///    and insert them into the cache
880         /// </summary>
881         static public Type [] GetArgumentTypes (MethodBase mb)
882         {
883                 if (method_arguments.Contains (mb))
884                         return (Type []) method_arguments [mb];
885                 else {
886                         ParameterInfo [] pi = mb.GetParameters ();
887                         int c = pi.Length;
888                         Type [] types = new Type [c];
889                         
890                         for (int i = 0; i < c; i++)
891                                 types [i] = pi [i].ParameterType;
892
893                         method_arguments.Add (mb, types);
894                         return types;
895                 }
896         }
897         
898         // <remarks>
899         //  This is a workaround the fact that GetValue is not
900         //  supported for dynamic types
901         // </remarks>
902         static Hashtable fields = new Hashtable ();
903         static public bool RegisterFieldValue (FieldBuilder fb, object value)
904         {
905                 if (fields.Contains (fb))
906                         return false;
907
908                 fields.Add (fb, value);
909
910                 return true;
911         }
912
913         static public object GetValue (FieldBuilder fb)
914         {
915                 return fields [fb];
916         }
917
918         static Hashtable fieldbuilders_to_fields = new Hashtable ();
919         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
920         {
921                 if (fieldbuilders_to_fields.Contains (fb))
922                         return false;
923
924                 fieldbuilders_to_fields.Add (fb, f);
925                 return true;
926         }
927
928         static public FieldBase GetField (FieldInfo fb)
929         {
930                 return (FieldBase) fieldbuilders_to_fields [fb];
931         }
932         
933         static Hashtable events;
934
935         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
936         {
937                 if (events == null)
938                         events = new Hashtable ();
939
940                 if (events.Contains (eb))
941                         return false;
942
943                 events.Add (eb, new Pair (add, remove));
944
945                 return true;
946         }
947
948         static public MethodInfo GetAddMethod (EventInfo ei)
949         {
950                 if (ei is MyEventBuilder) {
951                         Pair pair = (Pair) events [ei];
952
953                         return (MethodInfo) pair.First;
954                 } else
955                         return ei.GetAddMethod ();
956         }
957
958         static public MethodInfo GetRemoveMethod (EventInfo ei)
959         {
960                 if (ei is MyEventBuilder) {
961                         Pair pair = (Pair) events [ei];
962
963                         return (MethodInfo) pair.Second;
964                 } else
965                         return ei.GetAddMethod ();
966         }
967
968         static Hashtable properties;
969         
970         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
971         {
972                 if (properties == null)
973                         properties = new Hashtable ();
974
975                 if (properties.Contains (pb))
976                         return false;
977
978                 properties.Add (pb, new Pair (get, set));
979
980                 return true;
981         }
982         
983         //
984         // FIXME: we need to return the accessors depending on whether
985         // they are visible or not.
986         //
987         static public MethodInfo [] GetAccessors (PropertyInfo pi)
988         {
989                 MethodInfo [] ret;
990
991                 if (pi is PropertyBuilder){
992                         Pair pair = (Pair) properties [pi];
993
994                         ret = new MethodInfo [2];
995                         ret [0] = (MethodInfo) pair.First;
996                         ret [1] = (MethodInfo) pair.Second;
997
998                         return ret;
999                 } else {
1000                         MethodInfo [] mi = new MethodInfo [2];
1001
1002                         //
1003                         // Why this and not pi.GetAccessors?
1004                         // Because sometimes index 0 is the getter
1005                         // sometimes it is 1
1006                         //
1007                         mi [0] = pi.GetGetMethod (true);
1008                         mi [1] = pi.GetSetMethod (true);
1009
1010                         return mi;
1011                 }
1012         }
1013
1014         static public MethodInfo GetPropertyGetter (PropertyInfo pi)
1015         {
1016                 if (pi is PropertyBuilder){
1017                         Pair de = (Pair) properties [pi];
1018
1019                         return (MethodInfo) de.Second;
1020                 } else
1021                         return pi.GetSetMethod ();
1022         }
1023
1024         static public MethodInfo GetPropertySetter (PropertyInfo pi)
1025         {
1026                 if (pi is PropertyBuilder){
1027                         Pair de = (Pair) properties [pi];
1028
1029                         return (MethodInfo) de.First;
1030                 } else
1031                         return pi.GetGetMethod ();
1032         }
1033
1034         /// <summary>
1035         ///   This function returns the interfaces in the type `t'.  Works with
1036         ///   both types and TypeBuilders.
1037         /// </summary>
1038         public static Type [] GetInterfaces (Type t)
1039         {
1040                 //
1041                 // The reason for catching the Array case is that Reflection.Emit
1042                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1043                 // but will still throw an exception if we try to call GetInterfaces
1044                 // on the type.
1045                 //
1046                 // Since the array interfaces are always constant, we return those for
1047                 // the System.Array
1048                 //
1049                 
1050                 if (t.IsArray)
1051                         t = TypeManager.array_type;
1052                 
1053                 if (t is TypeBuilder)
1054                         return (Type []) builder_to_ifaces [t];
1055                 else
1056                         return t.GetInterfaces ();
1057         }
1058         
1059         /// <remarks>
1060         ///  The following is used to check if a given type implements an interface.
1061         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1062         /// </remarks>
1063         public static bool ImplementsInterface (Type t, Type iface)
1064         {
1065                 Type [] interfaces;
1066
1067                 //
1068                 // FIXME OPTIMIZATION:
1069                 // as soon as we hit a non-TypeBuiler in the interface
1070                 // chain, we could return, as the `Type.GetInterfaces'
1071                 // will return all the interfaces implement by the type
1072                 // or its parents.
1073                 //
1074                 do {
1075                         interfaces = GetInterfaces (t);
1076
1077                         if (interfaces != null){
1078                                 foreach (Type i in interfaces){
1079                                         if (i == iface)
1080                                                 return true;
1081                                 }
1082                         }
1083                         
1084                         t = t.BaseType;
1085                 } while (t != null);
1086                 
1087                 return false;
1088         }
1089
1090         // This is a custom version of Convert.ChangeType() which works
1091         // with the TypeBuilder defined types when compiling corlib.
1092         public static object ChangeType (object value, Type conversionType)
1093         {
1094                 if (!(value is IConvertible))
1095                         throw new ArgumentException ();
1096
1097                 IConvertible convertValue = (IConvertible) value;
1098                 CultureInfo ci = CultureInfo.CurrentCulture;
1099                 NumberFormatInfo provider = ci.NumberFormat;
1100
1101                 //
1102                 // We must use Type.Equals() here since `conversionType' is
1103                 // the TypeBuilder created version of a system type and not
1104                 // the system type itself.  You cannot use Type.GetTypeCode()
1105                 // on such a type - it'd always return TypeCode.Object.
1106                 //
1107                 if (conversionType.Equals (typeof (Boolean)))
1108                         return (object)(convertValue.ToBoolean (provider));
1109                 else if (conversionType.Equals (typeof (Byte)))
1110                         return (object)(convertValue.ToByte (provider));
1111                 else if (conversionType.Equals (typeof (Char)))
1112                         return (object)(convertValue.ToChar (provider));
1113                 else if (conversionType.Equals (typeof (DateTime)))
1114                         return (object)(convertValue.ToDateTime (provider));
1115                 else if (conversionType.Equals (typeof (Decimal)))
1116                         return (object)(convertValue.ToDecimal (provider));
1117                 else if (conversionType.Equals (typeof (Double)))
1118                         return (object)(convertValue.ToDouble (provider));
1119                 else if (conversionType.Equals (typeof (Int16)))
1120                         return (object)(convertValue.ToInt16 (provider));
1121                 else if (conversionType.Equals (typeof (Int32)))
1122                         return (object)(convertValue.ToInt32 (provider));
1123                 else if (conversionType.Equals (typeof (Int64)))
1124                         return (object)(convertValue.ToInt64 (provider));
1125                 else if (conversionType.Equals (typeof (SByte)))
1126                         return (object)(convertValue.ToSByte (provider));
1127                 else if (conversionType.Equals (typeof (Single)))
1128                         return (object)(convertValue.ToSingle (provider));
1129                 else if (conversionType.Equals (typeof (String)))
1130                         return (object)(convertValue.ToString (provider));
1131                 else if (conversionType.Equals (typeof (UInt16)))
1132                         return (object)(convertValue.ToUInt16 (provider));
1133                 else if (conversionType.Equals (typeof (UInt32)))
1134                         return (object)(convertValue.ToUInt32 (provider));
1135                 else if (conversionType.Equals (typeof (UInt64)))
1136                         return (object)(convertValue.ToUInt64 (provider));
1137                 else if (conversionType.Equals (typeof (Object)))
1138                         return (object)(value);
1139                 else 
1140                         throw new InvalidCastException ();
1141         }
1142
1143         //
1144         // This is needed, because enumerations from assemblies
1145         // do not report their underlyingtype, but they report
1146         // themselves
1147         //
1148         public static Type EnumToUnderlying (Type t)
1149         {
1150                 t = t.UnderlyingSystemType;
1151                 if (!TypeManager.IsEnumType (t))
1152                         return t;
1153                 
1154                 TypeCode tc = Type.GetTypeCode (t);
1155
1156                 switch (tc){
1157                 case TypeCode.Boolean:
1158                         return TypeManager.bool_type;
1159                 case TypeCode.Byte:
1160                         return TypeManager.byte_type;
1161                 case TypeCode.SByte:
1162                         return TypeManager.sbyte_type;
1163                 case TypeCode.Char:
1164                         return TypeManager.char_type;
1165                 case TypeCode.Int16:
1166                         return TypeManager.short_type;
1167                 case TypeCode.UInt16:
1168                         return TypeManager.ushort_type;
1169                 case TypeCode.Int32:
1170                         return TypeManager.int32_type;
1171                 case TypeCode.UInt32:
1172                         return TypeManager.uint32_type;
1173                 case TypeCode.Int64:
1174                         return TypeManager.int64_type;
1175                 case TypeCode.UInt64:
1176                         return TypeManager.uint64_type;
1177                 }
1178                 throw new Exception ("Unhandled typecode in enum" + tc);
1179         }
1180
1181         /// <summary>
1182         ///   Utility function that can be used to probe whether a type
1183         ///   is managed or not.  
1184         /// </summary>
1185         public static bool VerifyUnManaged (Type t, Location loc)
1186         {
1187                 if (t.IsValueType || t.IsPointer){
1188                         //
1189                         // FIXME: this is more complex, we actually need to
1190                         // make sure that the type does not contain any
1191                         // classes itself
1192                         //
1193                         return true;
1194                 }
1195
1196                 Report.Error (
1197                         208, loc,
1198                         "Cannot take the address or size of a variable of a managed type ('" +
1199                         CSharpName (t) + "')");
1200                 return false;   
1201         }
1202         
1203         /// <summary>
1204         ///   Returns the name of the indexer in a given type.
1205         /// </summary>
1206         /// <remarks>
1207         ///   The default is not always `Item'.  The user can change this behaviour by
1208         ///   using the DefaultMemberAttribute in the class.
1209         ///
1210         ///   For example, the String class indexer is named `Chars' not `Item' 
1211         /// </remarks>
1212         public static string IndexerPropertyName (Type t)
1213         {
1214                 
1215                 if (t is TypeBuilder) {
1216                         TypeContainer tc = (TypeContainer) builder_to_container [t];
1217
1218                         //
1219                         // FIXME: Temporary hack, until we deploy the IndexerName
1220                         // property code (and attributes) in the interface code.
1221                         //
1222                         if (tc == null){
1223                                 return "Item";
1224                         }
1225                         
1226                         return tc.IndexerName;
1227                 }
1228                 
1229                 System.Attribute attr = System.Attribute.GetCustomAttribute (
1230                         t, TypeManager.default_member_type);
1231                 if (attr != null){
1232                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
1233                         return dma.MemberName;
1234                 }
1235
1236                 return "Item";
1237         }
1238
1239         public static void MakePinned (LocalBuilder builder)
1240         {
1241                 //
1242                 // FIXME: Flag the "LocalBuilder" type as being
1243                 // pinned.  Figure out API.
1244                 //
1245         }
1246
1247
1248         //
1249         // Returns whether the array of memberinfos contains the given method
1250         //
1251         static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
1252         {
1253                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
1254                 
1255                 foreach (MethodBase method in array){
1256                         if (method.Name != new_method.Name)
1257                                 continue;
1258                         
1259                         Type [] old_args = TypeManager.GetArgumentTypes (method);
1260                         int old_count = old_args.Length;
1261                         int i;
1262                         
1263                         if (new_args.Length != old_count)
1264                                 continue;
1265                         
1266                         for (i = 0; i < old_count; i++){
1267                                 if (old_args [i] != new_args [i])
1268                                         break;
1269                         }
1270                         if (i != old_count)
1271                                 continue;
1272                         
1273                         if (!(method is MethodInfo && new_method is MethodInfo))
1274                                 return true;
1275                         
1276                         if (((MethodInfo) method).ReturnType == ((MethodInfo) new_method).ReturnType)
1277                                 return true;
1278                 }
1279                 return false;
1280         }
1281         
1282         //
1283         // We copy methods from `new_members' into `target_list' if the signature
1284         // for the method from in the new list does not exist in the target_list
1285         //
1286         // The name is assumed to be the same.
1287         //
1288         public static ArrayList CopyNewMethods (ArrayList target_list, MemberInfo [] new_members)
1289         {
1290                 if (target_list == null){
1291                         target_list = new ArrayList ();
1292
1293                         foreach (MemberInfo mi in new_members){
1294                                 if (mi is MethodBase)
1295                                         target_list.Add (mi);
1296                         }
1297                         return target_list;
1298                 }
1299                 
1300                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
1301                 target_list.CopyTo (target_array, 0);
1302                 
1303                 foreach (MemberInfo mi in new_members){
1304                         MethodBase new_method = (MethodBase) mi;
1305                         
1306                         if (!ArrayContainsMethod (target_array, new_method))
1307                                 target_list.Add (new_method);
1308                 }
1309                 return target_list;
1310         }
1311
1312 #region MemberLookup implementation
1313         
1314         //
1315         // Name of the member
1316         //
1317         static string   closure_name;
1318
1319         //
1320         // Whether we allow private members in the result (since FindMembers
1321         // uses NonPublic for both protected and private), we need to distinguish.
1322         //
1323         static bool     closure_private_ok;
1324
1325         //
1326         // Who is invoking us and which type is being queried currently.
1327         //
1328         static Type     closure_invocation_type;
1329         static Type     closure_queried_type;
1330
1331         //
1332         // The assembly that defines the type is that is calling us
1333         //
1334         static Assembly closure_invocation_assembly;
1335
1336         //
1337         // This filter filters by name + whether it is ok to include private
1338         // members in the search
1339         //
1340         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
1341         {
1342                 //
1343                 // Hack: we know that the filter criteria will always be in the `closure'
1344                 // fields. 
1345                 //
1346
1347                 if (m.Name != closure_name)
1348                         return false;
1349
1350                 //
1351                 // Ugly: we need to find out the type of `m', and depending
1352                 // on this, tell whether we accept or not
1353                 //
1354                 if (m is MethodBase){
1355                         MethodBase mb = (MethodBase) m;
1356                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
1357
1358                         if (ma == MethodAttributes.Private)
1359                                 return closure_private_ok;
1360
1361                         //
1362                         // FamAndAssem requires that we not only derivate, but we are on the
1363                         // same assembly.  
1364                         //
1365                         if (ma == MethodAttributes.FamANDAssem){
1366                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
1367                                         return false;
1368                         }
1369
1370                         // FamORAssem, Family and Public:
1371                         return true;
1372                 }
1373
1374                 if (m is FieldInfo){
1375                         FieldInfo fi = (FieldInfo) m;
1376                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
1377
1378                         if (fa == FieldAttributes.Private)
1379                                 return closure_private_ok;
1380
1381                         //
1382                         // FamAndAssem requires that we not only derivate, but we are on the
1383                         // same assembly.  
1384                         //
1385                         if (fa == FieldAttributes.FamANDAssem){
1386                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
1387                                         return false;
1388                         }
1389                         // FamORAssem, Family and Public:
1390                         return true;
1391                 }
1392
1393                 //
1394                 // EventInfos and PropertyInfos, return true
1395                 //
1396                 return true;
1397         }
1398
1399         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
1400         
1401         //
1402         // Looks up a member called `name' in the `queried_type'.  This lookup
1403         // is done by code that is contained in the definition for `invocation_type'.
1404         //
1405         // The binding flags are `bf' and the kind of members being looked up are `mt'
1406         //
1407         // Returns an array of a single element for everything but Methods/Constructors
1408         // that might return multiple matches.
1409         //
1410         public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type, 
1411                                                   MemberTypes mt, BindingFlags original_bf, string name)
1412         {
1413                 BindingFlags bf = original_bf;
1414                 
1415                 ArrayList method_list = null;
1416                 Type current_type = queried_type;
1417                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
1418                 bool private_ok;
1419                 bool always_ok_flag = false;
1420
1421                 closure_name = name;
1422                 closure_invocation_type = invocation_type;
1423                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
1424
1425                 //
1426                 // If we are a nested class, we always have access to our container
1427                 // type names
1428                 //
1429                 if (invocation_type != null){
1430                         string invocation_name = invocation_type.FullName;
1431                         if (invocation_name.IndexOf ('+') != -1){
1432                                 string container = queried_type.FullName + "+";
1433                                 int container_length = container.Length;
1434                                 
1435                                 if (invocation_name.Length > container_length){
1436                                         string shared = invocation_name.Substring (0, container_length);
1437                                 
1438                                         if (shared == container)
1439                                                 always_ok_flag = true;
1440                                 }
1441                         }
1442                 }
1443                 
1444                 do {
1445                         MemberInfo [] mi;
1446
1447                         //
1448                         // `NonPublic' is lame, because it includes both protected and
1449                         // private methods, so we need to control this behavior by
1450                         // explicitly tracking if a private method is ok or not.
1451                         //
1452                         // The possible cases are:
1453                         //    public, private and protected (internal does not come into the
1454                         //    equation)
1455                         //
1456                         if (invocation_type != null){
1457                                 if (invocation_type == current_type){
1458                                         private_ok = true;
1459                                 } else
1460                                         private_ok = always_ok_flag;
1461                                 
1462                                 if (private_ok || invocation_type.IsSubclassOf (current_type))
1463                                         bf = original_bf | BindingFlags.NonPublic;
1464                         } else {
1465                                 private_ok = false;
1466                                 bf = original_bf & ~BindingFlags.NonPublic;
1467                         }
1468
1469                         closure_private_ok = private_ok;
1470                         closure_queried_type = current_type;
1471                         
1472                         mi = TypeManager.FindMembers (
1473                                 current_type, mt, bf | BindingFlags.DeclaredOnly,
1474                                 FilterWithClosure_delegate, name);
1475                         
1476                         if (current_type == TypeManager.object_type)
1477                                 searching = false;
1478                         else {
1479                                 current_type = current_type.BaseType;
1480                                 
1481                                 //
1482                                 // This happens with interfaces, they have a null
1483                                 // basetype.  Look members up in the Object class.
1484                                 //
1485                                 if (current_type == null)
1486                                         current_type = TypeManager.object_type;
1487                         }
1488                         
1489                         if (mi == null)
1490                                 continue;
1491                         
1492                         int count = mi.Length;
1493                         
1494                         if (count == 0)
1495                                 continue;
1496                         
1497                         //
1498                         // Events and types are returned by both `static' and `instance'
1499                         // searches, which means that our above FindMembers will
1500                         // return two copies of the same.
1501                         //
1502                         if (count == 1 && !(mi [0] is MethodBase)){
1503                                 return mi;
1504                         }
1505
1506                         //
1507                         // Multiple properties: we query those just to find out the indexer
1508                         // name
1509                         //
1510                         if (mi [0] is PropertyInfo)
1511                                 return mi;
1512                         
1513                         //
1514                         // We found methods, turn the search into "method scan"
1515                         // mode.
1516                         //
1517                         
1518                         method_list = CopyNewMethods (method_list, mi);
1519                         mt &= (MemberTypes.Method | MemberTypes.Constructor);
1520                 } while (searching);
1521
1522                 if (method_list != null && method_list.Count > 0)
1523                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
1524         
1525                 //
1526                 // Interfaces do not list members they inherit, so we have to
1527                 // scan those.
1528                 // 
1529                 if (!queried_type.IsInterface)
1530                         return null;
1531
1532                 if (queried_type.IsArray)
1533                         queried_type = TypeManager.array_type;
1534                 
1535                 Type [] ifaces = GetInterfaces (queried_type);
1536                 if (ifaces == null)
1537                         return null;
1538                 
1539                 foreach (Type itype in ifaces){
1540                         MemberInfo [] x;
1541
1542                         x = MemberLookup (null, itype, mt, bf, name);
1543                         if (x != null)
1544                                 return x;
1545                 }
1546                                         
1547                 return null;
1548         }
1549 #endregion
1550         
1551 }
1552
1553 }