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