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