2 // typegen.cs: type generation
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
13 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
17 namespace Mono.CSharp {
19 public class TypeManager {
21 // A list of core types that the compiler requires or uses
23 static public Type object_type;
24 static public Type value_type;
25 static public Type string_type;
26 static public Type int32_type;
27 static public Type uint32_type;
28 static public Type int64_type;
29 static public Type uint64_type;
30 static public Type float_type;
31 static public Type double_type;
32 static public Type char_type;
33 static public Type short_type;
34 static public Type decimal_type;
35 static public Type bool_type;
36 static public Type sbyte_type;
37 static public Type byte_type;
38 static public Type ushort_type;
39 static public Type enum_type;
40 static public Type delegate_type;
41 static public Type void_type;
42 static public Type enumeration_type;
43 static public Type array_type;
44 static public Type runtime_handle_type;
45 static public Type icloneable_type;
46 static public Type type_type;
47 static public Type ienumerator_type;
48 static public Type idisposable_type;
49 static public Type default_member_type;
50 static public Type iasyncresult_type;
51 static public Type asynccallback_type;
52 static public Type intptr_type;
53 static public Type monitor_type;
54 static public Type runtime_field_handle_type;
55 static public Type attribute_usage_type;
56 static public Type param_array_type;
59 // Internal, not really used outside
61 Type runtime_helpers_type;
64 // These methods are called by code generated by the compiler
66 static public MethodInfo string_concat_string_string;
67 static public MethodInfo string_concat_object_object;
68 static public MethodInfo system_type_get_type_from_handle;
69 static public MethodInfo object_getcurrent_void;
70 static public MethodInfo bool_movenext_void;
71 static public MethodInfo void_dispose_void;
72 static public MethodInfo void_monitor_enter_object;
73 static public MethodInfo void_monitor_exit_object;
74 static public MethodInfo void_initializearray_array_fieldhandle;
75 static public MethodInfo int_getlength_int;
78 // The attribute constructors.
80 static public ConstructorInfo cons_param_array_attribute;
83 // Holds the Array of Assemblies that have been loaded
84 // (either because it is the default or the user used the
85 // -r command line option)
90 // Keeps a list of module builders. We used this to do lookups
91 // on the modulebuilder using GetType -- needed for arrays
96 // This is the type_cache from the assemblies to avoid
97 // hitting System.Reflection on every lookup.
102 // This is used to hotld the corresponding TypeContainer objects
103 // since we need this in FindMembers
105 Hashtable typecontainers;
108 // Keeps track of those types that are defined by the
111 ArrayList user_types;
114 // Keeps a mapping between TypeBuilders and their TypeContainers
116 static Hashtable builder_to_container;
119 // Maps MethodBase.RuntimeTypeHandle to a Type array that contains
120 // the arguments to the method
122 static Hashtable method_arguments;
124 static Hashtable builder_to_interface;
127 // Keeps track of delegate types
130 static Hashtable builder_to_delegate;
133 // Keeps track of enum types
136 static Hashtable builder_to_enum;
139 // Keeps track of attribute types
142 static Hashtable builder_to_attr;
144 public TypeManager ()
146 assemblies = new ArrayList ();
147 modules = new ArrayList ();
148 user_types = new ArrayList ();
149 types = new Hashtable ();
150 typecontainers = new Hashtable ();
151 builder_to_interface = new Hashtable ();
152 builder_to_delegate = new Hashtable ();
153 builder_to_enum = new Hashtable ();
154 builder_to_attr = new Hashtable ();
157 static TypeManager ()
159 method_arguments = new Hashtable ();
160 builder_to_container = new Hashtable ();
161 type_interface_cache = new Hashtable ();
164 static string MakeKey (Type t)
166 return t.FullName + t.GetHashCode ();
169 public void AddUserType (string name, TypeBuilder t)
175 public void AddUserType (string name, TypeBuilder t, TypeContainer tc)
177 AddUserType (name, t);
178 builder_to_container.Add (MakeKey (t), tc);
179 typecontainers.Add (name, tc);
182 public void AddDelegateType (string name, TypeBuilder t, Delegate del)
185 builder_to_delegate.Add (t, del);
188 public void AddEnumType (string name, TypeBuilder t, Enum en)
191 builder_to_enum.Add (MakeKey (t), en);
194 public void AddUserInterface (string name, TypeBuilder t, Interface i)
196 AddUserType (name, t);
197 builder_to_interface.Add (MakeKey (t), i);
200 public void RegisterAttrType (Type t, TypeContainer tc)
202 builder_to_attr.Add (MakeKey (t), tc);
206 /// Returns the TypeContainer whose Type is `t' or null if there is no
207 /// TypeContainer for `t' (ie, the Type comes from a library)
209 public static TypeContainer LookupTypeContainer (Type t)
211 return (TypeContainer) builder_to_container [MakeKey (t)];
214 public Interface LookupInterface (Type t)
216 return (Interface) builder_to_interface [MakeKey (t)];
219 public static Delegate LookupDelegate (Type t)
221 return (Delegate) builder_to_delegate [t];
224 public static Enum LookupEnum (Type t)
226 return (Enum) builder_to_enum [MakeKey (t)];
229 public static TypeContainer LookupAttr (Type t)
231 return (TypeContainer) builder_to_attr [MakeKey (t)];
235 /// Registers an assembly to load types from.
237 public void AddAssembly (Assembly a)
243 /// Registers a module builder to lookup types from
245 public void AddModule (ModuleBuilder mb)
251 /// Returns the Type associated with @name
253 public Type LookupType (string name)
258 // First lookup in user defined and cached values
261 t = (Type) types [name];
265 foreach (Assembly a in assemblies){
266 t = a.GetType (name);
274 foreach (ModuleBuilder mb in modules) {
275 t = mb.GetType (name);
286 /// Returns the C# name of a type if possible, or the full type name otherwise
288 static public string CSharpName (Type t)
292 else if (t == uint32_type)
294 else if (t == int64_type)
296 else if (t == uint64_type)
298 else if (t == float_type)
300 else if (t == double_type)
302 else if (t == char_type)
304 else if (t == short_type)
306 else if (t == decimal_type)
308 else if (t == bool_type)
310 else if (t == sbyte_type)
312 else if (t == byte_type)
314 else if (t == short_type)
316 else if (t == ushort_type)
318 else if (t == string_type)
320 else if (t == object_type)
327 /// Looks up a type, and aborts if it is not found. This is used
328 /// by types required by the compiler
330 Type CoreLookupType (string name)
332 Type t = LookupType (name);
335 throw new Exception ("Can not find core type " + name);
341 /// Returns the MethodInfo for a method named `name' defined
342 /// in type `t' which takes arguments of types `args'
344 MethodInfo GetMethod (Type t, string name, Type [] args)
346 MethodInfo mi = t.GetMethod (name, args);
349 throw new Exception ("Can not find the core function `" + name + "'");
354 ConstructorInfo GetConstructor (Type t, Type [] args)
356 ConstructorInfo ci = t.GetConstructor (args);
359 throw new Exception ("Can not find the core constructor for `" + t.FullName + "'");
365 /// The types have to be initialized after the initial
366 /// population of the type has happened (for example, to
367 /// bootstrap the corlib.dll
369 public void InitCoreTypes ()
371 object_type = CoreLookupType ("System.Object");
372 value_type = CoreLookupType ("System.ValueType");
373 string_type = CoreLookupType ("System.String");
374 int32_type = CoreLookupType ("System.Int32");
375 int64_type = CoreLookupType ("System.Int64");
376 uint32_type = CoreLookupType ("System.UInt32");
377 uint64_type = CoreLookupType ("System.UInt64");
378 float_type = CoreLookupType ("System.Single");
379 double_type = CoreLookupType ("System.Double");
380 byte_type = CoreLookupType ("System.Byte");
381 sbyte_type = CoreLookupType ("System.SByte");
382 char_type = CoreLookupType ("System.Char");
383 short_type = CoreLookupType ("System.Int16");
384 ushort_type = CoreLookupType ("System.UInt16");
385 decimal_type = CoreLookupType ("System.Decimal");
386 bool_type = CoreLookupType ("System.Boolean");
387 enum_type = CoreLookupType ("System.Enum");
388 delegate_type = CoreLookupType ("System.MulticastDelegate");
389 array_type = CoreLookupType ("System.Array");
390 void_type = CoreLookupType ("System.Void");
391 type_type = CoreLookupType ("System.Type");
393 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
394 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
395 default_member_type = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
396 runtime_handle_type = CoreLookupType ("System.RuntimeTypeHandle");
397 asynccallback_type = CoreLookupType ("System.AsyncCallback");
398 iasyncresult_type = CoreLookupType ("System.IAsyncResult");
399 ienumerator_type = CoreLookupType ("System.Collections.IEnumerator");
400 idisposable_type = CoreLookupType ("System.IDisposable");
401 icloneable_type = CoreLookupType ("System.ICloneable");
402 monitor_type = CoreLookupType ("System.Threading.Monitor");
403 intptr_type = CoreLookupType ("System.IntPtr");
405 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
406 param_array_type = CoreLookupType ("System.ParamArrayAttribute");
409 // Now load the default methods that we use.
411 Type [] string_string = { string_type, string_type };
412 string_concat_string_string = GetMethod (
413 string_type, "Concat", string_string);
415 Type [] object_object = { object_type, object_type };
416 string_concat_object_object = GetMethod (
417 string_type, "Concat", object_object);
419 Type [] runtime_type_handle = { runtime_handle_type };
420 system_type_get_type_from_handle = GetMethod (
421 type_type, "GetTypeFromHandle", runtime_type_handle);
426 Type [] void_arg = { };
427 object_getcurrent_void = GetMethod (
428 ienumerator_type, "get_Current", void_arg);
429 bool_movenext_void = GetMethod (
430 ienumerator_type, "MoveNext", void_arg);
431 void_dispose_void = GetMethod (
432 idisposable_type, "Dispose", void_arg);
437 Type [] object_arg = { object_type };
438 void_monitor_enter_object = GetMethod (
439 monitor_type, "Enter", object_arg);
440 void_monitor_exit_object = GetMethod (
441 monitor_type, "Exit", object_arg);
443 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
445 void_initializearray_array_fieldhandle = GetMethod (
446 runtime_helpers_type, "InitializeArray", array_field_handle_arg);
451 Type [] int_arg = { int32_type };
452 int_getlength_int = GetMethod (
453 array_type, "GetLength", int_arg);
458 cons_param_array_attribute = GetConstructor (
459 param_array_type, void_arg);
463 public MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
465 string key = MakeKey (t);
467 if (!(t is TypeBuilder))
468 return t.FindMembers (mt, bf, filter, criteria);
470 Enum e = (Enum) builder_to_enum [key];
473 return e.FindMembers (mt, bf, filter, criteria);
475 Delegate del = (Delegate) builder_to_delegate [t];
478 return del.FindMembers (mt, bf, filter, criteria);
480 Interface iface = (Interface) builder_to_interface [key];
483 return iface.FindMembers (mt, bf, filter, criteria);
485 TypeContainer tc = (TypeContainer) builder_to_container [key];
488 return tc.FindMembers (mt, bf, filter, criteria);
493 public static bool IsBuiltinType (Type t)
495 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
496 t == int64_type || t == uint64_type || t == float_type || t == double_type ||
497 t == char_type || t == short_type || t == decimal_type || t == bool_type ||
498 t == sbyte_type || t == byte_type || t == ushort_type)
504 public static bool IsDelegateType (Type t)
506 Delegate del = (Delegate) builder_to_delegate [t];
514 public static bool IsEnumType (Type t)
516 Enum en = (Enum) builder_to_enum [t];
524 public static bool IsInterfaceType (Type t)
526 Interface iface = (Interface) builder_to_interface [t];
535 /// Returns the User Defined Types
537 public ArrayList UserTypes {
543 public Hashtable TypeContainers {
545 return typecontainers;
549 static string GetSig (MethodBase mb)
551 if (mb is MethodBuilder || mb is ConstructorBuilder)
552 return mb.ReflectedType.FullName + ":" + mb;
554 return mb.MethodHandle.ToString ();
558 // Gigantic work around for stupidity in System.Reflection.Emit follows
560 // Since System.Reflection.Emit can not return MethodBase.GetParameters
561 // for anything which is dynamic, and we need this in a number of places,
562 // we register this information here, and use it afterwards.
564 static public bool RegisterMethod (MethodBase mb, Type [] args)
570 if (method_arguments.Contains (s))
573 method_arguments.Add (s, args);
578 /// Returns the argument types for a method based on its methodbase
580 /// For dynamic methods, we use the compiler provided types, for
581 /// methods from existing assemblies we load them from GetParameters,
582 /// and insert them into the cache
584 static public Type [] GetArgumentTypes (MethodBase mb)
586 string sig = GetSig (mb);
587 object o = method_arguments [sig];
589 if (method_arguments.Contains (sig))
590 return (Type []) method_arguments [sig];
592 ParameterInfo [] pi = mb.GetParameters ();
594 Type [] types = new Type [c];
596 for (int i = 0; i < c; i++)
597 types [i] = pi [i].ParameterType;
599 method_arguments.Add (sig, types);
605 // This is a workaround the fact that GetValue is not
606 // supported for dynamic types
608 static Hashtable fields;
610 static public bool RegisterField (FieldBuilder fb, object value)
613 fields = new Hashtable ();
615 if (fields.Contains (fb))
618 fields.Add (fb, value);
623 static public object GetValue (FieldBuilder fb)
629 static Hashtable properties;
631 static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
633 if (properties == null)
634 properties = new Hashtable ();
636 if (properties.Contains (pb))
639 properties.Add (pb, new DictionaryEntry (get, set));
644 static public MethodInfo [] GetAccessors (PropertyInfo pi)
648 if (pi is PropertyBuilder){
649 DictionaryEntry de = (DictionaryEntry) properties [pi];
651 ret = new MethodInfo [2];
652 ret [0] = (MethodInfo) de.Key;
653 ret [1] = (MethodInfo) de.Value;
657 return pi.GetAccessors ();
661 // The following is used to check if a given type implements an interface.
662 // The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
665 static Hashtable type_interface_cache;
667 public static bool ImplementsInterface (Type t, Type iface)
669 Type [] interfaces = (Type []) type_interface_cache [t];
671 if (interfaces == null) {
672 if (type_interface_cache.Contains (t))
675 interfaces = t.GetInterfaces ();
677 type_interface_cache [t] = interfaces;
680 if (interfaces == null)
683 for (int i = interfaces.Length; i > 0; ) {
685 if (interfaces [i] == iface)
694 /// Returns the name of the indexer in a given type.
697 /// The default is not always `Item'. The user can change this behaviour by
698 /// using the DefaultMemberAttribute in the class.
700 /// For example, the String class indexer is named `Chars' not `Item'
702 public static string IndexerPropertyName (Type t)
706 // FIXME: Replace with something that works around S.R.E failure
709 System.Attribute attr;
711 attr = System.Attribute.GetCustomAttribute (t, TypeManager.default_member_type);
715 DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
717 return dma.MemberName;