2 // class.cs: Class and Struct handlers
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)
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
19 public class TypeContainer : DeclSpace {
20 protected int mod_flags;
22 // Holds a list of classes and structures
25 // Holds the list of properties
28 // Holds the list of enumerations
31 // Holds the list of delegates
34 // Holds the list of constructors
35 ArrayList constructors;
37 // Holds the list of fields
40 // Holds a list of fields that have initializers
41 ArrayList initialized_fields;
43 // Holds a list of static fields that have initializers
44 ArrayList initialized_static_fields;
46 // Holds the list of constants
61 // Holds the operators
64 // Maps MethodBuilders to Methods
65 static Hashtable method_builders_to_methods;
68 // Pointers to the default constructor and the default static constructor
70 Constructor default_constructor;
71 Constructor default_static_constructor;
74 // Whether we have seen a static constructor for this class or not
76 bool have_static_constructor = false;
79 // This is the namespace in which this typecontainer
80 // was declared. We use this to resolve names.
82 Namespace my_namespace;
85 // This one is computed after we can distinguish interfaces
86 // from classes from the arraylist `type_bases'
88 string base_class_name;
94 // This behaves like a property ;-)
96 public readonly RootContext RootContext;
98 // Attributes for this type
99 protected Attributes attributes;
101 public TypeContainer (RootContext rc, TypeContainer parent, string name, Location l)
105 types = new ArrayList ();
106 this.parent = parent;
114 base_class_name = null;
116 //Console.WriteLine ("New class " + name + " inside " + n);
119 public AdditionResult AddConstant (Constant constant)
122 string name = constant.Name;
124 if ((res = IsValid (name)) != AdditionResult.Success)
127 if (constants == null)
128 constants = new ArrayList ();
130 constants.Add (constant);
131 DefineName (name, constant);
133 return AdditionResult.Success;
136 public AdditionResult AddEnum (CIR.Enum e)
139 string name = e.Name;
141 if ((res = IsValid (name)) != AdditionResult.Success)
145 enums = new ArrayList ();
148 DefineName (name, e);
150 return AdditionResult.Success;
153 public AdditionResult AddClass (Class c)
156 string name = c.Name;
159 if ((res = IsValid (name)) != AdditionResult.Success)
162 DefineName (name, c);
165 return AdditionResult.Success;
168 public AdditionResult AddStruct (Struct s)
171 string name = s.Name;
173 if ((res = IsValid (name)) != AdditionResult.Success)
176 DefineName (name, s);
179 return AdditionResult.Success;
182 public AdditionResult AddDelegate (Delegate d)
185 string name = d.Name;
187 if ((res = IsValid (name)) != AdditionResult.Success)
190 if (delegates == null)
191 delegates = new ArrayList ();
193 DefineName (name, d);
196 return AdditionResult.Success;
199 public AdditionResult AddMethod (Method method)
201 string name = method.Name;
202 Object value = defined_names [name];
204 if (value != null && (!(value is Method)))
205 return AdditionResult.NameExists;
208 methods = new ArrayList ();
210 methods.Add (method);
212 DefineName (name, method);
214 return AdditionResult.Success;
217 public AdditionResult AddConstructor (Constructor c)
219 if (c.Name != Basename)
220 return AdditionResult.NotAConstructor;
222 if (constructors == null)
223 constructors = new ArrayList ();
225 constructors.Add (c);
227 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
230 have_static_constructor = true;
232 if (c.IsDefault ()) {
234 default_static_constructor = c;
236 default_constructor = c;
239 return AdditionResult.Success;
242 public AdditionResult AddInterface (Interface iface)
245 string name = iface.Name;
247 if ((res = IsValid (name)) != AdditionResult.Success)
250 if (interfaces == null)
251 interfaces = new ArrayList ();
252 interfaces.Add (iface);
253 DefineName (name, iface);
255 return AdditionResult.Success;
258 public AdditionResult AddField (Field field)
261 string name = field.Name;
263 if ((res = IsValid (name)) != AdditionResult.Success)
267 fields = new ArrayList ();
270 if (field.Initializer != null){
271 if ((field.ModFlags & Modifiers.STATIC) != 0){
272 if (initialized_static_fields == null)
273 initialized_static_fields = new ArrayList ();
275 initialized_static_fields.Add (field);
278 // We have not seen a static constructor,
279 // but we will provide static initialization of fields
281 have_static_constructor = true;
283 if (initialized_fields == null)
284 initialized_fields = new ArrayList ();
286 initialized_fields.Add (field);
290 DefineName (name, field);
291 return AdditionResult.Success;
294 public AdditionResult AddProperty (Property prop)
297 string name = prop.Name;
299 if ((res = IsValid (name)) != AdditionResult.Success)
302 if (properties == null)
303 properties = new ArrayList ();
305 properties.Add (prop);
306 DefineName (name, prop);
308 return AdditionResult.Success;
311 public AdditionResult AddEvent (Event e)
314 string name = e.Name;
316 if ((res = IsValid (name)) != AdditionResult.Success)
320 events = new ArrayList ();
323 DefineName (name, e);
325 return AdditionResult.Success;
328 public AdditionResult AddIndexer (Indexer i)
330 if (indexers == null)
331 indexers = new ArrayList ();
335 return AdditionResult.Success;
338 public AdditionResult AddOperator (Operator op)
340 if (operators == null)
341 operators = new ArrayList ();
345 return AdditionResult.Success;
348 public TypeContainer Parent {
354 public ArrayList Types {
360 public ArrayList Methods {
366 public ArrayList Constants {
372 public ArrayList Interfaces {
378 public int ModFlags {
386 return base_class_name;
390 public ArrayList Bases {
400 public ArrayList Fields {
406 public ArrayList Constructors {
412 public ArrayList Properties {
418 public ArrayList Events {
424 public ArrayList Enums {
430 public ArrayList Indexers {
436 public ArrayList Operators {
442 public ArrayList Delegates {
448 public Attributes OptAttributes {
454 public Namespace Namespace {
460 my_namespace = value;
465 // root_types contains all the types. All TopLevel types
466 // hence have a parent that points to `root_types', that is
467 // why there is a non-obvious test down here.
469 public bool IsTopLevel {
472 if (parent.Parent == null)
479 public bool HaveStaticConstructor {
481 return have_static_constructor;
485 public virtual TypeAttributes TypeAttr {
487 return Modifiers.TypeAttr (mod_flags, this);
492 // Emits the instance field initializers
494 public bool EmitFieldInitializers (EmitContext ec, bool is_static)
497 ILGenerator ig = ec.ig;
500 fields = initialized_static_fields;
502 fields = initialized_fields;
507 foreach (Field f in fields){
508 Object init = f.Initializer;
510 if (init is Expression){
511 Expression e = (Expression) init;
513 e = e.Resolve (this);
518 ig.Emit (OpCodes.Ldarg_0);
523 ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
525 ig.Emit (OpCodes.Stfld, f.FieldBuilder);
533 // Defines the default constructors
535 void DefineDefaultConstructor (bool is_static)
540 c = new Constructor (Name, new Parameters (null, null),
541 new ConstructorBaseInitializer (null, new Location (-1)),
544 c.Block = new Block (null);
547 mods = Modifiers.STATIC;
552 public void ReportStructInitializedInstanceError ()
554 string n = TypeBuilder.FullName;
556 foreach (Field f in initialized_fields){
559 "`" + n + "." + f.Name + "': can not have " +
560 "instance field initializers in structs");
564 public void RegisterRequiredImplementations ()
566 Type [] ifaces = TypeBuilder.GetInterfaces ();
567 Type b = TypeBuilder.BaseType;
570 SetRequiredInterfaces (ifaces);
573 MemberInfo [] abstract_methods;
575 abstract_methods = FindMembers (
576 TypeBuilder.BaseType,
577 MemberTypes.Method, BindingFlags.Public,
578 abstract_method_filter, null);
580 if (abstract_methods != null){
581 MethodInfo [] mi = new MethodInfo [abstract_methods.Length];
583 abstract_methods.CopyTo (mi, 0);
584 RequireMethods (mi, b);
590 static object MakeKey (MethodBase mb)
592 if (mb is MethodBuilder || mb is ConstructorBuilder)
593 return mb.ReflectedType.FullName + ":" + mb;
595 return mb.MethodHandle.ToString ();
599 // Populates our TypeBuilder with fields and methods
601 public void Populate ()
603 if (Constants != null){
604 foreach (Constant c in Constants)
605 c.EmitConstant (RootContext, this);
609 foreach (Field f in Fields)
611 } else if (this is Struct){
613 // FIXME: Add a dummy field, because it is currently
614 // not possible with the reflection API to tell the size
617 TypeBuilder.DefineField ("Dummy", TypeManager.sbyte_type,
618 FieldAttributes.Static | FieldAttributes.Private);
622 if (default_constructor == null)
623 DefineDefaultConstructor (false);
625 if (initialized_static_fields != null &&
626 default_static_constructor == null)
627 DefineDefaultConstructor (true);
632 // Structs can not have initialized instance
635 if (initialized_static_fields != null &&
636 default_static_constructor == null)
637 DefineDefaultConstructor (true);
639 if (initialized_fields != null)
640 ReportStructInitializedInstanceError ();
643 RegisterRequiredImplementations ();
645 ArrayList remove_list = new ArrayList ();
647 if (constructors != null || methods != null ||
648 properties != null || operators != null){
649 if (method_builders_to_methods == null)
650 method_builders_to_methods = new Hashtable ();
653 if (constructors != null){
654 foreach (Constructor c in constructors){
655 MethodBase builder = c.Define (this);
660 method_builders_to_methods.Add (MakeKey (builder), c);
663 foreach (object o in remove_list)
664 constructors.Remove (o);
666 remove_list.Clear ();
669 if (Methods != null){
670 foreach (Method m in methods){
671 MethodBase key = m.Define (this);
675 // The following key is not enoug
676 // class x { public void X () {} }
677 // class y : x { public void X () {}}
683 method_builders_to_methods.Add (MakeKey (key), m);
685 foreach (object o in remove_list)
688 remove_list.Clear ();
691 if (Properties != null) {
692 foreach (Property p in Properties)
697 foreach (Enum e in Enums)
701 if (Events != null) {
702 foreach (Event e in Events)
706 if (Indexers != null) {
707 foreach (Indexer i in Indexers)
711 if (Operators != null) {
712 foreach (Operator o in Operators) {
715 method_builders_to_methods.Add (
716 MakeKey (o.OperatorMethodBuilder), o.OperatorMethod);
720 if (Delegates != null) {
721 foreach (Delegate d in Delegates)
727 // the `mb' must be a MethodBuilder or a
728 // ConstructorBuilder, we return the method that
731 static public MethodCore LookupMethodByBuilder (MethodBase mb)
733 return (MethodCore) method_builders_to_methods [MakeKey (mb)];
736 public Type LookupType (string name, bool silent)
738 return RootContext.LookupType (this, name, silent);
742 // This function is based by a delegate to the FindMembers routine
744 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
750 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
752 MethodInfo mi = (MethodInfo) m;
754 return mi.IsAbstract;
757 // This filter is used by FindMembers, and we just keep
758 // a global for the filter to `AlwaysAccept'
760 static MemberFilter accepting_filter;
763 // This delegate is a MemberFilter used to extract the
764 // abstact methods from a type.
766 static MemberFilter abstract_method_filter;
768 static TypeContainer ()
770 abstract_method_filter = new MemberFilter (IsAbstractMethod);
771 accepting_filter = new MemberFilter (AlwaysAccept);
775 // This method returns the members of this type just like Type.FindMembers would
776 // Only, we need to use this for types which are _being_ defined because MS'
777 // implementation can't take care of that.
779 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
780 MemberFilter filter, object criteria)
782 ArrayList members = new ArrayList ();
785 filter = accepting_filter;
787 if ((mt & MemberTypes.Field) != 0 && Fields != null) {
788 foreach (Field f in Fields) {
789 if (filter (f.FieldBuilder, criteria) == true)
790 members.Add (f.FieldBuilder);
794 if ((mt & MemberTypes.Method) != 0) {
795 if (Methods != null){
796 foreach (Method m in Methods) {
797 MethodBuilder mb = m.MethodBuilder;
799 if (filter (mb, criteria) == true)
804 if (Operators != null){
805 foreach (Operator o in Operators) {
806 MethodBuilder ob = o.OperatorMethodBuilder;
808 if (filter (ob, criteria) == true)
814 // FIXME : This ain't right because EventBuilder is not a
815 // MemberInfo. What do we do ?
817 if ((mt & MemberTypes.Event) != 0 && Events != null) {
818 //foreach (Event e in Events) {
819 // if (filter (e.EventBuilder, criteria) == true)
820 // mi [i++] = e.EventBuilder;
824 if ((mt & MemberTypes.Property) != 0 && Properties != null) {
825 foreach (Property p in Properties) {
826 if (filter (p.PropertyBuilder, criteria) == true)
827 members.Add (p.PropertyBuilder);
831 if ((mt & MemberTypes.NestedType) != 0 && Types != null) {
832 foreach (TypeContainer t in Types) {
833 if (filter (t.TypeBuilder, criteria) == true)
834 members.Add (t.TypeBuilder);
838 if ((mt & MemberTypes.Constructor) != 0){
839 if (Constructors != null){
840 foreach (Constructor c in Constructors){
841 ConstructorBuilder cb = c.ConstructorBuilder;
843 if (filter (cb, criteria) == true)
850 // Lookup members in parent if requested.
852 if ((bf & BindingFlags.DeclaredOnly) == 0){
855 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
857 members.AddRange (mi);
860 int count = members.Count;
862 MemberInfo [] mi = new MemberInfo [count];
870 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
871 MemberFilter filter, object criteria)
873 TypeContainer tc = TypeManager.LookupTypeContainer (t);
876 return tc.FindMembers (mt, bf, filter, criteria);
878 return t.FindMembers (mt, bf, filter, criteria);
882 Hashtable pending_implementations;
885 // Requires that the methods in `mi' be implemented for this
888 public void RequireMethods (MethodInfo [] mi, object data)
890 if (pending_implementations == null)
891 pending_implementations = new Hashtable ();
893 foreach (MethodInfo m in mi){
894 Type [] types = TypeManager.GetArgumentTypes (m);
896 pending_implementations.Add (
898 (m.Name, m.ReturnType, types), data);
903 // Used to set the list of interfaces that this typecontainer
908 // For each element exposed by the type, we create a MethodSignature
909 // struct that we will label as `implemented' as we define the various
912 public void SetRequiredInterfaces (Type [] ifaces)
914 foreach (Type t in ifaces){
917 if (t is TypeBuilder){
918 Interface iface = RootContext.TypeManager.LookupInterface (t);
920 mi = iface.GetMethods ();
922 mi = t.GetMethods ();
924 RequireMethods (mi, t);
929 // If a method with name `Name', return type `ret_type' and
930 // arguments `args' implements an interface, this method will
933 // This will remove the method from the list of "pending" methods
934 // that are required to be implemented for this class as a side effect.
937 public bool IsInterfaceMethod (string Name, Type ret_type, Type [] args)
939 MethodSignature query;
941 if (pending_implementations == null)
944 query = new MethodSignature (Name, ret_type, args);
946 if (pending_implementations.Contains (query)){
947 pending_implementations.Remove (query);
955 // Verifies that any pending abstract methods or interface methods
958 void VerifyPendingMethods ()
962 foreach (object m in pending_implementations){
963 DictionaryEntry de = (DictionaryEntry) m;
964 Type t = (Type) de.Value;
967 MethodSignature method = (MethodSignature) de.Key;
972 "`" + Name + "' does not implement interface member `" +
973 t.FullName + "." + method.Name + "'");
977 "`" + Name + "' does not implement inherited abstract " +
978 "member `" + t.FullName + "." + method.Name + "'");
983 // Emits the code, this step is performed after all
984 // the types, enumerations, constructors
988 if (Constructors != null)
989 foreach (Constructor c in Constructors)
993 foreach (Method m in methods)
996 if (operators != null)
997 foreach (Operator o in operators)
1000 if (properties != null)
1001 foreach (Property p in properties)
1004 if (pending_implementations != null)
1005 VerifyPendingMethods ();
1008 string MakeName (string n)
1010 return "`" + Name + "." + n + "'";
1013 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1019 public class Class : TypeContainer {
1021 // Modifiers allowed in a class declaration
1023 public const int AllowedModifiers =
1026 Modifiers.PROTECTED |
1027 Modifiers.INTERNAL |
1029 Modifiers.ABSTRACT |
1032 public Class (RootContext rc, TypeContainer parent, string name, int mod,
1033 Attributes attrs, Location l)
1034 : base (rc, parent, name, l)
1038 if (parent.Parent == null)
1039 accmods = Modifiers.INTERNAL;
1041 accmods = Modifiers.PRIVATE;
1043 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1044 this.attributes = attrs;
1048 // FIXME: How do we deal with the user specifying a different
1051 public override TypeAttributes TypeAttr {
1053 return base.TypeAttr | TypeAttributes.AutoLayout;
1058 public class Struct : TypeContainer {
1060 // Modifiers allowed in a struct declaration
1062 public const int AllowedModifiers =
1065 Modifiers.PROTECTED |
1066 Modifiers.INTERNAL |
1069 public Struct (RootContext rc, TypeContainer parent, string name, int mod,
1070 Attributes attrs, Location l)
1071 : base (rc, parent, name, l)
1075 if (parent.Parent == null)
1076 accmods = Modifiers.INTERNAL;
1078 accmods = Modifiers.PRIVATE;
1080 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1082 this.mod_flags |= Modifiers.SEALED;
1083 this.attributes = attrs;
1088 // FIXME: Allow the user to specify a different set of attributes
1089 // in some cases (Sealed for example is mandatory for a class,
1090 // but what SequentialLayout can be changed
1092 public override TypeAttributes TypeAttr {
1094 return base.TypeAttr |
1095 TypeAttributes.SequentialLayout |
1096 TypeAttributes.Sealed |
1097 TypeAttributes.BeforeFieldInit;
1102 public class MethodCore {
1103 public readonly Parameters Parameters;
1104 public readonly string Name;
1105 public int ModFlags;
1107 public readonly Location Location;
1110 // Parameters, cached for semantic analysis.
1112 InternalParameters parameter_info;
1114 public MethodCore (string name, Parameters parameters, Location l)
1117 Parameters = parameters;
1122 // Returns the System.Type array for the parameters of this method
1124 Type [] parameter_types;
1125 public Type [] ParameterTypes (TypeContainer parent)
1127 if (Parameters == null)
1130 if (parameter_types == null)
1131 parameter_types = Parameters.GetParameterInfo (parent);
1133 return parameter_types;
1136 public InternalParameters ParameterInfo
1139 return parameter_info;
1143 parameter_info = value;
1147 public Block Block {
1157 public CallingConventions GetCallingConvention (bool is_class)
1159 CallingConventions cc = 0;
1161 cc = Parameters.GetCallingConvention ();
1164 if ((ModFlags & Modifiers.STATIC) == 0)
1165 cc |= CallingConventions.HasThis;
1167 // FIXME: How is `ExplicitThis' used in C#?
1173 public class Method : MethodCore {
1174 public readonly string ReturnType;
1175 public MethodBuilder MethodBuilder;
1176 public readonly Attributes OptAttributes;
1179 // Modifiers allowed in a class declaration
1181 const int AllowedModifiers =
1184 Modifiers.PROTECTED |
1185 Modifiers.INTERNAL |
1190 Modifiers.OVERRIDE |
1191 Modifiers.ABSTRACT |
1194 // return_type can be "null" for VOID values.
1195 public Method (string return_type, int mod, string name, Parameters parameters,
1196 Attributes attrs, Location l)
1197 : base (name, parameters, l)
1199 ReturnType = return_type;
1200 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1201 OptAttributes = attrs;
1204 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1208 if (! (m is MethodInfo))
1211 MethodSignature sig = (MethodSignature) filter_criteria;
1213 if (m.Name != sig.Name)
1216 mi = (MethodInfo) m;
1218 if (mi.ReturnType != sig.RetType)
1221 Type [] args = TypeManager.GetArgumentTypes (mi);
1222 Type [] sigp = sig.Parameters;
1225 // FIXME: remove this assumption if we manage to
1226 // not enter a null as a the Parameters in TypeManager's
1227 // MethodBase to Type argument mapper.
1234 } else if (sigp == null)
1237 if (args.Length != sigp.Length)
1240 for (int i = args.Length; i > 0; ){
1242 if (args [i] != sigp [i])
1249 // This delegate is used to extract methods which have the
1250 // same signature as the argument
1252 static MemberFilter method_signature_filter;
1256 method_signature_filter = new MemberFilter (MemberSignatureCompare);
1260 // Returns the `System.Type' for the ReturnType of this
1261 // function. Provides a nice cache. (used between semantic analysis
1262 // and actual code generation
1264 Type type_return_type;
1265 public Type GetReturnType (TypeContainer parent)
1267 if (type_return_type == null)
1268 type_return_type = parent.LookupType (ReturnType, false);
1270 return type_return_type;
1273 void WarningNotHiding (TypeContainer parent)
1277 "The member `" + parent.Name + "." + Name + "' does not hide an " +
1278 "inherited member. The keyword new is not required");
1282 string MakeName (TypeContainer parent)
1284 return "`" + parent.Name + "." + Name + "'";
1287 string MethodBaseName (MethodBase mb)
1289 return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
1292 bool CheckMethod (TypeContainer parent, MemberInfo [] mi)
1294 MethodInfo mb = (MethodInfo) mi [0];
1296 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1298 108, Location, "The keyword new is required on " +
1299 MakeName (parent) + " because it hides `" +
1300 mb.ReflectedType.Name + "." +
1304 if (mb.IsVirtual || mb.IsAbstract){
1305 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1307 114, Location, MakeName (parent) +
1308 "hides inherited member " + MethodBaseName (mb) +
1309 ". To make the current member override that " +
1310 "implementation, add the override keyword, " +
1311 "otherwise use the new keyword");
1322 public MethodBuilder Define (TypeContainer parent)
1324 Type ret_type = GetReturnType (parent);
1325 Type [] parameters = ParameterTypes (parent);
1326 MethodAttributes flags;
1330 // Verify if the parent has a type with the same name, and then
1331 // check whether we have to create a new slot for it or not.
1333 Type ptype = parent.TypeBuilder.BaseType;
1335 // ptype is only null for System.Object while compiling corlib.
1337 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1340 mi = TypeContainer.FindMembers (
1341 ptype, MemberTypes.Method,
1342 BindingFlags.Public, method_signature_filter,
1345 if (mi != null && mi.Length > 0){
1346 CheckMethod (parent, mi);
1348 if ((ModFlags & Modifiers.NEW) != 0)
1349 WarningNotHiding (parent);
1351 if ((ModFlags & Modifiers.OVERRIDE) != 0)
1352 Report.Error (115, Location,
1354 " no suitable methods found to override");
1356 } else if ((ModFlags & Modifiers.NEW) != 0)
1357 WarningNotHiding (parent);
1360 // If we implement an interface, then set the proper flags.
1362 flags = Modifiers.MethodAttr (ModFlags);
1364 if (parent.IsInterfaceMethod (Name, ret_type, parameters))
1365 flags |= MethodAttributes.Virtual;
1368 // Catch invalid uses of virtual and abtract modifiers
1370 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1371 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1373 if ((ModFlags & va) == va){
1374 if ((ModFlags & va) == va){
1376 503, Location, "The abstract method " +
1377 MakeName (parent) + "can not be marked virtual");
1382 if ((ModFlags & Modifiers.ABSTRACT) != 0){
1383 if ((parent.ModFlags & Modifiers.ABSTRACT) == 0){
1385 513, Location, MakeName (parent) +
1386 " is abstract but its container class is not");
1391 if ((ModFlags & va) != 0 && ((ModFlags & Modifiers.PRIVATE) != 0)){
1393 621, Location, MakeName (parent) +
1394 " virtual or abstract members can not be private");
1398 if ((ModFlags & Modifiers.OVERRIDE) != 0 && ((ModFlags & nv) != 0)){
1400 113, Location, MakeName (parent) +
1401 "marked as override cannot be marked as new or virtual");
1409 // Finally, define the method
1412 MethodBuilder = parent.TypeBuilder.DefineMethod (
1414 GetCallingConvention (parent is Class),
1415 ret_type, parameters);
1418 // HACK because System.Reflection.Emit is lame
1420 TypeManager.RegisterMethod (MethodBuilder, parameters);
1422 ParameterInfo = new InternalParameters (parameters);
1425 // This is used to track the Entry Point,
1427 // FIXME: Allow pluggable entry point, check arguments, etc.
1429 if (Name == "Main"){
1430 if ((ModFlags & Modifiers.STATIC) != 0){
1431 parent.RootContext.EntryPoint = MethodBuilder;
1436 // Define each type attribute (in/out/ref) and
1437 // the argument names.
1439 Parameter [] p = Parameters.FixedParameters;
1443 for (i = 0; i < p.Length; i++)
1444 MethodBuilder.DefineParameter (
1445 i + 1, p [i].Attributes, p [i].Name);
1447 if (i != parameters.Length)
1448 Console.WriteLine ("Implement the type definition for params");
1451 return MethodBuilder;
1457 public void Emit (TypeContainer parent)
1459 ILGenerator ig = MethodBuilder.GetILGenerator ();
1460 EmitContext ec = new EmitContext (parent, ig);
1462 ec.EmitTopBlock (Block);
1466 public abstract class ConstructorInitializer {
1467 ArrayList argument_list;
1468 ConstructorInfo parent_constructor;
1471 public ConstructorInitializer (ArrayList argument_list, Location location)
1473 this.argument_list = argument_list;
1474 this.location = location;
1477 public ArrayList Arguments {
1479 return argument_list;
1483 public bool Resolve (TypeContainer tc)
1485 Expression parent_constructor_group;
1487 if (argument_list != null){
1488 for (int i = argument_list.Count; i > 0; ){
1491 Argument a = (Argument) argument_list [i];
1492 if (!a.Resolve (tc))
1497 parent_constructor_group = Expression.MemberLookup (
1499 tc.TypeBuilder.BaseType, ".ctor", false,
1500 MemberTypes.Constructor,
1501 BindingFlags.Public | BindingFlags.Instance);
1503 if (parent_constructor_group == null){
1504 Console.WriteLine ("Could not find a constructor in our parent");
1508 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (tc,
1509 (MethodGroupExpr) parent_constructor_group, argument_list, location);
1511 if (parent_constructor == null)
1517 public void Emit (EmitContext ec)
1519 ec.ig.Emit (OpCodes.Ldarg_0);
1520 if (argument_list != null)
1521 Invocation.EmitArguments (ec, parent_constructor, argument_list);
1522 ec.ig.Emit (OpCodes.Call, parent_constructor);
1526 public class ConstructorBaseInitializer : ConstructorInitializer {
1527 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1532 public class ConstructorThisInitializer : ConstructorInitializer {
1533 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1538 public class Constructor : MethodCore {
1539 public ConstructorBuilder ConstructorBuilder;
1540 public ConstructorInitializer Initializer;
1543 // Modifiers allowed for a constructor.
1545 const int AllowedModifiers =
1547 Modifiers.PROTECTED |
1548 Modifiers.INTERNAL |
1553 // The spec claims that static is not permitted, but
1554 // my very own code has static constructors.
1556 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
1557 : base (name, args, l)
1563 // Returns true if this is a default constructor
1565 public bool IsDefault ()
1567 return (Parameters == null ? true : Parameters.Empty) &&
1568 (Initializer is ConstructorBaseInitializer) &&
1569 (Initializer.Arguments == null);
1573 // Creates the ConstructorBuilder
1575 public ConstructorBuilder Define (TypeContainer parent)
1577 MethodAttributes ca = (MethodAttributes.RTSpecialName |
1578 MethodAttributes.SpecialName);
1580 Type [] parameters = ParameterTypes (parent);
1582 if (parent is Struct && parameters == null){
1585 "Structs can not contain explicit parameterless constructors");
1589 if ((ModFlags & Modifiers.STATIC) != 0)
1590 ca |= MethodAttributes.Static;
1592 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
1593 ca, GetCallingConvention (parent is Class),
1596 // HACK because System.Reflection.Emit is lame
1598 TypeManager.RegisterMethod (ConstructorBuilder, parameters);
1600 ParameterInfo = new InternalParameters (parameters);
1602 return ConstructorBuilder;
1608 public void Emit (TypeContainer parent)
1610 if (parent is Class){
1611 if (Initializer == null)
1612 Initializer = new ConstructorBaseInitializer (null, parent.Location);
1613 if (!Initializer.Resolve (parent))
1617 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
1618 EmitContext ec = new EmitContext (parent, ig);
1621 // Classes can have base initializers and instance field initializers.
1623 if (parent is Class){
1624 if ((ModFlags & Modifiers.STATIC) == 0)
1625 Initializer.Emit (ec);
1626 parent.EmitFieldInitializers (ec, false);
1629 if ((ModFlags & Modifiers.STATIC) != 0)
1630 parent.EmitFieldInitializers (ec, true);
1632 ec.EmitTopBlock (Block);
1636 public class Field {
1637 public readonly string Type;
1638 public readonly Object Initializer;
1639 public readonly string Name;
1640 public readonly int ModFlags;
1641 public readonly Attributes OptAttributes;
1642 public FieldBuilder FieldBuilder;
1646 // Modifiers allowed in a class declaration
1648 const int AllowedModifiers =
1651 Modifiers.PROTECTED |
1652 Modifiers.INTERNAL |
1657 public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
1660 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1662 Initializer = expr_or_array_init;
1663 OptAttributes = attrs;
1666 public void Define (TypeContainer parent)
1668 Type t = parent.LookupType (Type, false);
1673 FieldBuilder = parent.TypeBuilder.DefineField (
1674 Name, t, Modifiers.FieldAttr (ModFlags));
1678 public class Property {
1680 public readonly string Type;
1681 public readonly string Name;
1682 public readonly int ModFlags;
1683 public Block Get, Set;
1684 public PropertyBuilder PropertyBuilder;
1685 public Attributes OptAttributes;
1686 MethodBuilder GetBuilder, SetBuilder;
1689 const int AllowedModifiers =
1692 Modifiers.PROTECTED |
1693 Modifiers.INTERNAL |
1697 Modifiers.OVERRIDE |
1698 Modifiers.ABSTRACT |
1701 public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
1705 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
1708 OptAttributes = attrs;
1711 public void Define (TypeContainer parent)
1714 MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
1716 // FIXME - PropertyAttributes.HasDefault ?
1718 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
1719 PropertyAttributes.SpecialName;
1722 Type tp = parent.LookupType (Type, false);
1723 Type [] parameters = new Type [1];
1724 parameters [0] = tp;
1726 PropertyBuilder = parent.TypeBuilder.DefineProperty(Name, prop_attr, tp, null);
1730 GetBuilder = parent.TypeBuilder.DefineMethod (
1731 "get_" + Name, method_attr, tp, null);
1732 PropertyBuilder.SetGetMethod (GetBuilder);
1734 // HACK because System.Reflection.Emit is lame
1736 TypeManager.RegisterMethod (GetBuilder, null);
1741 SetBuilder = parent.TypeBuilder.DefineMethod (
1742 "set_" + Name, method_attr, null, parameters);
1743 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
1744 PropertyBuilder.SetSetMethod (SetBuilder);
1746 // HACK because System.Reflection.Emit is lame
1748 TypeManager.RegisterMethod (SetBuilder, parameters);
1753 public void Emit (TypeContainer tc)
1759 ig = GetBuilder.GetILGenerator ();
1760 ec = new EmitContext (tc, ig);
1762 ec.EmitTopBlock (Get);
1766 ig = SetBuilder.GetILGenerator ();
1767 ec = new EmitContext (tc, ig);
1769 ec.EmitTopBlock (Set);
1774 public class Event {
1776 const int AllowedModifiers =
1779 Modifiers.PROTECTED |
1780 Modifiers.INTERNAL |
1785 Modifiers.OVERRIDE |
1788 public readonly string Type;
1789 public readonly string Name;
1790 public readonly Object Initializer;
1791 public readonly int ModFlags;
1792 public readonly Block Add;
1793 public readonly Block Remove;
1794 public EventBuilder EventBuilder;
1795 public Attributes OptAttributes;
1797 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
1803 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
1806 OptAttributes = attrs;
1809 public void Define (TypeContainer parent)
1811 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
1813 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
1817 Type t = parent.LookupType (Type, false);
1818 Type [] parameters = new Type [1];
1821 EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
1824 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null,
1826 mb.DefineParameter (1, ParameterAttributes.None, "value");
1827 EventBuilder.SetAddOnMethod (mb);
1829 // HACK because System.Reflection.Emit is lame
1831 TypeManager.RegisterMethod (mb, parameters);
1834 if (Remove != null) {
1835 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null,
1837 mb.DefineParameter (1, ParameterAttributes.None, "value");
1838 EventBuilder.SetRemoveOnMethod (mb);
1841 // HACK because System.Reflection.Emit is lame
1843 TypeManager.RegisterMethod (mb, parameters);
1849 public class Indexer {
1851 const int AllowedModifiers =
1854 Modifiers.PROTECTED |
1855 Modifiers.INTERNAL |
1859 Modifiers.OVERRIDE |
1862 public readonly string Type;
1863 public readonly string InterfaceType;
1864 public readonly Parameters FormalParameters;
1865 public readonly int ModFlags;
1866 public readonly Block Get;
1867 public readonly Block Set;
1868 public Attributes OptAttributes;
1869 public MethodBuilder GetMethodBuilder;
1870 public MethodBuilder SetMethodBuilder;
1873 public Indexer (string type, string int_type, int flags, Parameters parms,
1874 Block get_block, Block set_block, Attributes attrs)
1878 InterfaceType = int_type;
1879 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
1880 FormalParameters = parms;
1883 OptAttributes = attrs;
1886 public void Define (TypeContainer parent)
1888 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
1890 Type ret_type = parent.LookupType (Type, false);
1891 Type [] parameters = FormalParameters.GetParameterInfo (parent);
1893 GetMethodBuilder = parent.TypeBuilder.DefineMethod (
1894 "get_Item", attr, ret_type, parameters);
1895 SetMethodBuilder = parent.TypeBuilder.DefineMethod (
1896 "set_Item", attr, ret_type, parameters);
1899 // HACK because System.Reflection.Emit is lame
1901 TypeManager.RegisterMethod (GetMethodBuilder, parameters);
1902 TypeManager.RegisterMethod (SetMethodBuilder, parameters);
1904 Parameter [] p = FormalParameters.FixedParameters;
1909 for (i = 0; i < p.Length; ++i) {
1910 GetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
1911 SetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
1914 if (i != parameters.Length)
1915 Console.WriteLine ("Implement type definition for params");
1922 public class Operator {
1924 const int AllowedModifiers =
1928 const int RequiredModifiers =
1932 public enum OpType {
1942 // Unary and Binary operators
1962 // Implicit and Explicit
1967 public readonly OpType OperatorType;
1968 public readonly string ReturnType;
1969 public readonly string FirstArgType;
1970 public readonly string FirstArgName;
1971 public readonly string SecondArgType;
1972 public readonly string SecondArgName;
1973 public readonly int ModFlags;
1974 public readonly Block Block;
1975 public Attributes OptAttributes;
1976 public MethodBuilder OperatorMethodBuilder;
1977 public Location Location;
1979 public string MethodName;
1980 public Method OperatorMethod;
1982 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
1983 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
1985 OperatorType = type;
1986 ReturnType = ret_type;
1987 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
1988 FirstArgType = arg1type;
1989 FirstArgName = arg1name;
1990 SecondArgType = arg2type;
1991 SecondArgName = arg2name;
1993 OptAttributes = attrs;
1997 string Prototype (TypeContainer parent)
1999 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
2000 SecondArgType + ")";
2003 public void Define (TypeContainer parent)
2006 MethodName = "op_" + OperatorType;
2008 if (SecondArgType != null)
2011 Parameter [] param_list = new Parameter [length];
2013 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2016 "User defined operators `" +
2017 Prototype (parent) +
2018 "' must be declared static and public");
2021 param_list[0] = new Parameter (FirstArgType, FirstArgName,
2022 Parameter.Modifier.NONE, null);
2023 if (SecondArgType != null)
2024 param_list[1] = new Parameter (SecondArgType, SecondArgName,
2025 Parameter.Modifier.NONE, null);
2027 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
2028 new Parameters (param_list, null),
2029 OptAttributes, Location.Null);
2031 OperatorMethod.Define (parent);
2032 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
2034 Type [] param_types = OperatorMethod.ParameterTypes (parent);
2035 Type declaring_type = OperatorMethodBuilder.DeclaringType;
2036 Type return_type = OperatorMethod.GetReturnType (parent);
2037 Type first_arg_type = param_types [0];
2039 // Rules for conversion operators
2041 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2043 if (first_arg_type == return_type && first_arg_type == declaring_type)
2044 Report.Error (555, Location,
2045 "User-defined conversion cannot take an object of the enclosing type " +
2046 "and convert to an object of the enclosing type");
2048 if (first_arg_type != declaring_type && return_type != declaring_type)
2049 Report.Error (556, Location,
2050 "User-defined conversion must convert to or from the enclosing type");
2052 if (first_arg_type == TypeManager.object_type || return_type == TypeManager.object_type)
2053 Report.Error (-8, Location,
2054 "User-defined conversion cannot convert to or from object type");
2056 if (first_arg_type.IsInterface || return_type.IsInterface)
2057 Report.Error (-9, Location,
2058 "User-defined conversion cannot convert to or from an interface type");
2060 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type))
2061 Report.Error (-10, Location,
2062 "User-defined conversion cannot convert between types that " +
2063 "derive from each other");
2065 } else if (SecondArgType == null) {
2066 // Checks for Unary operators
2068 if (first_arg_type != declaring_type)
2069 Report.Error (562, Location,
2070 "The parameter of a unary operator must be the containing type");
2073 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2074 if (return_type != declaring_type)
2075 Report.Error (559, Location,
2076 "The parameter and return type for ++ and -- " +
2077 "must be the containing type");
2081 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2082 if (return_type != TypeManager.bool_type)
2083 Report.Error (215, Location,
2084 "The return type of operator True or False " +
2089 // Checks for Binary operators
2091 if (first_arg_type != declaring_type &&
2092 param_types [1] != declaring_type)
2093 Report.Error (563, Location,
2094 "One of the parameters of a binary operator must be the containing type");
2101 public void Emit (TypeContainer parent)
2103 OperatorMethod.Block = Block;
2104 OperatorMethod.Emit (parent);
2111 // This is used to compare method signatures
2113 struct MethodSignature {
2115 public Type RetType;
2116 public Type [] Parameters;
2118 public MethodSignature (string name, Type ret_type, Type [] parameters)
2122 Parameters = parameters;
2124 if (parameters != null){
2125 if (parameters.Length == 0)
2130 public override int GetHashCode ()
2132 return Name.GetHashCode ();
2135 public override bool Equals (Object o)
2137 MethodSignature other = (MethodSignature) o;
2139 if (other.Name != Name)
2142 if (other.RetType != RetType)
2145 if (Parameters == null){
2146 if (other.Parameters == null)
2151 if (other.Parameters == null)
2154 int c = Parameters.Length;
2155 if (other.Parameters.Length != c)
2158 for (int i = 0; i < c; i++)
2159 if (other.Parameters [i] != Parameters [i])