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