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