8d7dab4345296061a602858f81b9ae2d2f9e2fb8
[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.Module.Builder.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                 string n = mi.Name;
795                 if (n == ".ctor")
796                         n = mi.DeclaringType.Name;
797                 
798                 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + n;
799         }
800
801         static public string GetFullName (Type t)
802         {
803                 string name = t.FullName.Replace ('+', '.');
804
805                 DeclSpace tc = LookupDeclSpace (t);
806                 if ((tc != null) && tc.IsGeneric) {
807                         TypeParameter[] tparam = tc.TypeParameters;
808
809                         StringBuilder sb = new StringBuilder (name);
810                         sb.Append ("<");
811                         for (int i = 0; i < tparam.Length; i++) {
812                                 if (i > 0)
813                                         sb.Append (",");
814                                 sb.Append (tparam [i].Name);
815                         }
816                         sb.Append (">");
817                         return sb.ToString ();
818                 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
819                         Type[] tparam = t.GetGenericArguments ();
820
821                         StringBuilder sb = new StringBuilder (name);
822                         sb.Append ("<");
823                         for (int i = 0; i < tparam.Length; i++) {
824                                 if (i > 0)
825                                         sb.Append (",");
826                                 sb.Append (tparam [i].Name);
827                         }
828                         sb.Append (">");
829                         return sb.ToString ();
830                 }
831
832                 return name;
833         }
834
835         /// <summary>
836         ///   Returns the signature of the property and indexer
837         /// </summary>
838         static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) 
839         {
840                 if (!is_indexer) {
841                         return GetFullNameSignature (pb);
842                 }
843
844                 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
845                 string signature = GetFullNameSignature (mb);
846                 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
847                 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
848         }
849
850         /// <summary>
851         ///   Returns the signature of the method
852         /// </summary>
853         static public string CSharpSignature (MethodBase mb)
854         {
855                 string sig = "(";
856
857                 //
858                 // FIXME: We should really have a single function to do
859                 // everything instead of the following 5 line pattern
860                 //
861                 ParameterData iparams = LookupParametersByBuilder (mb);
862
863                 if (iparams == null)
864                         iparams = new ReflectionParameters (mb);
865                 
866                 for (int i = 0; i < iparams.Count; i++) {
867                         if (i > 0) {
868                                 sig += ", ";
869                         }
870                         sig += iparams.ParameterDesc(i);
871                 }
872                 sig += ")";
873
874                 return GetFullNameSignature (mb) + sig;
875         }
876
877         /// <summary>
878         ///   Looks up a type, and aborts if it is not found.  This is used
879         ///   by types required by the compiler
880         /// </summary>
881         static Type CoreLookupType (string name)
882         {
883                 Type t = LookupTypeDirect (name);
884
885                 if (t == null){
886                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
887                         Environment.Exit (0);
888                 }
889
890                 return t;
891         }
892
893         /// <summary>
894         ///   Returns the MethodInfo for a method named `name' defined
895         ///   in type `t' which takes arguments of types `args'
896         /// </summary>
897         static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
898         {
899                 MemberList list;
900                 Signature sig;
901                 BindingFlags flags = instance_and_static | BindingFlags.Public;
902
903                 sig.name = name;
904                 sig.args = args;
905                 
906                 if (is_private)
907                         flags |= BindingFlags.NonPublic;
908
909                 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
910                 if (list.Count == 0) {
911                         if (report_errors)
912                                 Report.Error (-19, "Can not find the core function `" + name + "'");
913                         return null;
914                 }
915
916                 MethodInfo mi = list [0] as MethodInfo;
917                 if (mi == null) {
918                         if (report_errors)
919                                 Report.Error (-19, "Can not find the core function `" + name + "'");
920                         return null;
921                 }
922
923                 return mi;
924         }
925
926         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
927         {
928                 return GetMethod (t, name, args, false, report_errors);
929         }
930
931         static MethodInfo GetMethod (Type t, string name, Type [] args)
932         {
933                 return GetMethod (t, name, args, true);
934         }
935
936
937         /// <summary>
938         ///    Returns the ConstructorInfo for "args"
939         /// </summary>
940         static ConstructorInfo GetConstructor (Type t, Type [] args)
941         {
942                 MemberList list;
943                 Signature sig;
944
945                 sig.name = ".ctor";
946                 sig.args = args;
947                 
948                 list = FindMembers (t, MemberTypes.Constructor,
949                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
950                                     signature_filter, sig);
951                 if (list.Count == 0){
952                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
953                         return null;
954                 }
955
956                 ConstructorInfo ci = list [0] as ConstructorInfo;
957                 if (ci == null){
958                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
959                         return null;
960                 }
961
962                 return ci;
963         }
964
965         public static void InitEnumUnderlyingTypes ()
966         {
967
968                 int32_type    = CoreLookupType ("System.Int32");
969                 int64_type    = CoreLookupType ("System.Int64");
970                 uint32_type   = CoreLookupType ("System.UInt32"); 
971                 uint64_type   = CoreLookupType ("System.UInt64"); 
972                 byte_type     = CoreLookupType ("System.Byte");
973                 sbyte_type    = CoreLookupType ("System.SByte");
974                 short_type    = CoreLookupType ("System.Int16");
975                 ushort_type   = CoreLookupType ("System.UInt16");
976         }
977         
978         /// <remarks>
979         ///   The types have to be initialized after the initial
980         ///   population of the type has happened (for example, to
981         ///   bootstrap the corlib.dll
982         /// </remarks>
983         public static void InitCoreTypes ()
984         {
985                 object_type   = CoreLookupType ("System.Object");
986                 value_type    = CoreLookupType ("System.ValueType");
987
988                 InitEnumUnderlyingTypes ();
989
990                 char_type     = CoreLookupType ("System.Char");
991                 string_type   = CoreLookupType ("System.String");
992                 float_type    = CoreLookupType ("System.Single");
993                 double_type   = CoreLookupType ("System.Double");
994                 char_ptr_type = CoreLookupType ("System.Char*");
995                 decimal_type  = CoreLookupType ("System.Decimal");
996                 bool_type     = CoreLookupType ("System.Boolean");
997                 enum_type     = CoreLookupType ("System.Enum");
998
999                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1000                 delegate_type           = CoreLookupType ("System.Delegate");
1001
1002                 array_type    = CoreLookupType ("System.Array");
1003                 void_type     = CoreLookupType ("System.Void");
1004                 type_type     = CoreLookupType ("System.Type");
1005
1006                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1007                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1008                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1009                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
1010                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
1011                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
1012                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
1013                 ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
1014                 idisposable_type     = CoreLookupType ("System.IDisposable");
1015                 icloneable_type      = CoreLookupType ("System.ICloneable");
1016                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
1017                 intptr_type          = CoreLookupType ("System.IntPtr");
1018
1019                 attribute_type       = CoreLookupType ("System.Attribute");
1020                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1021                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1022                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1023                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1024                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
1025                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1026
1027                 //
1028                 // Sigh. Remove this before the release.  Wonder what versions of Mono
1029                 // people are running.
1030                 //
1031                 guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1032
1033                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1034
1035                 void_ptr_type         = CoreLookupType ("System.Void*");
1036
1037                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1038
1039                 exception_type        = CoreLookupType ("System.Exception");
1040                 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1041
1042                 //
1043                 // Attribute types
1044                 //
1045                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1046                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1047
1048                 //
1049                 // When compiling corlib, store the "real" types here.
1050                 //
1051                 if (!RootContext.StdLib) {
1052                         system_int32_type = typeof (System.Int32);
1053                         system_array_type = typeof (System.Array);
1054                         system_type_type = typeof (System.Type);
1055                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1056
1057                         Type [] void_arg = {  };
1058                         system_int_array_get_length = GetMethod (
1059                                 system_array_type, "get_Length", void_arg);
1060                         system_int_array_get_rank = GetMethod (
1061                                 system_array_type, "get_Rank", void_arg);
1062                         system_object_array_clone = GetMethod (
1063                                 system_array_type, "Clone", void_arg);
1064
1065                         Type [] system_int_arg = { system_int32_type };
1066                         system_int_array_get_length_int = GetMethod (
1067                                 system_array_type, "GetLength", system_int_arg);
1068                         system_int_array_get_upper_bound_int = GetMethod (
1069                                 system_array_type, "GetUpperBound", system_int_arg);
1070                         system_int_array_get_lower_bound_int = GetMethod (
1071                                 system_array_type, "GetLowerBound", system_int_arg);
1072
1073                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
1074                         system_void_array_copyto_array_int = GetMethod (
1075                                 system_array_type, "CopyTo", system_array_int_arg);
1076
1077                         Type [] system_3_type_arg = {
1078                                 system_type_type, system_type_type, system_type_type };
1079                         Type [] system_4_type_arg = {
1080                                 system_type_type, system_type_type, system_type_type, system_type_type };
1081
1082                         MethodInfo set_corlib_type_builders = GetMethod (
1083                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1084                                 system_4_type_arg, true, false);
1085
1086                         if (set_corlib_type_builders != null) {
1087                                 object[] args = new object [4];
1088                                 args [0] = object_type;
1089                                 args [1] = value_type;
1090                                 args [2] = enum_type;
1091                                 args [3] = void_type;
1092                                 
1093                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1094                         } else {
1095                                 // Compatibility for an older version of the class libs.
1096                                 set_corlib_type_builders = GetMethod (
1097                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
1098                                         system_3_type_arg, true, true);
1099
1100                                 if (set_corlib_type_builders == null) {
1101                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1102                                         return;
1103                                 }
1104
1105                                 object[] args = new object [3];
1106                                 args [0] = object_type;
1107                                 args [1] = value_type;
1108                                 args [2] = enum_type;
1109                                 
1110                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1111                         }
1112                 }
1113
1114                 system_object_expr.Type = object_type;
1115                 system_string_expr.Type = string_type;
1116                 system_boolean_expr.Type = bool_type;
1117                 system_decimal_expr.Type = decimal_type;
1118                 system_single_expr.Type = float_type;
1119                 system_double_expr.Type = double_type;
1120                 system_sbyte_expr.Type = sbyte_type;
1121                 system_byte_expr.Type = byte_type;
1122                 system_int16_expr.Type = short_type;
1123                 system_uint16_expr.Type = ushort_type;
1124                 system_int32_expr.Type = int32_type;
1125                 system_uint32_expr.Type = uint32_type;
1126                 system_int64_expr.Type = int64_type;
1127                 system_uint64_expr.Type = uint64_type;
1128                 system_char_expr.Type = char_type;
1129                 system_void_expr.Type = void_type;
1130                 system_asynccallback_expr.Type = asynccallback_type;
1131                 system_iasyncresult_expr.Type = iasyncresult_type;
1132                 system_valuetype_expr.Type = value_type;
1133         }
1134
1135         //
1136         // The helper methods that are used by the compiler
1137         //
1138         public static void InitCodeHelpers ()
1139         {
1140                 //
1141                 // Now load the default methods that we use.
1142                 //
1143                 Type [] string_string = { string_type, string_type };
1144                 string_concat_string_string = GetMethod (
1145                         string_type, "Concat", string_string);
1146                 Type [] string_string_string = { string_type, string_type, string_type };
1147                 string_concat_string_string_string = GetMethod (
1148                         string_type, "Concat", string_string_string);
1149                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1150                 string_concat_string_string_string_string = GetMethod (
1151                         string_type, "Concat", string_string_string_string);
1152
1153                 Type [] object_object = { object_type, object_type };
1154                 string_concat_object_object = GetMethod (
1155                         string_type, "Concat", object_object);
1156
1157                 Type [] string_ = { string_type };
1158                 string_isinterneted_string = GetMethod (
1159                         string_type, "IsInterned", string_);
1160                 
1161                 Type [] runtime_type_handle = { runtime_handle_type };
1162                 system_type_get_type_from_handle = GetMethod (
1163                         type_type, "GetTypeFromHandle", runtime_type_handle);
1164
1165                 Type [] delegate_delegate = { delegate_type, delegate_type };
1166                 delegate_combine_delegate_delegate = GetMethod (
1167                                 delegate_type, "Combine", delegate_delegate);
1168
1169                 delegate_remove_delegate_delegate = GetMethod (
1170                                 delegate_type, "Remove", delegate_delegate);
1171
1172                 //
1173                 // Void arguments
1174                 //
1175                 Type [] void_arg = {  };
1176                 object_getcurrent_void = GetMethod (
1177                         ienumerator_type, "get_Current", void_arg);
1178                 bool_movenext_void = GetMethod (
1179                         ienumerator_type, "MoveNext", void_arg);
1180                 void_reset_void = GetMethod (
1181                         ienumerator_type, "Reset", void_arg);
1182                 void_dispose_void = GetMethod (
1183                         idisposable_type, "Dispose", void_arg);
1184                 int_get_offset_to_string_data = GetMethod (
1185                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
1186                 int_array_get_length = GetMethod (
1187                         array_type, "get_Length", void_arg);
1188                 int_array_get_rank = GetMethod (
1189                         array_type, "get_Rank", void_arg);
1190                 ienumerable_getenumerator_void = GetMethod (
1191                         ienumerable_type, "GetEnumerator", void_arg);
1192                 
1193                 //
1194                 // Int32 arguments
1195                 //
1196                 Type [] int_arg = { int32_type };
1197                 int_array_get_length_int = GetMethod (
1198                         array_type, "GetLength", int_arg);
1199                 int_array_get_upper_bound_int = GetMethod (
1200                         array_type, "GetUpperBound", int_arg);
1201                 int_array_get_lower_bound_int = GetMethod (
1202                         array_type, "GetLowerBound", int_arg);
1203
1204                 //
1205                 // System.Array methods
1206                 //
1207                 object_array_clone = GetMethod (
1208                         array_type, "Clone", void_arg);
1209                 Type [] array_int_arg = { array_type, int32_type };
1210                 void_array_copyto_array_int = GetMethod (
1211                         array_type, "CopyTo", array_int_arg);
1212                 
1213                 //
1214                 // object arguments
1215                 //
1216                 Type [] object_arg = { object_type };
1217                 void_monitor_enter_object = GetMethod (
1218                         monitor_type, "Enter", object_arg);
1219                 void_monitor_exit_object = GetMethod (
1220                         monitor_type, "Exit", object_arg);
1221
1222                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1223                 
1224                 void_initializearray_array_fieldhandle = GetMethod (
1225                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1226
1227                 //
1228                 // Array functions
1229                 //
1230                 int_getlength_int = GetMethod (
1231                         array_type, "GetLength", int_arg);
1232
1233                 //
1234                 // Decimal constructors
1235                 //
1236                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1237                 void_decimal_ctor_five_args = GetConstructor (
1238                         decimal_type, dec_arg);
1239                 
1240                 //
1241                 // Attributes
1242                 //
1243                 cons_param_array_attribute = GetConstructor (
1244                         param_array_type, void_arg);
1245
1246                 unverifiable_code_ctor = GetConstructor (
1247                         unverifiable_code_type, void_arg);
1248
1249                 //
1250                 // InvalidOperationException
1251                 //
1252                 invalid_operation_ctor = GetConstructor (
1253                         invalid_operation_exception_type, void_arg);
1254
1255
1256                 // Object
1257                 object_ctor = GetConstructor (object_type, void_arg);
1258
1259         }
1260
1261         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1262
1263         /// <remarks>
1264         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1265         ///   the cache here because there is no member name argument.
1266         /// </remarks>
1267         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1268                                               MemberFilter filter, object criteria)
1269         {
1270                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1271
1272                 //
1273                 // `builder_to_declspace' contains all dynamic types.
1274                 //
1275                 if (decl != null) {
1276                         MemberList list;
1277                         Timer.StartTimer (TimerType.FindMembers);
1278                         list = decl.FindMembers (mt, bf, filter, criteria);
1279                         Timer.StopTimer (TimerType.FindMembers);
1280                         return list;
1281                 }
1282
1283                 //
1284                 // We have to take care of arrays specially, because GetType on
1285                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1286                 // and we can not call FindMembers on this type.
1287                 //
1288                 if (t.IsSubclassOf (TypeManager.array_type))
1289                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1290
1291                 //
1292                 // Since FindMembers will not lookup both static and instance
1293                 // members, we emulate this behaviour here.
1294                 //
1295                 if ((bf & instance_and_static) == instance_and_static){
1296                         MemberInfo [] i_members = t.FindMembers (
1297                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1298
1299                         int i_len = i_members.Length;
1300                         if (i_len == 1){
1301                                 MemberInfo one = i_members [0];
1302
1303                                 //
1304                                 // If any of these are present, we are done!
1305                                 //
1306                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1307                                         return new MemberList (i_members);
1308                         }
1309                                 
1310                         MemberInfo [] s_members = t.FindMembers (
1311                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1312
1313                         int s_len = s_members.Length;
1314                         if (i_len > 0 || s_len > 0)
1315                                 return new MemberList (i_members, s_members);
1316                         else {
1317                                 if (i_len > 0)
1318                                         return new MemberList (i_members);
1319                                 else
1320                                         return new MemberList (s_members);
1321                         }
1322                 }
1323
1324                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1325         }
1326
1327
1328         /// <summary>
1329         ///   This method is only called from within MemberLookup.  It tries to use the member
1330         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1331         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1332         ///   our return value will already contain all inherited members and the caller don't need
1333         ///   to check base classes and interfaces anymore.
1334         /// </summary>
1335         private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1336                                                             string name, int num_type_arguments,
1337                                                             out bool used_cache)
1338         {
1339                 //
1340                 // We have to take care of arrays specially, because GetType on
1341                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1342                 // and we can not call FindMembers on this type.
1343                 //
1344                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1345                         used_cache = true;
1346                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1347                                 mt, bf, name, FilterWithClosure_delegate, null);
1348                 }
1349
1350                 //
1351                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1352                 // and we can ask the DeclSpace for the MemberCache.
1353                 //
1354                 if (t is TypeBuilder) {
1355                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1356                         MemberCache cache = decl.MemberCache;
1357
1358                         //
1359                         // If this DeclSpace has a MemberCache, use it.
1360                         //
1361
1362                         if (cache != null) {
1363                                 used_cache = true;
1364                                 return cache.FindMembers (
1365                                         mt, bf, name, FilterWithClosure_delegate, null);
1366                         }
1367
1368                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1369
1370                         MemberList list;
1371                         Timer.StartTimer (TimerType.FindMembers);
1372                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1373                                                  FilterWithClosure_delegate, name);
1374                         Timer.StopTimer (TimerType.FindMembers);
1375                         used_cache = false;
1376                         return list;
1377                 }
1378
1379                 //
1380                 // This call will always succeed.  There is exactly one TypeHandle instance per
1381                 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
1382                 // if it didn't already exist.
1383                 //
1384                 TypeHandle handle = TypeHandle.GetTypeHandle (t);
1385
1386                 used_cache = true;
1387                 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1388         }
1389
1390         public static bool IsBuiltinType (Type t)
1391         {
1392                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1393                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1394                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1395                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1396                         return true;
1397                 else
1398                         return false;
1399         }
1400
1401         //
1402         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1403         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1404         // 
1405         public static bool IsCLRType (Type t)
1406         {
1407                 if (t == object_type || t == int32_type || t == uint32_type ||
1408                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1409                     t == char_type || t == short_type || t == bool_type ||
1410                     t == sbyte_type || t == byte_type || t == ushort_type)
1411                         return true;
1412                 else
1413                         return false;
1414         }
1415
1416         public static bool IsDelegateType (Type t)
1417         {
1418                 if (t.IsGenericInstance)
1419                         t = t.GetGenericTypeDefinition ();
1420
1421                 if (t.IsSubclassOf (TypeManager.delegate_type))
1422                         return true;
1423                 else
1424                         return false;
1425         }
1426         
1427         public static bool IsEnumType (Type t)
1428         {
1429                 if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
1430                         return true;
1431                 else
1432                         return false;
1433         }
1434         public static bool IsBuiltinOrEnum (Type t)
1435         {
1436                 if (IsBuiltinType (t))
1437                         return true;
1438                 
1439                 if (IsEnumType (t))
1440                         return true;
1441
1442                 return false;
1443         }
1444
1445         //
1446         // Only a quick hack to get things moving, while real runtime support appears
1447         //
1448         public static bool IsGeneric (Type t)
1449         {
1450                 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1451
1452                 return ds.IsGeneric;
1453         }
1454
1455         public static int GetNumberOfTypeArguments (Type t)
1456         {
1457                 DeclSpace tc = LookupDeclSpace (t);
1458                 if (tc != null)
1459                         return tc.IsGeneric ? tc.CountTypeParameters : 0;
1460                 else
1461                         return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
1462         }
1463
1464         public static Type[] GetTypeArguments (Type t)
1465         {
1466                 DeclSpace tc = LookupDeclSpace (t);
1467                 if (tc != null) {
1468                         if (!tc.IsGeneric)
1469                                 throw new InvalidOperationException ();
1470
1471                         TypeParameter[] tparam = tc.TypeParameters;
1472                         Type[] ret = new Type [tparam.Length];
1473                         for (int i = 0; i < tparam.Length; i++) {
1474                                 ret [i] = tparam [i].Type;
1475                                 if (ret [i] == null)
1476                                         throw new InternalErrorException ();
1477                         }
1478
1479                         return ret;
1480                 } else
1481                         return t.GetGenericArguments ();
1482         }
1483
1484         public static bool CheckGeneric (Type t, int num_type_arguments)
1485         {
1486                 if (num_type_arguments < 0)
1487                         return true;
1488
1489                 DeclSpace tc = LookupDeclSpace (t);
1490
1491                 if (tc != null) {
1492                         if (!tc.IsGeneric)
1493                                 return num_type_arguments == 0;
1494
1495                         if (num_type_arguments == 0)
1496                                 return false;
1497
1498                         if (num_type_arguments != tc.CountTypeParameters)
1499                                 return false;
1500                 } else {
1501                         if (!t.HasGenericArguments)
1502                                 return num_type_arguments == 0;
1503
1504                         if (num_type_arguments == 0)
1505                                 return false;
1506
1507                         if (num_type_arguments != t.GetGenericArguments ().Length)
1508                                 return false;
1509                 }
1510
1511                 return true;
1512         }
1513         
1514         //
1515         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1516         //
1517         public static bool IsUnmanagedType (Type t)
1518         {
1519                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1520                         return true;
1521
1522                 if (IsEnumType (t))
1523                         return true;
1524
1525                 if (t.IsPointer)
1526                         return true;
1527
1528                 if (IsValueType (t)){
1529                         if (t is TypeBuilder){
1530                                 TypeContainer tc = LookupTypeContainer (t);
1531
1532                                 foreach (Field f in tc.Fields){
1533                                         if (f.FieldBuilder.IsStatic)
1534                                                 continue;
1535                                         if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1536                                                 return false;
1537                                 }
1538                         } else {
1539                                 FieldInfo [] fields = t.GetFields ();
1540
1541                                 foreach (FieldInfo f in fields){
1542                                         if (f.IsStatic)
1543                                                 continue;
1544                                         if (!IsUnmanagedType (f.FieldType))
1545                                                 return false;
1546                                 }
1547                         }
1548                         return true;
1549                 }
1550
1551                 return false;
1552         }
1553                 
1554         public static bool IsValueType (Type t)
1555         {
1556                 return t.IsGenericParameter || t.IsValueType;
1557         }
1558         
1559         public static bool IsInterfaceType (Type t)
1560         {
1561                 Interface iface = builder_to_declspace [t] as Interface;
1562
1563                 if (iface != null)
1564                         return true;
1565                 else
1566                         return false;
1567         }
1568
1569         public static bool IsEqualGenericType (Type a, Type b)
1570         {
1571                 if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
1572                         //
1573                         // `a' is a generic type definition's TypeBuilder and `b' is a
1574                         // generic instance of the same type.
1575                         //
1576                         // Example:
1577                         //
1578                         // class Stack<T>
1579                         // {
1580                         //     void Test (Stack<T> stack) { }
1581                         // }
1582                         //
1583                         // The first argument of `Test' will be the generic instance
1584                         // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1585                         //
1586                         if (a != b.GetGenericTypeDefinition ())
1587                                 return false;
1588
1589                         Type[] aparams = a.GetGenericArguments ();
1590                         Type[] bparams = b.GetGenericArguments ();
1591
1592                         if (aparams.Length != bparams.Length)
1593                                 return false;
1594
1595                         for (int i = 0; i < aparams.Length; i++)
1596                                 if (!aparams [i].Equals (bparams [i]))
1597                                         return false;
1598
1599                         return true;
1600                 }
1601
1602                 return false;
1603         }
1604
1605         public static bool IsEqual (Type a, Type b)
1606         {
1607                 if (a.Equals (b))
1608                         return true;
1609                 else
1610                         return IsEqualGenericType (a, b);
1611         }
1612
1613         public static bool MayBecomeEqualGenericTypes (Type a, Type b)
1614         {
1615                 if (a.IsGenericParameter) {
1616                         //
1617                         // If a is an array of a's type, they may never
1618                         // become equal.
1619                         //
1620                         while (b.IsArray) {
1621                                 b = b.GetElementType ();
1622                                 if (a.Equals (b))
1623                                         return false;
1624                         }
1625
1626                         //
1627                         // If b is a generic parameter or an actual type,
1628                         // they may become equal:
1629                         //
1630                         //    class X<T,U> : I<T>, I<U>
1631                         //    class X<T> : I<T>, I<float>
1632                         // 
1633                         if (b.IsGenericParameter || !b.IsGenericInstance)
1634                                 return true;
1635
1636                         //
1637                         // We're now comparing a type parameter with a
1638                         // generic instance.  They may become equal unless
1639                         // the type parameter appears anywhere in the
1640                         // generic instance:
1641                         //
1642                         //    class X<T,U> : I<T>, I<X<U>>
1643                         //        -> error because you could instanciate it as
1644                         //           X<X<int>,int>
1645                         //
1646                         //    class X<T> : I<T>, I<X<T>> -> ok
1647                         //
1648
1649                         Type[] bargs = GetTypeArguments (b);
1650                         for (int i = 0; i < bargs.Length; i++) {
1651                                 if (a.Equals (bargs [i]))
1652                                         return false;
1653                         }
1654
1655                         return true;
1656                 }
1657
1658                 if (b.IsGenericParameter)
1659                         return MayBecomeEqualGenericTypes (b, a);
1660
1661                 //
1662                 // At this point, neither a nor b are a type parameter.
1663                 //
1664                 // If one of them is a generic instance, let
1665                 // MayBecomeEqualGenericInstances() compare them (if the
1666                 // other one is not a generic instance, they can never
1667                 // become equal).
1668                 //
1669
1670                 if (a.IsGenericInstance || b.IsGenericInstance)
1671                         return MayBecomeEqualGenericInstances (a, b);
1672
1673                 //
1674                 // If both of them are arrays.
1675                 //
1676
1677                 if (a.IsArray && b.IsArray) {
1678                         if (a.GetArrayRank () != b.GetArrayRank ())
1679                                 return false;
1680                         
1681                         a = a.GetElementType ();
1682                         b = b.GetElementType ();
1683
1684                         return MayBecomeEqualGenericTypes (a, b);
1685                 }
1686
1687                 //
1688                 // Ok, two ordinary types.
1689                 //
1690
1691                 return a.Equals (b);
1692         }
1693
1694         //
1695         // Checks whether two generic instances may become equal for some
1696         // particular instantiation (26.3.1).
1697         //
1698         public static bool MayBecomeEqualGenericInstances (Type a, Type b)
1699         {
1700                 if (!a.IsGenericInstance || !b.IsGenericInstance)
1701                         return false;
1702                 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1703                         return false;
1704
1705                 Type[] aargs = GetTypeArguments (a);
1706                 Type[] bargs = GetTypeArguments (b);
1707
1708                 if (aargs.Length != bargs.Length)
1709                         return false;
1710
1711                 for (int i = 0; i < aargs.Length; i++) {
1712                         if (MayBecomeEqualGenericTypes (aargs [i], bargs [i]))
1713                                 return true;
1714                 }
1715
1716                 return false;
1717         }
1718
1719         //
1720         // Checks whether `type' is a subclass or nested child of `parent'.
1721         //
1722         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1723         {
1724                 do {
1725                         if ((type == parent) || type.IsSubclassOf (parent) ||
1726                             IsEqualGenericType (type, parent))
1727                                 return true;
1728
1729                         // Handle nested types.
1730                         type = type.DeclaringType;
1731                 } while (type != null);
1732
1733                 return false;
1734         }
1735
1736         //
1737         // Checks whether `type' is a nested child of `parent'.
1738         //
1739         public static bool IsNestedChildOf (Type type, Type parent)
1740         {
1741                 if (type == parent)
1742                         return false;
1743
1744                 type = type.DeclaringType;
1745                 while (type != null) {
1746                         if (type == parent)
1747                                 return true;
1748
1749                         type = type.DeclaringType;
1750                 }
1751
1752                 return false;
1753         }
1754
1755         //
1756         // Do the right thing when returning the element type of an
1757         // array type based on whether we are compiling corlib or not
1758         //
1759         public static Type GetElementType (Type t)
1760         {
1761                 if (RootContext.StdLib)
1762                         return t.GetElementType ();
1763                 else
1764                         return TypeToCoreType (t.GetElementType ());
1765         }
1766
1767         /// <summary>
1768         ///   Returns the User Defined Types
1769         /// </summary>
1770         public static ArrayList UserTypes {
1771                 get {
1772                         return user_types;
1773                 }
1774         }
1775
1776         public static Hashtable TypeContainers {
1777                 get {
1778                         return typecontainers;
1779                 }
1780         }
1781
1782         static Hashtable attr_to_allowmult;
1783
1784         public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
1785         {
1786                 if (attr_to_allowmult == null)
1787                         attr_to_allowmult = new PtrHashtable ();
1788
1789                 if (attr_to_allowmult.Contains (attr_type))
1790                         return;
1791
1792                 attr_to_allowmult.Add (attr_type, allow);
1793                                
1794         }
1795
1796         public static bool AreMultipleAllowed (Type attr_type)
1797         {
1798                 if (!(attr_type is TypeBuilder)) {
1799                         System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
1800
1801                         foreach (System.Attribute tmp in attrs)
1802                                 if (tmp is AttributeUsageAttribute) {
1803                                         return ((AttributeUsageAttribute) tmp).AllowMultiple;
1804                                 }
1805
1806                         return false;
1807                 }
1808                 
1809                 if (attr_to_allowmult == null)
1810                         return false;
1811
1812                 return (bool) attr_to_allowmult [attr_type];
1813         }
1814
1815         static Hashtable builder_to_constant;
1816
1817         public static void RegisterConstant (FieldBuilder fb, Const c)
1818         {
1819                 if (builder_to_constant == null)
1820                         builder_to_constant = new PtrHashtable ();
1821
1822                 if (builder_to_constant.Contains (fb))
1823                         return;
1824
1825                 builder_to_constant.Add (fb, c);
1826         }
1827
1828         public static Const LookupConstant (FieldBuilder fb)
1829         {
1830                 if (builder_to_constant == null)
1831                         return null;
1832                 
1833                 return (Const) builder_to_constant [fb];
1834         }
1835         
1836         /// <summary>
1837         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1838         /// </summary>
1839         ///
1840         /// <remarks>
1841         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1842         ///   for anything which is dynamic, and we need this in a number of places,
1843         ///   we register this information here, and use it afterwards.
1844         /// </remarks>
1845         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1846         {
1847                 if (args == null)
1848                         args = NoTypes;
1849                                 
1850                 method_arguments.Add (mb, args);
1851                 method_internal_params.Add (mb, ip);
1852                 
1853                 return true;
1854         }
1855         
1856         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1857         {
1858                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1859                         return null;
1860                 
1861                 if (method_internal_params.Contains (mb))
1862                         return (InternalParameters) method_internal_params [mb];
1863                 else
1864                         throw new Exception ("Argument for Method not registered" + mb);
1865         }
1866
1867         /// <summary>
1868         ///    Returns the argument types for a method based on its methodbase
1869         ///
1870         ///    For dynamic methods, we use the compiler provided types, for
1871         ///    methods from existing assemblies we load them from GetParameters,
1872         ///    and insert them into the cache
1873         /// </summary>
1874         static public Type [] GetArgumentTypes (MethodBase mb)
1875         {
1876                 if (method_arguments.Contains (mb))
1877                         return (Type []) method_arguments [mb];
1878                 else {
1879                         ParameterInfo [] pi = mb.GetParameters ();
1880                         int c = pi.Length;
1881                         Type [] types = new Type [c];
1882                         
1883                         for (int i = 0; i < c; i++)
1884                                 types [i] = pi [i].ParameterType;
1885
1886                         method_arguments.Add (mb, types);
1887                         return types;
1888                 }
1889         }
1890
1891         /// <summary>
1892         ///    Returns the argument types for an indexer based on its PropertyInfo
1893         ///
1894         ///    For dynamic indexers, we use the compiler provided types, for
1895         ///    indexers from existing assemblies we load them from GetParameters,
1896         ///    and insert them into the cache
1897         /// </summary>
1898         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1899         {
1900                 if (indexer_arguments.Contains (indexer))
1901                         return (Type []) indexer_arguments [indexer];
1902                 else if (indexer is PropertyBuilder)
1903                         // If we're a PropertyBuilder and not in the
1904                         // `indexer_arguments' hash, then we're a property and
1905                         // not an indexer.
1906                         return NoTypes;
1907                 else {
1908                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1909                         // Property, not an indexer.
1910                         if (pi == null)
1911                                 return NoTypes;
1912                         int c = pi.Length;
1913                         Type [] types = new Type [c];
1914                         
1915                         for (int i = 0; i < c; i++)
1916                                 types [i] = pi [i].ParameterType;
1917
1918                         indexer_arguments.Add (indexer, types);
1919                         return types;
1920                 }
1921         }
1922         
1923         // <remarks>
1924         //  This is a workaround the fact that GetValue is not
1925         //  supported for dynamic types
1926         // </remarks>
1927         static Hashtable fields = new Hashtable ();
1928         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1929         {
1930                 if (fields.Contains (fb))
1931                         return false;
1932
1933                 fields.Add (fb, value);
1934
1935                 return true;
1936         }
1937
1938         static public object GetValue (FieldBuilder fb)
1939         {
1940                 return fields [fb];
1941         }
1942
1943         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1944         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1945         {
1946                 if (fieldbuilders_to_fields.Contains (fb))
1947                         return false;
1948
1949                 fieldbuilders_to_fields.Add (fb, f);
1950                 return true;
1951         }
1952
1953         //
1954         // The return value can be null;  This will be the case for
1955         // auxiliary FieldBuilders created by the compiler that have no
1956         // real field being declared on the source code
1957         //
1958         static public FieldBase GetField (FieldInfo fb)
1959         {
1960                 return (FieldBase) fieldbuilders_to_fields [fb];
1961         }
1962         
1963         static Hashtable events;
1964
1965         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1966         {
1967                 if (events == null)
1968                         events = new Hashtable ();
1969
1970                 if (events.Contains (eb))
1971                         return false;
1972
1973                 events.Add (eb, new Pair (add, remove));
1974
1975                 return true;
1976         }
1977
1978         static public MethodInfo GetAddMethod (EventInfo ei)
1979         {
1980                 if (ei is MyEventBuilder) {
1981                         Pair pair = (Pair) events [ei];
1982
1983                         return (MethodInfo) pair.First;
1984                 } else
1985                         return ei.GetAddMethod ();
1986         }
1987
1988         static public MethodInfo GetRemoveMethod (EventInfo ei)
1989         {
1990                 if (ei is MyEventBuilder) {
1991                         Pair pair = (Pair) events [ei];
1992
1993                         return (MethodInfo) pair.Second;
1994                 } else
1995                         return ei.GetRemoveMethod ();
1996         }
1997
1998         static Hashtable priv_fields_events;
1999
2000         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2001         {
2002                 if (priv_fields_events == null)
2003                         priv_fields_events = new Hashtable ();
2004
2005                 if (priv_fields_events.Contains (einfo))
2006                         return false;
2007
2008                 priv_fields_events.Add (einfo, builder);
2009
2010                 return true;
2011         }
2012
2013         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2014         {
2015                 if (priv_fields_events == null)
2016                         return null;
2017                 else
2018                         return (MemberInfo) priv_fields_events [ei];
2019         }
2020                 
2021         static Hashtable properties;
2022         
2023         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2024         {
2025                 if (properties == null)
2026                         properties = new Hashtable ();
2027
2028                 if (properties.Contains (pb))
2029                         return false;
2030
2031                 properties.Add (pb, new Pair (get, set));
2032
2033                 return true;
2034         }
2035
2036         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2037                                             MethodBase set, Type[] args)
2038         {
2039                 if (!RegisterProperty (pb, get,set))
2040                         return false;
2041
2042                 indexer_arguments.Add (pb, args);
2043
2044                 return true;
2045         }
2046
2047         /// <summary>
2048         ///   Given an array of interface types, expand and eliminate repeated ocurrences
2049         ///   of an interface.  
2050         /// </summary>
2051         ///
2052         /// <remarks>
2053         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2054         ///   be IA, IB, IC.
2055         /// </remarks>
2056         public static TypeExpr[] ExpandInterfaces (TypeExpr [] base_interfaces)
2057         {
2058                 ArrayList new_ifaces = new ArrayList ();
2059                 
2060                 foreach (TypeExpr iface in base_interfaces){
2061                         if (!new_ifaces.Contains (iface))
2062                                 new_ifaces.Add (iface);
2063                         
2064                         TypeExpr [] implementing = iface.GetInterfaces ();
2065                         
2066                         foreach (TypeExpr imp in implementing){
2067                                 if (!new_ifaces.Contains (imp))
2068                                         new_ifaces.Add (imp);
2069                         }
2070                 }
2071                 TypeExpr [] ret = new TypeExpr [new_ifaces.Count];
2072                 new_ifaces.CopyTo (ret, 0);
2073                 return ret;
2074         }
2075                 
2076         static PtrHashtable iface_cache = new PtrHashtable ();
2077                 
2078         /// <summary>
2079         ///   This function returns the interfaces in the type `t'.  Works with
2080         ///   both types and TypeBuilders.
2081         /// </summary>
2082         public static TypeExpr [] GetInterfaces (Type t)
2083         {
2084                 
2085                 TypeExpr [] cached = iface_cache [t] as TypeExpr [];
2086                 if (cached != null)
2087                         return cached;
2088                 
2089                 //
2090                 // The reason for catching the Array case is that Reflection.Emit
2091                 // will not return a TypeBuilder for Array types of TypeBuilder types,
2092                 // but will still throw an exception if we try to call GetInterfaces
2093                 // on the type.
2094                 //
2095                 // Since the array interfaces are always constant, we return those for
2096                 // the System.Array
2097                 //
2098                 
2099                 if (t.IsArray)
2100                         t = TypeManager.array_type;
2101                 
2102                 if (t is TypeBuilder){
2103                         TypeExpr [] parent_ifaces;
2104                         
2105                         if (t.BaseType == null)
2106                                 parent_ifaces = NoTypeExprs;
2107                         else
2108                                 parent_ifaces = GetInterfaces (t.BaseType);
2109                         TypeExpr [] type_ifaces = (TypeExpr []) builder_to_ifaces [t];
2110                         if (type_ifaces == null)
2111                                 type_ifaces = NoTypeExprs;
2112
2113                         int parent_count = parent_ifaces.Length;
2114                         TypeExpr [] result = new TypeExpr [parent_count + type_ifaces.Length];
2115                         parent_ifaces.CopyTo (result, 0);
2116                         type_ifaces.CopyTo (result, parent_count);
2117
2118                         iface_cache [t] = result;
2119                         return result;
2120                 } else {
2121                         Type [] ifaces = t.GetInterfaces ();
2122                         if (ifaces.Length == 0)
2123                                 return NoTypeExprs;
2124
2125                         TypeExpr [] result = new TypeExpr [ifaces.Length];
2126                         for (int i = 0; i < ifaces.Length; i++)
2127                                 result [i] = new TypeExpression (ifaces [i], Location.Null);
2128                         
2129                         iface_cache [t] = result;
2130                         return result;
2131                 }
2132         }
2133         
2134         //
2135         // gets the interfaces that are declared explicitly on t
2136         //
2137         public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
2138         {
2139                 return (TypeExpr []) builder_to_ifaces [t];
2140         }
2141         
2142         /// <remarks>
2143         ///  The following is used to check if a given type implements an interface.
2144         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2145         /// </remarks>
2146         public static bool ImplementsInterface (Type t, Type iface)
2147         {
2148                 TypeExpr [] interfaces;
2149
2150                 //
2151                 // FIXME OPTIMIZATION:
2152                 // as soon as we hit a non-TypeBuiler in the interface
2153                 // chain, we could return, as the `Type.GetInterfaces'
2154                 // will return all the interfaces implement by the type
2155                 // or its parents.
2156                 //
2157                 do {
2158                         interfaces = GetInterfaces (t);
2159
2160                         if (interfaces != null){
2161                                 foreach (TypeExpr i in interfaces){
2162                                         if (i.Type == iface)
2163                                                 return true;
2164                                 }
2165                         }
2166                         
2167                         t = t.BaseType;
2168                 } while (t != null);
2169                 
2170                 return false;
2171         }
2172
2173         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2174
2175         // This is a custom version of Convert.ChangeType() which works
2176         // with the TypeBuilder defined types when compiling corlib.
2177         public static object ChangeType (object value, Type conversionType, out bool error)
2178         {
2179                 IConvertible convert_value = value as IConvertible;
2180                 
2181                 if (convert_value == null){
2182                         error = true;
2183                         return null;
2184                 }
2185                 
2186                 //
2187                 // We must use Type.Equals() here since `conversionType' is
2188                 // the TypeBuilder created version of a system type and not
2189                 // the system type itself.  You cannot use Type.GetTypeCode()
2190                 // on such a type - it'd always return TypeCode.Object.
2191                 //
2192                 error = false;
2193                 try {
2194                         if (conversionType.Equals (typeof (Boolean)))
2195                                 return (object)(convert_value.ToBoolean (nf_provider));
2196                         else if (conversionType.Equals (typeof (Byte)))
2197                                 return (object)(convert_value.ToByte (nf_provider));
2198                         else if (conversionType.Equals (typeof (Char)))
2199                                 return (object)(convert_value.ToChar (nf_provider));
2200                         else if (conversionType.Equals (typeof (DateTime)))
2201                                 return (object)(convert_value.ToDateTime (nf_provider));
2202                         else if (conversionType.Equals (typeof (Decimal)))
2203                                 return (object)(convert_value.ToDecimal (nf_provider));
2204                         else if (conversionType.Equals (typeof (Double)))
2205                                 return (object)(convert_value.ToDouble (nf_provider));
2206                         else if (conversionType.Equals (typeof (Int16)))
2207                                 return (object)(convert_value.ToInt16 (nf_provider));
2208                         else if (conversionType.Equals (typeof (Int32)))
2209                                 return (object)(convert_value.ToInt32 (nf_provider));
2210                         else if (conversionType.Equals (typeof (Int64)))
2211                                 return (object)(convert_value.ToInt64 (nf_provider));
2212                         else if (conversionType.Equals (typeof (SByte)))
2213                                 return (object)(convert_value.ToSByte (nf_provider));
2214                         else if (conversionType.Equals (typeof (Single)))
2215                                 return (object)(convert_value.ToSingle (nf_provider));
2216                         else if (conversionType.Equals (typeof (String)))
2217                                 return (object)(convert_value.ToString (nf_provider));
2218                         else if (conversionType.Equals (typeof (UInt16)))
2219                                 return (object)(convert_value.ToUInt16 (nf_provider));
2220                         else if (conversionType.Equals (typeof (UInt32)))
2221                                 return (object)(convert_value.ToUInt32 (nf_provider));
2222                         else if (conversionType.Equals (typeof (UInt64)))
2223                                 return (object)(convert_value.ToUInt64 (nf_provider));
2224                         else if (conversionType.Equals (typeof (Object)))
2225                                 return (object)(value);
2226                         else 
2227                                 error = true;
2228                 } catch {
2229                         error = true;
2230                 }
2231                 return null;
2232         }
2233
2234         //
2235         // This is needed, because enumerations from assemblies
2236         // do not report their underlyingtype, but they report
2237         // themselves
2238         //
2239         public static Type EnumToUnderlying (Type t)
2240         {
2241                 if (t == TypeManager.enum_type)
2242                         return t;
2243
2244                 t = t.UnderlyingSystemType;
2245                 if (!TypeManager.IsEnumType (t))
2246                         return t;
2247         
2248                 if (t is TypeBuilder) {
2249                         // slow path needed to compile corlib
2250                         if (t == TypeManager.bool_type ||
2251                                         t == TypeManager.byte_type ||
2252                                         t == TypeManager.sbyte_type ||
2253                                         t == TypeManager.char_type ||
2254                                         t == TypeManager.short_type ||
2255                                         t == TypeManager.ushort_type ||
2256                                         t == TypeManager.int32_type ||
2257                                         t == TypeManager.uint32_type ||
2258                                         t == TypeManager.int64_type ||
2259                                         t == TypeManager.uint64_type)
2260                                 return t;
2261                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2262                 }
2263                 TypeCode tc = Type.GetTypeCode (t);
2264
2265                 switch (tc){
2266                 case TypeCode.Boolean:
2267                         return TypeManager.bool_type;
2268                 case TypeCode.Byte:
2269                         return TypeManager.byte_type;
2270                 case TypeCode.SByte:
2271                         return TypeManager.sbyte_type;
2272                 case TypeCode.Char:
2273                         return TypeManager.char_type;
2274                 case TypeCode.Int16:
2275                         return TypeManager.short_type;
2276                 case TypeCode.UInt16:
2277                         return TypeManager.ushort_type;
2278                 case TypeCode.Int32:
2279                         return TypeManager.int32_type;
2280                 case TypeCode.UInt32:
2281                         return TypeManager.uint32_type;
2282                 case TypeCode.Int64:
2283                         return TypeManager.int64_type;
2284                 case TypeCode.UInt64:
2285                         return TypeManager.uint64_type;
2286                 }
2287                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2288         }
2289
2290         //
2291         // When compiling corlib and called with one of the core types, return
2292         // the corresponding typebuilder for that type.
2293         //
2294         public static Type TypeToCoreType (Type t)
2295         {
2296                 if (RootContext.StdLib || (t is TypeBuilder))
2297                         return t;
2298
2299                 TypeCode tc = Type.GetTypeCode (t);
2300
2301                 switch (tc){
2302                 case TypeCode.Boolean:
2303                         return TypeManager.bool_type;
2304                 case TypeCode.Byte:
2305                         return TypeManager.byte_type;
2306                 case TypeCode.SByte:
2307                         return TypeManager.sbyte_type;
2308                 case TypeCode.Char:
2309                         return TypeManager.char_type;
2310                 case TypeCode.Int16:
2311                         return TypeManager.short_type;
2312                 case TypeCode.UInt16:
2313                         return TypeManager.ushort_type;
2314                 case TypeCode.Int32:
2315                         return TypeManager.int32_type;
2316                 case TypeCode.UInt32:
2317                         return TypeManager.uint32_type;
2318                 case TypeCode.Int64:
2319                         return TypeManager.int64_type;
2320                 case TypeCode.UInt64:
2321                         return TypeManager.uint64_type;
2322                 case TypeCode.Single:
2323                         return TypeManager.float_type;
2324                 case TypeCode.Double:
2325                         return TypeManager.double_type;
2326                 case TypeCode.String:
2327                         return TypeManager.string_type;
2328                 default:
2329                         if (t == typeof (void))
2330                                 return TypeManager.void_type;
2331                         if (t == typeof (object))
2332                                 return TypeManager.object_type;
2333                         if (t == typeof (System.Type))
2334                                 return TypeManager.type_type;
2335                         return t;
2336                 }
2337         }
2338
2339         /// <summary>
2340         ///   Utility function that can be used to probe whether a type
2341         ///   is managed or not.  
2342         /// </summary>
2343         public static bool VerifyUnManaged (Type t, Location loc)
2344         {
2345                 if (t.IsValueType || t.IsPointer){
2346                         //
2347                         // FIXME: this is more complex, we actually need to
2348                         // make sure that the type does not contain any
2349                         // classes itself
2350                         //
2351                         return true;
2352                 }
2353
2354                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2355                         // We need this explicit check here to make it work when
2356                         // compiling corlib.
2357                         return true;
2358
2359                 Report.Error (
2360                         208, loc,
2361                         "Cannot take the address or size of a variable of a managed type ('" +
2362                         CSharpName (t) + "')");
2363                 return false;   
2364         }
2365         
2366         /// <summary>
2367         ///   Returns the name of the indexer in a given type.
2368         /// </summary>
2369         /// <remarks>
2370         ///   The default is not always `Item'.  The user can change this behaviour by
2371         ///   using the DefaultMemberAttribute in the class.
2372         ///
2373         ///   For example, the String class indexer is named `Chars' not `Item' 
2374         /// </remarks>
2375         public static string IndexerPropertyName (Type t)
2376         {
2377                 if (t.IsGenericInstance)
2378                         t = t.GetGenericTypeDefinition ();
2379
2380                 if (t is TypeBuilder) {
2381                         if (t.IsInterface) {
2382                                 Interface i = LookupInterface (t);
2383
2384                                 if ((i == null) || (i.IndexerName == null))
2385                                         return "Item";
2386
2387                                 return i.IndexerName;
2388                         } else {
2389                                 TypeContainer tc = LookupTypeContainer (t);
2390
2391                                 if ((tc == null) || (tc.IndexerName == null))
2392                                         return "Item";
2393
2394                                 return tc.IndexerName;
2395                         }
2396                 }
2397                 
2398                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2399                         t, TypeManager.default_member_type);
2400                 if (attr != null){
2401                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2402                         return dma.MemberName;
2403                 }
2404
2405                 return "Item";
2406         }
2407
2408         public static void MakePinned (LocalBuilder builder)
2409         {
2410                 //
2411                 // FIXME: Flag the "LocalBuilder" type as being
2412                 // pinned.  Figure out API.
2413                 //
2414         }
2415
2416
2417         //
2418         // Returns whether the array of memberinfos contains the given method
2419         //
2420         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2421         {
2422                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2423                 
2424                 foreach (MethodBase method in array) {
2425                         if (method.Name != new_method.Name)
2426                                 continue;
2427
2428                         if (method is MethodInfo && new_method is MethodInfo)
2429                                 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2430                                         continue;
2431
2432                         
2433                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2434                         int old_count = old_args.Length;
2435                         int i;
2436                         
2437                         if (new_args.Length != old_count)
2438                                 continue;
2439                         
2440                         for (i = 0; i < old_count; i++){
2441                                 if (old_args [i] != new_args [i])
2442                                         break;
2443                         }
2444                         if (i != old_count)
2445                                 continue;
2446
2447                         return true;
2448                 }
2449                 
2450                 return false;
2451         }
2452         
2453         //
2454         // We copy methods from `new_members' into `target_list' if the signature
2455         // for the method from in the new list does not exist in the target_list
2456         //
2457         // The name is assumed to be the same.
2458         //
2459         public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
2460         {
2461                 if (target_list == null){
2462                         target_list = new ArrayList ();
2463
2464                         foreach (MemberInfo mi in new_members){
2465                                 if (mi is MethodBase)
2466                                         target_list.Add (mi);
2467                         }
2468                         return target_list;
2469                 }
2470                 
2471                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2472                 target_list.CopyTo (target_array, 0);
2473                 
2474                 foreach (MemberInfo mi in new_members){
2475                         MethodBase new_method = (MethodBase) mi;
2476                         
2477                         if (!ArrayContainsMethod (target_array, new_method))
2478                                 target_list.Add (new_method);
2479                 }
2480                 return target_list;
2481         }
2482
2483         [Flags]
2484         public enum MethodFlags {
2485                 IsObsolete = 1,
2486                 IsObsoleteError = 1 << 1,
2487                 ShouldIgnore = 1 << 2
2488         }
2489
2490         static public bool IsGenericMethod (MethodInfo mb)
2491         {
2492                 if (mb.DeclaringType is TypeBuilder) {
2493                         MethodData method = (MethodData) builder_to_method [mb];
2494                         if (method == null)
2495                                 return false;
2496
2497                         return method.GenericMethod != null;
2498                 }
2499
2500                 return mb.IsGenericMethodDefinition;
2501         }
2502         
2503         //
2504         // Returns the TypeManager.MethodFlags for this method.
2505         // This emits an error 619 / warning 618 if the method is obsolete.
2506         // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2507         //
2508         static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
2509         {
2510                 MethodFlags flags = 0;
2511
2512                 if (mb.DeclaringType is TypeBuilder){
2513                         MethodData method = (MethodData) builder_to_method [mb];
2514                         if (method == null) {
2515                                 // FIXME: implement Obsolete attribute on Property,
2516                                 //        Indexer and Event.
2517                                 return 0;
2518                         }
2519
2520                         return method.GetMethodFlags (loc);
2521                 }
2522
2523                 if (mb.HasGenericParameters) {
2524                         MethodBase generic = mb.GetGenericMethodDefinition ();
2525
2526                         return GetMethodFlags (generic, loc);
2527                 }
2528
2529                 object [] attrs = mb.GetCustomAttributes (true);
2530                 foreach (object ta in attrs){
2531                         if (!(ta is System.Attribute)){
2532                                 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
2533                                 continue;
2534                         }
2535                         System.Attribute a = (System.Attribute) ta;
2536                         if (a.TypeId == TypeManager.obsolete_attribute_type){
2537                                 ObsoleteAttribute oa = (ObsoleteAttribute) a;
2538
2539                                 string method_desc = TypeManager.CSharpSignature (mb);
2540
2541                                 if (oa.IsError) {
2542                                         Report.Error (619, loc, "Method `" + method_desc +
2543                                                       "' is obsolete: `" + oa.Message + "'");
2544                                         return MethodFlags.IsObsoleteError;
2545                                 } else
2546                                         Report.Warning (618, loc, "Method `" + method_desc +
2547                                                         "' is obsolete: `" + oa.Message + "'");
2548
2549                                 flags |= MethodFlags.IsObsolete;
2550
2551                                 continue;
2552                         }
2553                         
2554                         //
2555                         // Skip over conditional code.
2556                         //
2557                         if (a.TypeId == TypeManager.conditional_attribute_type){
2558                                 ConditionalAttribute ca = (ConditionalAttribute) a;
2559
2560                                 if (RootContext.AllDefines [ca.ConditionString] == null)
2561                                         flags |= MethodFlags.ShouldIgnore;
2562                         }
2563                 }
2564
2565                 return flags;
2566         }
2567         
2568 #region MemberLookup implementation
2569         
2570         //
2571         // Whether we allow private members in the result (since FindMembers
2572         // uses NonPublic for both protected and private), we need to distinguish.
2573         //
2574         static bool     closure_private_ok;
2575
2576         //
2577         // Who is invoking us and which type is being queried currently.
2578         //
2579         static Type     closure_invocation_type;
2580         static Type     closure_qualifier_type;
2581         static int      closure_num_type_arguments;
2582
2583         //
2584         // The assembly that defines the type is that is calling us
2585         //
2586         static Assembly closure_invocation_assembly;
2587
2588         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2589         {
2590                 return true;
2591         }
2592         
2593         //
2594         // This filter filters by name + whether it is ok to include private
2595         // members in the search
2596         //
2597         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
2598         {
2599                 //
2600                 // Hack: we know that the filter criteria will always be in the `closure'
2601                 // fields. 
2602                 //
2603
2604                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
2605                         return false;
2606
2607                 if (m is Type)
2608                         return TypeManager.CheckGeneric ((Type) m, closure_num_type_arguments);
2609
2610                 if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
2611                     (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type))
2612                         return true;
2613
2614                 //
2615                 // Ugly: we need to find out the type of `m', and depending
2616                 // on this, tell whether we accept or not
2617                 //
2618                 if (m is MethodBase){
2619                         MethodBase mb = (MethodBase) m;
2620                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2621
2622                         if (ma == MethodAttributes.Private)
2623                                 return closure_private_ok ||
2624                                         IsEqual (closure_invocation_type, m.DeclaringType) ||
2625                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2626
2627                         //
2628                         // FamAndAssem requires that we not only derivate, but we are on the
2629                         // same assembly.  
2630                         //
2631                         if (ma == MethodAttributes.FamANDAssem){
2632                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
2633                                         return false;
2634                         }
2635
2636                         // Assembly and FamORAssem succeed if we're in the same assembly.
2637                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2638                                 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
2639                                         return true;
2640                         }
2641
2642                         // We already know that we aren't in the same assembly.
2643                         if (ma == MethodAttributes.Assembly)
2644                                 return false;
2645
2646                         // Family and FamANDAssem require that we derive.
2647                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2648                                 if (closure_invocation_type == null)
2649                                         return false;
2650
2651                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
2652                                         return false;
2653
2654                                 // Although a derived class can access protected members of its base class
2655                                 // it cannot do so through an instance of the base class (CS1540).
2656                                 if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2657                                     (closure_qualifier_type != null) &&
2658                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2659                                         return false;
2660
2661                                 return true;
2662                         }
2663
2664                         // Public.
2665                         return true;
2666                 }
2667
2668                 if (m is FieldInfo){
2669                         FieldInfo fi = (FieldInfo) m;
2670                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2671
2672                         if (fa == FieldAttributes.Private)
2673                                 return closure_private_ok ||
2674                                         IsEqual (closure_invocation_type, m.DeclaringType) ||
2675                                         IsNestedChildOf (closure_invocation_type, m.DeclaringType);
2676
2677                         //
2678                         // FamAndAssem requires that we not only derivate, but we are on the
2679                         // same assembly.  
2680                         //
2681                         if (fa == FieldAttributes.FamANDAssem){
2682                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
2683                                         return false;
2684                         }
2685
2686                         // Assembly and FamORAssem succeed if we're in the same assembly.
2687                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2688                                 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
2689                                         return true;
2690                         }
2691
2692                         // We already know that we aren't in the same assembly.
2693                         if (fa == FieldAttributes.Assembly)
2694                                 return false;
2695
2696                         // Family and FamANDAssem require that we derive.
2697                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
2698                                 if (closure_invocation_type == null)
2699                                         return false;
2700
2701                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
2702                                         return false;
2703
2704                                 // Although a derived class can access protected members of its base class
2705                                 // it cannot do so through an instance of the base class (CS1540).
2706                                 if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
2707                                     (closure_qualifier_type != null) &&
2708                                     closure_invocation_type.IsSubclassOf (closure_qualifier_type))
2709                                         return false;
2710
2711                                 return true;
2712                         }
2713
2714                         // Public.
2715                         return true;
2716                 }
2717
2718                 //
2719                 // EventInfos and PropertyInfos, return true because they lack permission
2720                 // informaiton, so we need to check later on the methods.
2721                 //
2722                 return true;
2723         }
2724
2725         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
2726         static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
2727
2728         //
2729         // Looks up a member called `name' in the `queried_type'.  This lookup
2730         // is done by code that is contained in the definition for `invocation_type'
2731         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
2732         //
2733         // `invocation_type' is used to check whether we're allowed to access the requested
2734         // member wrt its protection level.
2735         //
2736         // When called from MemberAccess, `qualifier_type' is the type which is used to access
2737         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
2738         // is B and qualifier_type is A).  This is used to do the CS1540 check.
2739         //
2740         // When resolving a SimpleName, `qualifier_type' is null.
2741         //
2742         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
2743         // the same than `queried_type' - except when we're being called from BaseAccess;
2744         // in this case, `invocation_type' is the current type and `queried_type' the base
2745         // type, so this'd normally trigger a CS1540.
2746         //
2747         // The binding flags are `bf' and the kind of members being looked up are `mt'
2748         //
2749         // The return value always includes private members which code in `invocation_type'
2750         // is allowed to access (using the specified `qualifier_type' if given); only use
2751         // BindingFlags.NonPublic to bypass the permission check.
2752         //
2753         // Returns an array of a single element for everything but Methods/Constructors
2754         // that might return multiple matches.
2755         //
2756         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
2757                                                   Type queried_type, int num_type_arguments,
2758                                                   MemberTypes mt, BindingFlags original_bf,
2759                                                   string name)
2760         {
2761                 Timer.StartTimer (TimerType.MemberLookup);
2762
2763                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
2764                                                         queried_type, num_type_arguments,
2765                                                         mt, original_bf, name);
2766
2767                 Timer.StopTimer (TimerType.MemberLookup);
2768
2769                 return retval;
2770         }
2771
2772         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
2773                                                Type queried_type, int num_type_arguments,
2774                                                MemberTypes mt, BindingFlags original_bf,
2775                                                string name)
2776         {
2777                 BindingFlags bf = original_bf;
2778                 
2779                 ArrayList method_list = null;
2780                 Type current_type = queried_type;
2781                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
2782                 bool skip_iface_check = true, used_cache = false;
2783                 bool always_ok_flag = false;
2784
2785                 closure_invocation_type = invocation_type;
2786                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
2787                 closure_qualifier_type = qualifier_type;
2788
2789                 closure_num_type_arguments = num_type_arguments;
2790
2791                 //
2792                 // If we are a nested class, we always have access to our container
2793                 // type names
2794                 //
2795                 if (invocation_type != null){
2796                         string invocation_name = invocation_type.FullName;
2797                         if (invocation_name.IndexOf ('+') != -1){
2798                                 string container = queried_type.FullName + "+";
2799                                 int container_length = container.Length;
2800
2801                                 if (invocation_name.Length > container_length){
2802                                         string shared = invocation_name.Substring (0, container_length);
2803                                 
2804                                         if (shared == container)
2805                                                 always_ok_flag = true;
2806                                 }
2807                         }
2808                 }
2809                 
2810                 do {
2811                         MemberList list;
2812
2813                         //
2814                         // `NonPublic' is lame, because it includes both protected and
2815                         // private methods, so we need to control this behavior by
2816                         // explicitly tracking if a private method is ok or not.
2817                         //
2818                         // The possible cases are:
2819                         //    public, private and protected (internal does not come into the
2820                         //    equation)
2821                         //
2822                         if ((invocation_type != null) &&
2823                             ((invocation_type == current_type) ||
2824                              IsNestedChildOf (invocation_type, current_type)) ||
2825                             always_ok_flag)
2826                                 bf = original_bf | BindingFlags.NonPublic;
2827                         else
2828                                 bf = original_bf;
2829
2830                         closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
2831
2832                         Timer.StopTimer (TimerType.MemberLookup);
2833
2834                         list = MemberLookup_FindMembers (current_type, mt, bf, name,
2835                                                          num_type_arguments, out used_cache);
2836
2837                         Timer.StartTimer (TimerType.MemberLookup);
2838
2839                         //
2840                         // When queried for an interface type, the cache will automatically check all
2841                         // inherited members, so we don't need to do this here.  However, this only
2842                         // works if we already used the cache in the first iteration of this loop.
2843                         //
2844                         // If we used the cache in any further iteration, we can still terminate the
2845                         // loop since the cache always looks in all parent classes.
2846                         //
2847
2848                         if (used_cache)
2849                                 searching = false;
2850                         else
2851                                 skip_iface_check = false;
2852
2853                         if (current_type == TypeManager.object_type)
2854                                 searching = false;
2855                         else {
2856                                 current_type = current_type.BaseType;
2857                                 
2858                                 //
2859                                 // This happens with interfaces, they have a null
2860                                 // basetype.  Look members up in the Object class.
2861                                 //
2862                                 if (current_type == null)
2863                                         current_type = TypeManager.object_type;
2864                         }
2865                         
2866                         if (list.Count == 0)
2867                                 continue;
2868
2869                         //
2870                         // Events and types are returned by both `static' and `instance'
2871                         // searches, which means that our above FindMembers will
2872                         // return two copies of the same.
2873                         //
2874                         if (list.Count == 1 && !(list [0] is MethodBase)){
2875                                 return (MemberInfo []) list;
2876                         }
2877
2878                         //
2879                         // Multiple properties: we query those just to find out the indexer
2880                         // name
2881                         //
2882                         if (list [0] is PropertyInfo)
2883                                 return (MemberInfo []) list;
2884
2885                         //
2886                         // We found an event: the cache lookup returns both the event and
2887                         // its private field.
2888                         //
2889                         if (list [0] is EventInfo) {
2890                                 if ((list.Count == 2) && (list [1] is FieldInfo))
2891                                         return new MemberInfo [] { list [0] };
2892
2893                                 // Oooops
2894                                 return null;
2895                         }
2896
2897                         //
2898                         // We found methods, turn the search into "method scan"
2899                         // mode.
2900                         //
2901
2902                         method_list = CopyNewMethods (method_list, list);
2903                         mt &= (MemberTypes.Method | MemberTypes.Constructor);
2904                 } while (searching);
2905
2906                 if (method_list != null && method_list.Count > 0) {
2907                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2908                 }
2909                 //
2910                 // This happens if we already used the cache in the first iteration, in this case
2911                 // the cache already looked in all interfaces.
2912                 //
2913                 if (skip_iface_check)
2914                         return null;
2915
2916                 //
2917                 // Interfaces do not list members they inherit, so we have to
2918                 // scan those.
2919                 // 
2920                 if (!queried_type.IsInterface)
2921                         return null;
2922
2923                 if (queried_type.IsArray)
2924                         queried_type = TypeManager.array_type;
2925                 
2926                 TypeExpr [] ifaces = GetInterfaces (queried_type);
2927                 if (ifaces == null)
2928                         return null;
2929                 
2930                 foreach (TypeExpr itype in ifaces){
2931                         MemberInfo [] x;
2932
2933                         x = MemberLookup (null, null, itype.Type, num_type_arguments,
2934                                           mt, bf, name);
2935                         if (x != null)
2936                                 return x;
2937                 }
2938                                         
2939                 return null;
2940         }
2941
2942         //
2943         // This is used to extract properties and event declarations from a type
2944         //
2945         static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
2946         {
2947                 BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
2948
2949                 bf |= BindingFlags.Public | BindingFlags.NonPublic;
2950                 
2951                 if (t is TypeBuilder) {
2952                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
2953
2954                         return (MemberInfo []) decl.FindMembers (
2955                                 MemberTypes.Property | MemberTypes.Event,
2956                                 bf, FilterNone_delegate, null);
2957                 } else {
2958                         return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
2959                                               bf, FilterNone_delegate, null);
2960
2961                 }
2962         }
2963         
2964         public static bool IsSpecialMethod (MethodBase mb)
2965         {
2966                 Type t = mb.DeclaringType;
2967                 
2968                 MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
2969                 if (matches == null)
2970                         return false;
2971                 
2972                 foreach (MemberInfo mi in matches){
2973                         if (mi is PropertyBuilder){
2974                                 Pair p = (Pair) properties [mi];
2975
2976                                 if (p.First == mb || p.Second == mb)
2977                                         return true;
2978                         } else if (mi is PropertyInfo){
2979                                 MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
2980                                 
2981                                 foreach (MethodInfo m in methods){
2982                                         if (m == mb)
2983                                                 return true;
2984                                 }
2985                         } else if (mi is MyEventBuilder){
2986                                 Pair p = (Pair) events [mi];
2987
2988                                 if (p.First == mb || p.Second == mb)
2989                                         return true;
2990                         } else if (mi is EventInfo){
2991                                 EventInfo ei = ((EventInfo) mi);
2992                                 
2993                                 if (ei.GetAddMethod (true) == mb)
2994                                         return true;
2995                                 
2996                                 if (ei.GetRemoveMethod (true) == mb)
2997                                         return true;
2998                                 
2999                                 if (ei.GetRaiseMethod (true) == mb)
3000                                         return true;
3001                         }
3002                 }
3003
3004                 //
3005                 // Now check if it is an operator method
3006                 //
3007                 string s = mb.Name;
3008
3009                 if (s.StartsWith ("op_")){
3010                         foreach (string name in Unary.oper_names){
3011                                 if (s == name)
3012                                         return true;
3013                         }
3014
3015                         foreach (string name in Binary.oper_names){
3016                                 if (s == name)
3017                                         return true;
3018                         }
3019                 }
3020                 
3021                 return false;
3022         }
3023                 
3024 #endregion
3025         
3026 }
3027
3028 /// <summary>
3029 ///   There is exactly one instance of this class per type.
3030 /// </summary>
3031 public sealed class TypeHandle : IMemberContainer {
3032         public readonly TypeHandle BaseType;
3033
3034         readonly int id = ++next_id;
3035         static int next_id = 0;
3036
3037         /// <summary>
3038         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
3039         ///   a TypeHandle yet, a new instance of it is created.  This static method
3040         ///   ensures that we'll only have one TypeHandle instance per type.
3041         /// </summary>
3042         public static TypeHandle GetTypeHandle (Type t)
3043         {
3044                 TypeHandle handle = (TypeHandle) type_hash [t];
3045                 if (handle != null)
3046                         return handle;
3047
3048                 handle = new TypeHandle (t);
3049                 type_hash.Add (t, handle);
3050                 return handle;
3051         }
3052         
3053         public static void CleanUp ()
3054         {
3055                 type_hash = null;
3056         }
3057
3058         /// <summary>
3059         ///   Returns the TypeHandle for TypeManager.object_type.
3060         /// </summary>
3061         public static IMemberContainer ObjectType {
3062                 get {
3063                         if (object_type != null)
3064                                 return object_type;
3065
3066                         object_type = GetTypeHandle (TypeManager.object_type);
3067
3068                         return object_type;
3069                 }
3070         }
3071
3072         /// <summary>
3073         ///   Returns the TypeHandle for TypeManager.array_type.
3074         /// </summary>
3075         public static IMemberContainer ArrayType {
3076                 get {
3077                         if (array_type != null)
3078                                 return array_type;
3079
3080                         array_type = GetTypeHandle (TypeManager.array_type);
3081
3082                         return array_type;
3083                 }
3084         }
3085
3086         private static PtrHashtable type_hash = new PtrHashtable ();
3087
3088         private static TypeHandle object_type = null;
3089         private static TypeHandle array_type = null;
3090
3091         private Type type;
3092         private bool is_interface;
3093         private MemberCache member_cache;
3094
3095         private TypeHandle (Type type)
3096         {
3097                 this.type = type;
3098                 if (type.BaseType != null)
3099                         BaseType = GetTypeHandle (type.BaseType);
3100                 this.is_interface = type.IsInterface;
3101                 this.member_cache = new MemberCache (this);
3102         }
3103
3104         // IMemberContainer methods
3105
3106         public string Name {
3107                 get {
3108                         return type.FullName;
3109                 }
3110         }
3111
3112         public Type Type {
3113                 get {
3114                         return type;
3115                 }
3116         }
3117
3118         public IMemberContainer Parent {
3119                 get {
3120                         return BaseType;
3121                 }
3122         }
3123
3124         public bool IsInterface {
3125                 get {
3126                         return is_interface;
3127                 }
3128         }
3129
3130         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3131         {
3132                 MemberInfo [] members;
3133                 if (mt == MemberTypes.Event)
3134                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3135                 else
3136                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3137                                                     null, null);
3138                 Array.Reverse (members);
3139
3140                 return new MemberList (members);
3141         }
3142
3143         // IMemberFinder methods
3144
3145         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3146                                        MemberFilter filter, object criteria)
3147         {
3148                 return member_cache.FindMembers (mt, bf, name, filter, criteria);
3149         }
3150
3151         public MemberCache MemberCache {
3152                 get {
3153                         return member_cache;
3154                 }
3155         }
3156
3157         public override string ToString ()
3158         {
3159                 if (BaseType != null)
3160                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3161                 else
3162                         return "TypeHandle (" + id + "," + Name + ")";
3163         }
3164 }
3165
3166 }