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;
17 namespace Mono.CSharp {
20 /// This is the base class for structs and classes.
22 public class TypeContainer : DeclSpace {
23 // Holds a list of classes and structures
26 // Holds the list of properties
29 // Holds the list of enumerations
32 // Holds the list of delegates
35 // Holds the list of constructors
36 ArrayList instance_constructors;
38 // Holds the list of fields
41 // Holds a list of fields that have initializers
42 ArrayList initialized_fields;
44 // Holds a list of static fields that have initializers
45 ArrayList initialized_static_fields;
47 // Holds the list of constants
62 // Holds the operators
66 // Pointers to the default constructor and the default static constructor
68 Constructor default_constructor;
69 Constructor default_static_constructor;
72 // Whether we have seen a static constructor for this class or not
74 bool have_static_constructor = false;
77 // This one is computed after we can distinguish interfaces
78 // from classes from the arraylist `type_bases'
80 string base_class_name;
84 // Attributes for this type
85 protected Attributes attributes;
87 // Information in the case we are an attribute type
89 public AttributeTargets Targets;
90 public bool AllowMultiple;
91 public bool Inherited;
94 public TypeContainer (TypeContainer parent, string name, Location l)
95 : base (parent, name, l)
98 types = new ArrayList ();
105 base_class_name = null;
107 //Console.WriteLine ("New class " + name + " inside " + n);
110 public AdditionResult AddConstant (Const constant)
113 string name = constant.Name;
115 if ((res = IsValid (name)) != AdditionResult.Success)
118 if (constants == null)
119 constants = new ArrayList ();
121 constants.Add (constant);
122 DefineName (name, constant);
124 return AdditionResult.Success;
127 public AdditionResult AddEnum (Mono.CSharp.Enum e)
130 string name = e.Name;
132 if ((res = IsValid (name)) != AdditionResult.Success)
136 enums = new ArrayList ();
139 DefineName (name, e);
141 return AdditionResult.Success;
144 public AdditionResult AddClass (Class c)
147 string name = c.Name;
150 if ((res = IsValid (name)) != AdditionResult.Success)
153 DefineName (name, c);
156 return AdditionResult.Success;
159 public AdditionResult AddStruct (Struct s)
162 string name = s.Name;
164 if ((res = IsValid (name)) != AdditionResult.Success)
167 DefineName (name, s);
170 return AdditionResult.Success;
173 public AdditionResult AddDelegate (Delegate d)
176 string name = d.Name;
178 if ((res = IsValid (name)) != AdditionResult.Success)
181 if (delegates == null)
182 delegates = new ArrayList ();
184 DefineName (name, d);
187 return AdditionResult.Success;
190 public AdditionResult AddMethod (Method method)
192 string name = method.Name;
193 Object value = defined_names [name];
195 if (value != null && (!(value is Method)))
196 return AdditionResult.NameExists;
199 methods = new ArrayList ();
201 methods.Add (method);
203 DefineName (name, method);
205 return AdditionResult.Success;
208 public AdditionResult AddConstructor (Constructor c)
210 if (c.Name != Basename)
211 return AdditionResult.NotAConstructor;
213 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
216 have_static_constructor = true;
217 if (default_static_constructor != null){
218 Console.WriteLine ("I have a static constructor already");
219 Console.WriteLine (" " + default_static_constructor);
220 return AdditionResult.MethodExists;
223 default_static_constructor = c;
226 if (default_constructor != null)
227 return AdditionResult.MethodExists;
228 default_constructor = c;
231 if (instance_constructors == null)
232 instance_constructors = new ArrayList ();
234 instance_constructors.Add (c);
237 return AdditionResult.Success;
240 public AdditionResult AddInterface (Interface iface)
243 string name = iface.Name;
245 if ((res = IsValid (name)) != AdditionResult.Success)
248 if (interfaces == null)
249 interfaces = new ArrayList ();
250 interfaces.Add (iface);
251 DefineName (name, iface);
253 return AdditionResult.Success;
256 public AdditionResult AddField (Field field)
259 string name = field.Name;
261 if ((res = IsValid (name)) != AdditionResult.Success)
265 fields = new ArrayList ();
268 if (field.Initializer != null){
269 if ((field.ModFlags & Modifiers.STATIC) != 0){
270 if (initialized_static_fields == null)
271 initialized_static_fields = new ArrayList ();
273 initialized_static_fields.Add (field);
276 // We have not seen a static constructor,
277 // but we will provide static initialization of fields
279 have_static_constructor = true;
281 if (initialized_fields == null)
282 initialized_fields = new ArrayList ();
284 initialized_fields.Add (field);
288 DefineName (name, field);
289 return AdditionResult.Success;
292 public AdditionResult AddProperty (Property prop)
295 string name = prop.Name;
297 if ((res = IsValid (name)) != AdditionResult.Success)
300 if (properties == null)
301 properties = new ArrayList ();
303 properties.Add (prop);
304 DefineName (name, prop);
306 return AdditionResult.Success;
309 public AdditionResult AddEvent (Event e)
312 string name = e.Name;
314 if ((res = IsValid (name)) != AdditionResult.Success)
318 events = new ArrayList ();
321 DefineName (name, e);
323 return AdditionResult.Success;
326 public AdditionResult AddIndexer (Indexer i)
328 if (indexers == null)
329 indexers = new ArrayList ();
333 return AdditionResult.Success;
336 public AdditionResult AddOperator (Operator op)
338 if (operators == null)
339 operators = new ArrayList ();
343 return AdditionResult.Success;
346 public ArrayList Types {
352 public ArrayList Methods {
358 public ArrayList Constants {
364 public ArrayList Interfaces {
372 return base_class_name;
376 public ArrayList Bases {
386 public ArrayList Fields {
392 public ArrayList InstanceConstructors {
394 return instance_constructors;
398 public ArrayList Properties {
404 public ArrayList Events {
410 public ArrayList Enums {
416 public ArrayList Indexers {
422 public ArrayList Operators {
428 public ArrayList Delegates {
434 public Attributes OptAttributes {
441 // root_types contains all the types. All TopLevel types
442 // hence have a parent that points to `root_types', that is
443 // why there is a non-obvious test down here.
445 public bool IsTopLevel {
448 if (Parent.Parent == null)
455 public bool HaveStaticConstructor {
457 return have_static_constructor;
461 public virtual TypeAttributes TypeAttr {
463 return Modifiers.TypeAttr (ModFlags, this);
468 // Emits the instance field initializers
470 public bool EmitFieldInitializers (EmitContext ec, bool is_static)
473 ILGenerator ig = ec.ig;
476 fields = initialized_static_fields;
478 fields = initialized_fields;
483 foreach (Field f in fields){
484 Object init = f.Initializer;
487 if (init is Expression)
488 e = (Expression) init;
490 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
491 string rank = f.Type.Substring (f.Type.IndexOf ("["));
492 e = new ArrayCreation (base_type, rank, (ArrayList) init, f.Location);
500 ig.Emit (OpCodes.Ldarg_0);
505 ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
507 ig.Emit (OpCodes.Stfld, f.FieldBuilder);
515 // Defines the default constructors
517 void DefineDefaultConstructor (bool is_static)
522 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
523 new ConstructorBaseInitializer (null, new Location (-1)),
527 mods = Modifiers.STATIC;
533 c.Block = new Block (null);
537 public void ReportStructInitializedInstanceError ()
539 string n = TypeBuilder.FullName;
541 foreach (Field f in initialized_fields){
544 "`" + n + "." + f.Name + "': can not have " +
545 "instance field initializers in structs");
549 struct TypeAndMethods {
551 public MethodInfo [] methods;
553 // Far from ideal, but we want to avoid creating a copy
555 public Type [][] args;
558 // This flag on the method says `We found a match, but
559 // because it was private, we could not use the match
561 public bool [] found;
565 // This array keeps track of the pending implementations
567 TypeAndMethods [] pending_implementations;
570 // Registers the required method implementations for this class
572 // Register method implementations are either abstract methods
573 // flagged as such on the base class or interface methods
575 public void RegisterRequiredImplementations ()
577 Type [] ifaces = TypeBuilder.GetInterfaces ();
578 Type b = TypeBuilder.BaseType;
582 icount = ifaces.Length;
587 pending_implementations = new TypeAndMethods [icount + (b.IsAbstract ? 1 : 0)];
591 foreach (Type t in ifaces){
594 if (t is TypeBuilder){
597 iface = RootContext.TypeManager.LookupInterface (t);
599 mi = iface.GetMethods ();
601 mi = t.GetMethods ();
603 int count = mi.Length;
604 pending_implementations [i].type = t;
605 pending_implementations [i].methods = mi;
606 pending_implementations [i].args = new Type [count][];
607 pending_implementations [i].found = new bool [count];
610 foreach (MethodInfo m in mi){
611 Type [] types = TypeManager.GetArgumentTypes (m);
613 pending_implementations [i].args [j] = types;
621 MemberInfo [] abstract_methods;
623 abstract_methods = FindMembers (
624 TypeBuilder.BaseType,
625 MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
626 abstract_method_filter, null);
628 if (abstract_methods != null){
629 int count = abstract_methods.Length;
630 pending_implementations [i].methods = new MethodInfo [count];
632 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
633 pending_implementations [i].found = new bool [count];
634 pending_implementations [i].args = new Type [count][];
635 pending_implementations [i].type = TypeBuilder;
638 foreach (MemberInfo m in abstract_methods){
639 MethodInfo mi = (MethodInfo) m;
641 Type [] types = TypeManager.GetArgumentTypes (mi);
643 pending_implementations [i].args [j] = types;
651 public static string MakeFQN (string nsn, string name)
653 string prefix = (nsn == "" ? "" : nsn + ".");
655 return prefix + name;
658 Type LookupInterfaceOrClass (object builder, string ns, string name, bool is_class, out bool error)
660 TypeContainer parent;
664 name = MakeFQN (ns, name);
666 t = RootContext.TypeManager.LookupType (name);
671 parent = (Class) RootContext.Tree.Classes [name];
673 parent = (Struct) RootContext.Tree.Structs [name];
677 t = parent.DefineType (builder);
679 Report.Error (146, "Class definition is circular: `"+name+"'");
691 // returns the type for an interface or a class, this will recursively
692 // try to define the types that it depends on.
694 Type GetInterfaceOrClass (object builder, string name, bool is_class)
700 // Attempt to lookup the class on our namespace
702 t = LookupInterfaceOrClass (builder, Namespace.Name, name, is_class, out error);
710 // Attempt to do a direct unqualified lookup
712 t = LookupInterfaceOrClass (builder, "", name, is_class, out error);
720 // Attempt to lookup the class on any of the `using'
724 for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
725 ArrayList using_list = ns.UsingTable;
727 if (using_list == null)
730 foreach (string n in using_list){
731 t = LookupInterfaceOrClass (builder, n, name, is_class, out error);
740 Report.Error (246, "Can not find type `"+name+"'");
745 /// This function computes the Base class and also the
746 /// list of interfaces that the class or struct @c implements.
748 /// The return value is an array (might be null) of
749 /// interfaces implemented (as Types).
751 /// The @parent argument is set to the parent object or null
752 /// if this is `System.Object'.
754 Type [] GetClassBases (object builder, bool is_class, out Type parent, out bool error)
756 ArrayList bases = Bases;
765 parent = TypeManager.value_type;
769 if (RootContext.StdLib)
770 parent = TypeManager.object_type;
771 else if (Name != "System.Object")
772 parent = TypeManager.object_type;
775 // If we are compiling our runtime,
776 // and we are defining ValueType, then our
777 // parent is `System.Object'.
779 if (!RootContext.StdLib && Name == "System.ValueType")
780 parent = TypeManager.object_type;
787 // Bases should be null if there are no bases at all
792 string name = (string) bases [0];
793 Type first = GetInterfaceOrClass (builder, name, is_class);
804 parent = TypeManager.object_type;
811 Type [] ifaces = new Type [count-start];
813 for (i = start, j = 0; i < count; i++, j++){
814 string name = (string) bases [i];
815 Type t = GetInterfaceOrClass (builder, name, is_class);
822 if (is_class == false && !t.IsInterface){
823 Report.Error (527, "In Struct `" + Name + "', type `"+
824 name +"' is not an interface");
833 detail = " (a class can not inherit from a struct)";
835 Report.Error (509, "class `"+ Name +
836 "': Cannot inherit from sealed class `"+
837 bases [i]+"'"+detail);
844 Report.Error (527, "In Class `" + Name + "', type `"+
845 name+"' is not an interface");
858 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
860 public TypeBuilder DefineType (object parent_builder)
867 if (TypeBuilder != null)
880 ifaces = GetClassBases (parent_builder, is_class, out parent, out error);
885 if (parent_builder is ModuleBuilder) {
886 ModuleBuilder builder = (ModuleBuilder) parent_builder;
888 // Structs with no fields need to have a ".size 1"
892 if (!is_class && Fields == null)
893 TypeBuilder = builder.DefineType (Name,
896 PackingSize.Unspecified, 1);
899 // classes or structs with fields
901 TypeBuilder = builder.DefineType (Name,
906 TypeBuilder builder = (System.Reflection.Emit.TypeBuilder) parent_builder;
909 // Structs with no fields need to have a ".size 1"
912 if (!is_class && Fields == null)
913 TypeBuilder = builder.DefineNestedType (Basename,
916 PackingSize.Unspecified);
919 // classes or structs with fields
921 TypeBuilder = builder.DefineNestedType (Basename,
927 RootContext.TypeManager.AddUserType (Name, TypeBuilder, this);
928 RootContext.RegisterOrder (this);
931 foreach (TypeContainer tc in Types)
932 tc.DefineType (TypeBuilder);
935 if (Delegates != null) {
936 foreach (Delegate d in Delegates)
937 d.DefineDelegate (TypeBuilder);
941 foreach (Enum en in Enums)
942 en.DefineEnum (TypeBuilder);
951 /// Defines the MemberCore objects that are in the `list' Arraylist
953 /// The `defined_names' array contains a list of members defined in
956 static ArrayList remove_list = new ArrayList ();
957 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
961 remove_list.Clear ();
963 foreach (MemberCore mc in list){
964 if (!mc.Define (this)){
965 remove_list.Add (mc);
969 if (defined_names == null)
972 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
975 if (RootContext.WarningLevel >= 4){
976 if ((mc.ModFlags & Modifiers.NEW) != 0)
977 Report109 (mc.Location, mc);
982 if (defined_names [idx] is PropertyInfo &&
983 ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
987 #if WANT_TO_VERIFY_SIGNATURES_HERE
988 if (defined_names [idx] is MethodBase && mc is MethodCore){
989 MethodBase mb = (MethodBase) defined_names [idx];
990 MethodCore met = (MethodCore) mc;
992 if ((mb.IsVirtual || mb.IsAbstract) &&
993 (mc.ModFlags & Modifiers.OVERRIDE) != 0)
997 // FIXME: Compare the signatures here. If they differ,
1001 Report108 (mc.Location, defined_names [idx]);
1004 foreach (object o in remove_list)
1007 remove_list.Clear ();
1011 /// Populates our TypeBuilder with fields and methods
1013 public override bool Define (TypeContainer parent)
1015 MemberInfo [] defined_names = null;
1017 if (RootContext.WarningLevel > 1){
1021 // This code throws an exception in the comparer
1022 // I guess the string is not an object?
1024 ptype = TypeBuilder.BaseType;
1026 defined_names = FindMembers (
1027 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1028 BindingFlags.Public | BindingFlags.Instance |
1029 BindingFlags.Static, null, null);
1031 Array.Sort (defined_names, mif_compare);
1035 if (constants != null)
1036 DefineMembers (constants, defined_names);
1039 DefineMembers (fields, defined_names);
1042 if (instance_constructors == null){
1043 if (default_constructor == null)
1044 DefineDefaultConstructor (false);
1047 if (initialized_static_fields != null &&
1048 default_static_constructor == null)
1049 DefineDefaultConstructor (true);
1052 if (this is Struct){
1054 // Structs can not have initialized instance
1057 if (initialized_static_fields != null &&
1058 default_static_constructor == null)
1059 DefineDefaultConstructor (true);
1061 if (initialized_fields != null)
1062 ReportStructInitializedInstanceError ();
1065 RegisterRequiredImplementations ();
1068 // Constructors are not in the defined_names array
1070 if (instance_constructors != null)
1071 DefineMembers (instance_constructors, null);
1073 if (default_static_constructor != null)
1074 default_static_constructor.Define (this);
1076 if (methods != null)
1077 DefineMembers (methods, null);
1079 if (properties != null)
1080 DefineMembers (properties, defined_names);
1083 DefineMembers (events, defined_names);
1085 if (indexers != null) {
1086 foreach (Indexer i in Indexers)
1090 if (operators != null)
1091 DefineMembers (operators, null);
1094 DefineMembers (enums, defined_names);
1096 if (delegates != null)
1097 DefineMembers (delegates, defined_names);
1103 /// Looks up the alias for the name
1105 public string LookupAlias (string name)
1107 if (Namespace != null)
1108 return Namespace.LookupAlias (name);
1114 /// This function is based by a delegate to the FindMembers routine
1116 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1121 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
1123 MethodInfo mi = (MethodInfo) m;
1125 return mi.IsAbstract;
1129 /// This filter is used by FindMembers, and we just keep
1130 /// a global for the filter to `AlwaysAccept'
1132 static MemberFilter accepting_filter;
1135 /// This delegate is a MemberFilter used to extract the
1136 /// abstact methods from a type.
1138 static MemberFilter abstract_method_filter;
1141 /// A member comparission method based on name only
1143 static IComparer mif_compare;
1145 static TypeContainer ()
1147 abstract_method_filter = new MemberFilter (IsAbstractMethod);
1148 accepting_filter = new MemberFilter (AlwaysAccept);
1149 mif_compare = new MemberInfoCompare ();
1153 /// This method returns the members of this type just like Type.FindMembers would
1154 /// Only, we need to use this for types which are _being_ defined because MS'
1155 /// implementation can't take care of that.
1158 // FIXME: return an empty static array instead of null, that cleans up
1159 // some code and is consistent with some coding conventions I just found
1161 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1162 MemberFilter filter, object criteria)
1164 ArrayList members = new ArrayList ();
1167 filter = accepting_filter;
1169 if ((mt & MemberTypes.Field) != 0) {
1170 if (Fields != null) {
1171 foreach (Field f in Fields) {
1172 FieldBuilder fb = f.FieldBuilder;
1173 if (filter (fb, criteria) == true)
1178 if (Constants != null) {
1179 foreach (Const con in Constants) {
1180 FieldBuilder fb = con.FieldBuilder;
1181 if (filter (fb, criteria) == true)
1187 if ((mt & MemberTypes.Method) != 0) {
1188 if (Methods != null) {
1189 foreach (Method m in Methods) {
1190 MethodBuilder mb = m.MethodBuilder;
1192 // If we are in transit, ignore
1193 // This case arises when we are still defining a PInvoke method
1194 // and we hit FindMembers because of the need to resolve named
1195 // arguments inside of Attribute.DefinePInvokeMethod
1199 if (filter (mb, criteria) == true)
1204 if (Operators != null){
1205 foreach (Operator o in Operators) {
1206 MethodBuilder ob = o.OperatorMethodBuilder;
1208 if (filter (ob, criteria) == true)
1214 if ((mt & MemberTypes.Event) != 0) {
1216 foreach (Event e in Events) {
1217 if (filter (e.EventBuilder, criteria) == true)
1218 members.Add (e.EventBuilder);
1222 if ((mt & MemberTypes.Property) != 0){
1223 if (Properties != null)
1224 foreach (Property p in Properties) {
1225 if (filter (p.PropertyBuilder, criteria) == true) {
1226 members.Add (p.PropertyBuilder);
1230 if (Indexers != null)
1231 foreach (Indexer ix in Indexers) {
1232 if (filter (ix.PropertyBuilder, criteria) == true) {
1233 members.Add (ix.PropertyBuilder);
1238 if ((mt & MemberTypes.NestedType) != 0) {
1241 foreach (TypeContainer t in Types)
1242 if (filter (t.TypeBuilder, criteria) == true)
1243 members.Add (t.TypeBuilder);
1246 foreach (Enum en in Enums)
1247 if (filter (en.TypeBuilder, criteria) == true)
1248 members.Add (en.TypeBuilder);
1252 if ((mt & MemberTypes.Constructor) != 0){
1253 if (instance_constructors != null){
1254 foreach (Constructor c in instance_constructors){
1255 ConstructorBuilder cb = c.ConstructorBuilder;
1257 if (filter (cb, criteria) == true)
1262 if (default_static_constructor != null){
1263 ConstructorBuilder cb =
1264 default_static_constructor.ConstructorBuilder;
1266 if (filter (cb, criteria) == true)
1272 // Lookup members in parent if requested.
1274 if ((bf & BindingFlags.DeclaredOnly) == 0){
1277 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1279 members.AddRange (mi);
1282 int count = members.Count;
1284 MemberInfo [] mi = new MemberInfo [count];
1285 members.CopyTo (mi);
1292 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1294 EventInfo ei = event_expr.EventInfo;
1296 foreach (Event e in events) {
1298 if (e.FieldBuilder == null)
1301 if (Type.FilterName (e.FieldBuilder, ei.Name))
1302 return e.FieldBuilder;
1308 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1309 MemberFilter filter, object criteria)
1311 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1314 return tc.FindMembers (mt, bf, filter, criteria);
1316 return t.FindMembers (mt, bf, filter, criteria);
1320 /// Whether the specified method is an interface method implementation
1324 /// If a method in Type `t' (or null to look in all interfaces
1325 /// and the base abstract class) with name `Name', return type `ret_type' and
1326 /// arguments `args' implements an interface, this method will
1327 /// return the MethodInfo that this method implements.
1329 /// This will remove the method from the list of "pending" methods
1330 /// that are required to be implemented for this class as a side effect.
1333 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1336 if (pending_implementations == null)
1339 foreach (TypeAndMethods tm in pending_implementations){
1340 if (!(t == null || tm.type == t))
1344 foreach (MethodInfo m in tm.methods){
1350 if (Name != m.Name){
1355 if (ret_type != m.ReturnType){
1361 if (tm.args [i] == null || tm.args [i].Length == 0){
1363 tm.methods [i] = null;
1364 tm.found [i] = true;
1371 if (tm.args == null){
1372 Console.WriteLine ("Type: " + tm.type);
1373 Console.WriteLine ("method: " + tm.methods [i]);
1376 if (tm.args [i] == null){
1382 // Check if we have the same parameters
1384 if (tm.args [i].Length != args.Length){
1389 int j, top = args.Length;
1392 for (j = 0; j < top; j++){
1393 if (tm.args [i][j] != args[j]){
1404 tm.methods [i] = null;
1405 tm.found [i] = true;
1409 // If a specific type was requested, we can stop now.
1417 /// Verifies that any pending abstract methods or interface methods
1418 /// were implemented.
1420 bool VerifyPendingMethods ()
1422 int top = pending_implementations.Length;
1423 bool errors = false;
1426 for (i = 0; i < top; i++){
1427 Type type = pending_implementations [i].type;
1430 foreach (MethodInfo mi in pending_implementations [i].methods){
1434 if (type.IsInterface){
1437 if (pending_implementations [i].found [j])
1438 extra = ". (method might be private or static)";
1441 "`" + Name + "' does not implement " +
1442 "interface member `" +
1443 type.FullName + "." + mi.Name + "'" + extra);
1447 "`" + Name + "' does not implement " +
1448 "inherited abstract member `" +
1449 type.FullName + "." + mi.Name + "'");
1459 /// Emits the values for the constants
1461 public void EmitConstants ()
1463 if (constants != null)
1464 foreach (Const con in constants)
1465 con.EmitConstant (this);
1470 /// Emits the code, this step is performed after all
1471 /// the types, enumerations, constructors
1475 if (instance_constructors != null)
1476 foreach (Constructor c in instance_constructors)
1479 if (default_static_constructor != null)
1480 default_static_constructor.Emit (this);
1482 if (methods != null)
1483 foreach (Method m in methods)
1486 if (operators != null)
1487 foreach (Operator o in operators)
1490 if (properties != null)
1491 foreach (Property p in properties)
1494 if (indexers != null) {
1495 foreach (Indexer ix in indexers)
1498 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1500 TypeBuilder.SetCustomAttribute (cb);
1504 foreach (Field f in fields)
1507 if (events != null){
1508 foreach (Event e in Events)
1512 if (pending_implementations != null)
1513 if (!VerifyPendingMethods ())
1516 EmitContext ec = new EmitContext (
1517 this, Mono.CSharp.Location.Null, null, null,
1520 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1522 // if (types != null)
1523 // foreach (TypeContainer tc in types)
1527 public override void CloseType ()
1532 TypeBuilder.CreateType ();
1534 } catch (TypeLoadException){
1536 // This is fine, the code still created the type
1538 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1539 // Console.WriteLine (e.Message);
1543 foreach (Enum en in Enums)
1547 foreach (TypeContainer tc in Types)
1551 foreach (TypeContainer tc in Types)
1552 if (!(tc is Struct))
1556 if (Delegates != null)
1557 foreach (Delegate d in Delegates)
1561 public string MakeName (string n)
1563 return "`" + Name + "." + n + "'";
1566 public void Report108 (Location l, MemberInfo mi)
1569 108, l, "The keyword new is required on " +
1570 MakeName (mi.Name) + " because it hides `" +
1571 mi.ReflectedType.Name + "." + mi.Name + "'");
1574 public void Report109 (Location l, MemberCore mc)
1577 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1578 "inherited member, the keyword new is not required");
1581 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1587 // Performs the validation on a Method's modifiers (properties have
1588 // the same properties).
1590 public bool MethodModifiersValid (int flags, string n, Location loc)
1592 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1593 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1595 string name = MakeName (n);
1598 // At most one of static, virtual or override
1600 if ((flags & Modifiers.STATIC) != 0){
1601 if ((flags & vao) != 0){
1603 112, loc, "static method " + name + "can not be marked " +
1604 "as virtual, abstract or override");
1609 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1612 " marked as override cannot be marked as new or virtual");
1617 // If the declaration includes the abstract modifier, then the
1618 // declaration does not include static, virtual or extern
1620 if ((flags & Modifiers.ABSTRACT) != 0){
1621 if ((flags & Modifiers.EXTERN) != 0){
1623 180, loc, name + " can not be both abstract and extern");
1627 if ((flags & Modifiers.VIRTUAL) != 0){
1629 503, loc, name + " can not be both abstract and virtual");
1633 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1636 " is abstract but its container class is not");
1642 if ((flags & Modifiers.PRIVATE) != 0){
1643 if ((flags & vao) != 0){
1646 " virtual or abstract members can not be private");
1651 if ((flags & Modifiers.SEALED) != 0){
1652 if ((flags & Modifiers.OVERRIDE) == 0){
1655 " cannot be sealed because it is not an override");
1664 // Returns true if `type' is as accessible as the flags `flags'
1665 // given for this member
1667 static public bool AsAccessible (Type type, int flags)
1669 // FIXME: Implement me
1674 public class Class : TypeContainer {
1676 // Modifiers allowed in a class declaration
1678 public const int AllowedModifiers =
1681 Modifiers.PROTECTED |
1682 Modifiers.INTERNAL |
1684 Modifiers.ABSTRACT |
1687 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1688 : base (parent, name, l)
1692 if (parent.Parent == null)
1693 accmods = Modifiers.INTERNAL;
1695 accmods = Modifiers.PRIVATE;
1697 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods);
1698 this.attributes = attrs;
1702 // FIXME: How do we deal with the user specifying a different
1705 public override TypeAttributes TypeAttr {
1707 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1712 public class Struct : TypeContainer {
1714 // Modifiers allowed in a struct declaration
1716 public const int AllowedModifiers =
1719 Modifiers.PROTECTED |
1720 Modifiers.INTERNAL |
1723 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1724 : base (parent, name, l)
1728 if (parent.Parent == null)
1729 accmods = Modifiers.INTERNAL;
1731 accmods = Modifiers.PRIVATE;
1733 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods);
1735 this.ModFlags |= Modifiers.SEALED;
1736 this.attributes = attrs;
1741 // FIXME: Allow the user to specify a different set of attributes
1742 // in some cases (Sealed for example is mandatory for a class,
1743 // but what SequentialLayout can be changed
1745 public override TypeAttributes TypeAttr {
1747 return base.TypeAttr |
1748 TypeAttributes.SequentialLayout |
1749 TypeAttributes.Sealed |
1750 TypeAttributes.BeforeFieldInit;
1755 public abstract class MethodCore : MemberCore {
1756 public readonly Parameters Parameters;
1760 // Parameters, cached for semantic analysis.
1762 InternalParameters parameter_info;
1764 public MethodCore (string name, Parameters parameters, Location l)
1768 Parameters = parameters;
1772 // Returns the System.Type array for the parameters of this method
1774 Type [] parameter_types;
1775 static Type [] no_types = new Type [0];
1776 public Type [] ParameterTypes (TypeContainer parent)
1778 if (Parameters == null)
1781 if (parameter_types == null)
1782 parameter_types = Parameters.GetParameterInfo (parent);
1784 return parameter_types;
1787 public InternalParameters ParameterInfo
1790 return parameter_info;
1794 parameter_info = value;
1798 public Block Block {
1808 public CallingConventions GetCallingConvention (bool is_class)
1810 CallingConventions cc = 0;
1812 cc = Parameters.GetCallingConvention ();
1815 if ((ModFlags & Modifiers.STATIC) == 0)
1816 cc |= CallingConventions.HasThis;
1818 // FIXME: How is `ExplicitThis' used in C#?
1824 public class Method : MethodCore {
1825 public readonly string ReturnType;
1826 public MethodBuilder MethodBuilder;
1827 public readonly Attributes OptAttributes;
1829 MethodAttributes flags;
1832 /// Modifiers allowed in a class declaration
1834 const int AllowedModifiers =
1837 Modifiers.PROTECTED |
1838 Modifiers.INTERNAL |
1843 Modifiers.OVERRIDE |
1844 Modifiers.ABSTRACT |
1848 // return_type can be "null" for VOID values.
1850 public Method (string return_type, int mod, string name, Parameters parameters,
1851 Attributes attrs, Location l)
1852 : base (name, parameters, l)
1854 ReturnType = return_type;
1855 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1856 OptAttributes = attrs;
1859 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1863 if (! (m is MethodInfo))
1866 MethodSignature sig = (MethodSignature) filter_criteria;
1868 if (m.Name != sig.Name)
1871 mi = (MethodInfo) m;
1873 if (mi.ReturnType != sig.RetType)
1876 Type [] args = TypeManager.GetArgumentTypes (mi);
1877 Type [] sigp = sig.Parameters;
1879 if (args.Length != sigp.Length)
1882 for (int i = args.Length; i > 0; ){
1884 if (args [i] != sigp [i])
1891 /// This delegate is used to extract methods which have the
1892 /// same signature as the argument
1894 static MemberFilter method_signature_filter;
1898 method_signature_filter = new MemberFilter (MemberSignatureCompare);
1903 // Returns the `System.Type' for the ReturnType of this
1904 // function. Provides a nice cache. (used between semantic analysis
1905 // and actual code generation
1907 Type type_return_type;
1909 public Type GetReturnType (TypeContainer parent)
1911 if (type_return_type == null)
1912 type_return_type = RootContext.LookupType (
1913 parent, ReturnType, false, Location);
1915 return type_return_type;
1918 void DuplicatEntryPoint (MethodInfo b)
1922 "Program `" + RootContext.CodeGen.FileName +
1923 "' has more than one entry point defined: `" +
1924 b.DeclaringType.Name + "." + b.Name + "'");
1930 public override bool Define (TypeContainer parent)
1932 Type ret_type = GetReturnType (parent);
1933 Type [] parameters = ParameterTypes (parent);
1935 MethodInfo implementing;
1936 Type iface_type = null;
1937 string iface = "", short_name;
1939 // Check if the return type and arguments were correct
1940 if (ret_type == null || parameters == null)
1943 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
1947 // verify accessibility
1949 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
1952 foreach (Type partype in parameters)
1953 if (!TypeContainer.AsAccessible (partype, ModFlags))
1960 // Verify if the parent has a type with the same name, and then
1961 // check whether we have to create a new slot for it or not.
1963 Type ptype = parent.TypeBuilder.BaseType;
1965 // ptype is only null for System.Object while compiling corlib.
1967 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1968 MemberInfo [] mi, mi_static, mi_instance;
1970 mi_static = TypeContainer.FindMembers (
1971 ptype, MemberTypes.Method,
1972 BindingFlags.Public | BindingFlags.Static, method_signature_filter,
1975 mi_instance = TypeContainer.FindMembers (
1976 ptype, MemberTypes.Method,
1977 BindingFlags.Public | BindingFlags.Instance, method_signature_filter,
1980 if (mi_instance != null && mi_instance.Length > 0){
1982 } else if (mi_static != null && mi_static.Length > 0)
1987 if (mi != null && mi.Length > 0){
1988 if (!CheckMethodAgainstBase (parent, (MethodInfo) mi [0])){
1992 if ((ModFlags & Modifiers.NEW) != 0)
1993 WarningNotHiding (parent);
1995 if ((ModFlags & Modifiers.OVERRIDE) != 0)
1996 Report.Error (115, Location,
1997 parent.MakeName (Name) +
1998 " no suitable methods found to override");
2000 } else if ((ModFlags & Modifiers.NEW) != 0)
2001 WarningNotHiding (parent);
2004 // If we implement an interface, extract the interface name.
2006 flags = Modifiers.MethodAttr (ModFlags);
2008 if (Name.IndexOf (".") != -1){
2009 int pos = Name.LastIndexOf (".");
2010 iface = Name.Substring (0, pos);
2012 iface_type = RootContext.LookupType (parent, iface, false, Location);
2013 short_name = Name.Substring (pos + 1);
2015 if (iface_type == null)
2018 // Compute the full name that we need to export
2019 Name = iface_type.FullName + "." + short_name;
2024 // Check if we are an implementation of an interface method or
2027 implementing = parent.IsInterfaceMethod (
2028 iface_type, short_name, ret_type, parameters, false);
2031 // For implicit implementations, make sure we are public, for
2032 // explicit implementations, make sure we are private.
2034 if (implementing != null){
2036 // Setting null inside this block will trigger a more
2037 // verbose error reporting for missing interface implementations
2039 // The "candidate" function has been flagged already
2040 // but it wont get cleared
2042 if (iface_type == null){
2043 if ((ModFlags & Modifiers.PUBLIC) == 0)
2044 implementing = null;
2046 if ((ModFlags & Modifiers.STATIC) != 0)
2047 implementing = null;
2049 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2051 106, Location, "`public' or `abstract' modifiers "+
2052 "are not allowed in explicit interface declarations"
2054 implementing = null;
2060 // If implementing is still valid, set flags
2062 if (implementing != null){
2064 MethodAttributes.Virtual |
2065 MethodAttributes.NewSlot |
2066 MethodAttributes.HideBySig;
2068 // If not abstract, then we can set Final.
2069 if (((flags & MethodAttributes.Abstract) == 0) &&
2070 implementing.DeclaringType.IsInterface)
2071 flags |= MethodAttributes.Final;
2076 parent.IsInterfaceMethod (
2077 iface_type, short_name, ret_type, parameters, true);
2080 Attribute dllimport_attr = null;
2081 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2082 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2083 if (asec.Attributes == null)
2086 foreach (Attribute a in asec.Attributes)
2087 if (a.Name.IndexOf ("DllImport") != -1) {
2088 flags |= MethodAttributes.PinvokeImpl;
2095 // Finally, define the method
2098 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2099 EmitContext ec = new EmitContext (
2100 parent, Location, null, GetReturnType (parent), ModFlags);
2102 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2103 ec, parent.TypeBuilder,
2104 Name, flags, ret_type, parameters);
2106 MethodBuilder = parent.TypeBuilder.DefineMethod (
2108 GetCallingConvention (parent is Class),
2109 ret_type, parameters);
2111 if (implementing != null){
2112 parent.TypeBuilder.DefineMethodOverride (
2113 MethodBuilder, implementing);
2117 if (MethodBuilder == null)
2121 // HACK because System.Reflection.Emit is lame
2123 ParameterInfo = new InternalParameters (parent, Parameters);
2125 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2129 "Class `" + parent.Name + "' already contains a definition with " +
2130 " the same return value and parameter types for method `" +
2136 // This is used to track the Entry Point,
2138 // FIXME: Allow pluggable entry point, check arguments, etc.
2140 if (Name == "Main" &&
2141 ((ModFlags & Modifiers.STATIC) != 0) &&
2142 (RootContext.MainClass == null ||
2143 RootContext.MainClass == parent.TypeBuilder.FullName)){
2144 if (RootContext.EntryPoint != null){
2145 DuplicatEntryPoint (MethodBuilder);
2146 DuplicatEntryPoint (RootContext.EntryPoint);
2148 RootContext.EntryPoint = MethodBuilder;
2151 // FIXME: Verify that the method signature
2152 // is valid for an entry point, and report
2158 // Define each type attribute (in/out/ref) and
2159 // the argument names.
2161 Parameter [] p = Parameters.FixedParameters;
2165 for (i = 0; i < p.Length; i++)
2166 MethodBuilder.DefineParameter (
2167 i + 1, p [i].Attributes, p [i].Name);
2169 if (i != parameters.Length) {
2170 ParameterBuilder pb;
2172 Parameter array_param = Parameters.ArrayParameter;
2173 pb = MethodBuilder.DefineParameter (
2174 i + 1, array_param.Attributes,
2177 CustomAttributeBuilder a = new CustomAttributeBuilder (
2178 TypeManager.cons_param_array_attribute, new object [0]);
2180 pb.SetCustomAttribute (a);
2190 public void Emit (TypeContainer parent)
2192 if ((flags & MethodAttributes.PinvokeImpl) != 0)
2195 ILGenerator ig = MethodBuilder.GetILGenerator ();
2196 EmitContext ec = new EmitContext (parent, Location, ig,
2197 GetReturnType (parent), ModFlags);
2199 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2203 // abstract or extern methods have no bodies
2205 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2209 // Handle destructors specially
2211 // FIXME: This code generates buggy code
2213 if (Name == "Finalize" && type_return_type == TypeManager.void_type){
2214 Label end = ig.BeginExceptionBlock ();
2215 Label finish = ig.DefineLabel ();
2216 bool old_in_try = ec.InTry;
2218 ec.EmitTopBlock (Block, Location);
2219 ig.Emit (OpCodes.Leave, finish);
2220 ec.InTry = old_in_try;
2222 bool old_in_finally = ec.InFinally;
2223 ec.InFinally = true;
2224 ig.BeginFinallyBlock ();
2225 // throw new Exception ("IMPLEMENT BASE ACCESS!");
2226 // DONT FORGET TO SET THE EC VARIABLES.
2227 Console.WriteLine ("Implement base access here");
2229 ec.InFinally = old_in_finally;
2230 ig.EndExceptionBlock ();
2232 ec.EmitTopBlock (Block, Location);
2236 public abstract class ConstructorInitializer {
2237 ArrayList argument_list;
2238 ConstructorInfo parent_constructor;
2241 public ConstructorInitializer (ArrayList argument_list, Location location)
2243 this.argument_list = argument_list;
2244 this.location = location;
2247 public ArrayList Arguments {
2249 return argument_list;
2253 public bool Resolve (EmitContext ec)
2255 Expression parent_constructor_group;
2258 if (argument_list != null){
2259 for (int i = argument_list.Count; i > 0; ){
2262 Argument a = (Argument) argument_list [i];
2263 if (!a.Resolve (ec, location))
2268 if (this is ConstructorBaseInitializer)
2269 t = ec.TypeContainer.TypeBuilder.BaseType;
2271 t = ec.TypeContainer.TypeBuilder;
2273 parent_constructor_group = Expression.MemberLookup (
2274 ec, t, ".ctor", true,
2275 MemberTypes.Constructor,
2276 BindingFlags.Public | BindingFlags.Instance, location);
2278 if (parent_constructor_group == null){
2279 Console.WriteLine ("Could not find a constructor in our parent");
2283 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2284 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2286 if (parent_constructor == null){
2287 Console.WriteLine ("Could not locate a proper overload function");
2294 public void Emit (EmitContext ec)
2296 ec.ig.Emit (OpCodes.Ldarg_0);
2297 if (argument_list != null)
2298 Invocation.EmitArguments (ec, null, argument_list);
2299 ec.ig.Emit (OpCodes.Call, parent_constructor);
2303 public class ConstructorBaseInitializer : ConstructorInitializer {
2304 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2309 public class ConstructorThisInitializer : ConstructorInitializer {
2310 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2315 public class Constructor : MethodCore {
2316 public ConstructorBuilder ConstructorBuilder;
2317 public ConstructorInitializer Initializer;
2318 public Attributes OptAttributes;
2321 // Modifiers allowed for a constructor.
2323 const int AllowedModifiers =
2325 Modifiers.PROTECTED |
2326 Modifiers.INTERNAL |
2331 // The spec claims that static is not permitted, but
2332 // my very own code has static constructors.
2334 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2335 : base (name, args, l)
2341 // Returns true if this is a default constructor
2343 public bool IsDefault ()
2345 if ((ModFlags & Modifiers.STATIC) != 0)
2346 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2347 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2350 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2351 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2352 (Initializer is ConstructorBaseInitializer) &&
2353 (Initializer.Arguments == null);
2357 // Creates the ConstructorBuilder
2359 public override bool Define (TypeContainer parent)
2361 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2362 MethodAttributes.SpecialName);
2364 Type [] parameters = ParameterTypes (parent);
2366 if ((ModFlags & Modifiers.STATIC) != 0)
2367 ca |= MethodAttributes.Static;
2369 if (parent is Struct && parameters.Length == 0){
2372 "Structs can not contain explicit parameterless " +
2376 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2379 foreach (Type partype in parameters)
2380 if (!TypeContainer.AsAccessible (partype, ModFlags))
2383 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2384 ca, GetCallingConvention (parent is Class), parameters);
2387 // HACK because System.Reflection.Emit is lame
2389 ParameterInfo = new InternalParameters (parent, Parameters);
2391 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2394 "Class `" +parent.Name+ "' already contains a definition with the " +
2395 "same return value and parameter types for constructor `" + Name
2406 public void Emit (TypeContainer parent)
2408 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2409 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2411 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2412 if (Initializer == null)
2413 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2415 if (!Initializer.Resolve (ec)){
2416 Console.WriteLine ("Could not resolve initializer: " + parent.Name);
2421 // Classes can have base initializers and instance field initializers.
2423 if (parent is Class){
2424 if ((ModFlags & Modifiers.STATIC) == 0){
2425 Initializer.Emit (ec);
2426 parent.EmitFieldInitializers (ec, false);
2430 if ((ModFlags & Modifiers.STATIC) != 0)
2431 parent.EmitFieldInitializers (ec, true);
2433 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2435 ec.EmitTopBlock (Block, Location);
2439 public class Field : MemberCore {
2440 public readonly string Type;
2441 public readonly Object Initializer;
2442 public readonly Attributes OptAttributes;
2443 public FieldBuilder FieldBuilder;
2446 // Modifiers allowed in a class declaration
2448 const int AllowedModifiers =
2451 Modifiers.PROTECTED |
2452 Modifiers.INTERNAL |
2457 public Field (string type, int mod, string name, Object expr_or_array_init,
2458 Attributes attrs, Location loc)
2462 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
2463 Initializer = expr_or_array_init;
2464 OptAttributes = attrs;
2467 public override bool Define (TypeContainer parent)
2469 Type t = RootContext.LookupType (parent, Type, false, Location);
2474 if (!TypeContainer.AsAccessible (t, ModFlags))
2477 if (RootContext.WarningLevel > 1){
2478 Type ptype = parent.TypeBuilder.BaseType;
2480 // ptype is only null for System.Object while compiling corlib.
2484 mi = TypeContainer.FindMembers (
2485 ptype, MemberTypes.Method,
2486 BindingFlags.Public |
2487 BindingFlags.Static | BindingFlags.Instance,
2488 System.Type.FilterName, Name);
2492 FieldBuilder = parent.TypeBuilder.DefineField (
2493 Name, t, Modifiers.FieldAttr (ModFlags));
2498 public void Emit (TypeContainer tc)
2500 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
2502 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2506 public class Property : MemberCore {
2507 public readonly string Type;
2508 public Block Get, Set;
2509 public PropertyBuilder PropertyBuilder;
2510 public Attributes OptAttributes;
2511 MethodBuilder GetBuilder, SetBuilder;
2514 // The type, once we compute it.
2518 const int AllowedModifiers =
2521 Modifiers.PROTECTED |
2522 Modifiers.INTERNAL |
2526 Modifiers.OVERRIDE |
2527 Modifiers.ABSTRACT |
2530 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2531 Attributes attrs, Location loc)
2535 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2538 OptAttributes = attrs;
2542 // Checks our base implementation if any
2544 bool CheckBase (TypeContainer parent)
2547 // Find properties with the same name on the base class
2549 MemberInfo [] props;
2550 MemberInfo [] props_static = TypeContainer.FindMembers (
2551 parent.TypeBuilder.BaseType,
2552 MemberTypes.All, BindingFlags.Public | BindingFlags.Static,
2553 System.Type.FilterName, Name);
2555 MemberInfo [] props_instance = TypeContainer.FindMembers (
2556 parent.TypeBuilder.BaseType,
2557 MemberTypes.All, BindingFlags.Public | BindingFlags.Instance,
2558 System.Type.FilterName, Name);
2561 // Find if we have anything
2563 if (props_static != null && props_static.Length > 0)
2564 props = props_static;
2565 else if (props_instance != null && props_instance.Length > 0)
2566 props = props_instance;
2571 // If we have something on the base.
2572 if (props != null && props.Length > 0){
2575 // Currently we expect only to get 1 match at most from our
2576 // base class, maybe we can get more than one, investigate
2577 // whether this is possible
2579 if (props.Length > 1)
2580 throw new Exception ("How do we handle this?");
2582 PropertyInfo pi = (PropertyInfo) props [0];
2584 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2585 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2587 MethodInfo reference = inherited_get == null ?
2588 inherited_set : inherited_get;
2590 if (!CheckMethodAgainstBase (parent, reference))
2593 if ((ModFlags & Modifiers.NEW) != 0)
2594 WarningNotHiding (parent);
2596 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2597 Report.Error (115, Location,
2598 parent.MakeName (Name) +
2599 " no suitable methods found to override");
2606 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name, bool is_get)
2608 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
2609 Type [] parameters = null;
2610 MethodInfo implementing;
2614 flags |= MethodAttributes.HideBySig |
2615 MethodAttributes.SpecialName;
2618 fn_type = PropertyType;
2619 name = "get_" + short_name;
2621 name = "set_" + short_name;
2622 parameters = new Type [1];
2623 parameters [0] = PropertyType;
2624 fn_type = TypeManager.void_type;
2627 implementing = parent.IsInterfaceMethod (
2628 iface_type, name, fn_type, parameters, false);
2631 // For implicit implementations, make sure we are public, for
2632 // explicit implementations, make sure we are private.
2634 if (implementing != null){
2636 // Setting null inside this block will trigger a more
2637 // verbose error reporting for missing interface implementations
2639 // The "candidate" function has been flagged already
2640 // but it wont get cleared
2642 if (iface_type == null){
2643 if ((ModFlags & Modifiers.PUBLIC) == 0)
2644 implementing = null;
2645 if ((ModFlags & Modifiers.STATIC) != 0)
2646 implementing = null;
2648 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2650 106, Location, "`public' or `abstract' modifiers "+
2651 "are not allowed in explicit interface declarations"
2653 implementing = null;
2659 // If implementing is still valid, set flags
2661 if (implementing != null){
2663 MethodAttributes.Virtual |
2664 MethodAttributes.NewSlot |
2665 MethodAttributes.HideBySig;
2667 // If an interface implementation, then we can set Final.
2668 if (((flags & MethodAttributes.Abstract) == 0) &&
2669 implementing.DeclaringType.IsInterface)
2670 flags |= MethodAttributes.Final;
2673 // clear the pending flag
2675 parent.IsInterfaceMethod (
2676 iface_type, name, fn_type, parameters, true);
2680 GetBuilder = parent.TypeBuilder.DefineMethod (
2681 name, flags, PropertyType, null);
2682 PropertyBuilder.SetGetMethod (GetBuilder);
2684 if (implementing != null)
2685 parent.TypeBuilder.DefineMethodOverride (
2686 GetBuilder, implementing);
2689 // HACK because System.Reflection.Emit is lame
2691 InternalParameters ip = new InternalParameters (
2692 parent, Parameters.GetEmptyReadOnlyParameters ());
2694 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
2695 Report.Error (111, Location,
2696 "Class `" + parent.Name +
2697 "' already contains a definition with the " +
2698 "same return value and parameter types as the " +
2699 "'get' method of property `" + Name + "'");
2703 SetBuilder = parent.TypeBuilder.DefineMethod (
2704 name, flags, null, parameters);
2706 if (implementing != null)
2707 parent.TypeBuilder.DefineMethodOverride (
2708 SetBuilder, implementing);
2710 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2711 PropertyBuilder.SetSetMethod (SetBuilder);
2714 // HACK because System.Reflection.Emit is lame
2716 Parameter [] parms = new Parameter [1];
2717 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2718 InternalParameters ip = new InternalParameters (
2719 parent, new Parameters (parms, null, Location));
2721 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
2724 "Class `" + parent.Name +
2725 "' already contains a definition with the " +
2726 "same return value and parameter types as the " +
2727 "'set' method of property `" + Name + "'");
2735 public override bool Define (TypeContainer parent)
2737 Type iface_type = null;
2740 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2743 // Lookup Type, verify validity
2744 PropertyType = RootContext.LookupType (parent, Type, false, Location);
2745 if (PropertyType == null)
2748 // verify accessibility
2749 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
2752 if (!CheckBase (parent))
2756 // Check for explicit interface implementation
2758 if (Name.IndexOf (".") != -1){
2759 int pos = Name.LastIndexOf (".");
2760 string iface = Name.Substring (0, pos);
2762 iface_type = RootContext.LookupType (parent, iface, false, Location);
2763 if (iface_type == null)
2766 short_name = Name.Substring (pos + 1);
2768 // Compute the full name that we need to export.
2769 Name = iface_type.FullName + "." + short_name;
2773 // FIXME - PropertyAttributes.HasDefault ?
2775 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2776 PropertyAttributes.SpecialName;
2778 PropertyBuilder = parent.TypeBuilder.DefineProperty (
2779 Name, prop_attr, PropertyType, null);
2782 if (!DefineMethod (parent, iface_type, short_name, true))
2786 if (!DefineMethod (parent, iface_type, short_name, false))
2790 // HACK for the reasons exposed above
2792 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
2795 "Class `" + parent.Name +
2796 "' already contains a definition for the property `" +
2804 public void Emit (TypeContainer tc)
2809 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
2810 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
2814 // abstract or extern properties have no bodies
2816 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2820 ig = GetBuilder.GetILGenerator ();
2821 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
2823 ec.EmitTopBlock (Get, Location);
2827 ig = SetBuilder.GetILGenerator ();
2828 ec = new EmitContext (tc, Location, ig, null, ModFlags);
2830 ec.EmitTopBlock (Set, Location);
2837 /// Gigantic workaround for lameness in SRE follows :
2838 /// This class derived from EventInfo and attempts to basically
2839 /// wrap around the EventBuilder so that FindMembers can quickly
2840 /// return this in it search for members
2842 public class MyEventBuilder : EventInfo {
2845 // We use this to "point" to our Builder which is
2846 // not really a MemberInfo
2848 EventBuilder MyBuilder;
2851 // We "catch" and wrap these methods
2853 MethodInfo raise, remove, add;
2855 EventAttributes attributes;
2856 Type declaring_type, reflected_type, event_type;
2859 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
2861 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
2863 // And now store the values in our own fields.
2865 declaring_type = type_builder;
2867 // FIXME : This is supposed to be MyBuilder but since that doesn't
2868 // derive from Type, I have no clue what to do with this.
2869 reflected_type = null;
2871 attributes = event_attr;
2873 this.event_type = event_type;
2877 // Methods that you have to override. Note that you only need
2878 // to "implement" the variants that take the argument (those are
2879 // the "abstract" methods, the others (GetAddMethod()) are
2882 public override MethodInfo GetAddMethod (bool nonPublic)
2887 public override MethodInfo GetRemoveMethod (bool nonPublic)
2892 public override MethodInfo GetRaiseMethod (bool nonPublic)
2898 // These methods make "MyEventInfo" look like a Builder
2900 public void SetRaiseMethod (MethodBuilder raiseMethod)
2902 raise = raiseMethod;
2903 MyBuilder.SetRaiseMethod (raiseMethod);
2906 public void SetRemoveOnMethod (MethodBuilder removeMethod)
2908 remove = removeMethod;
2909 MyBuilder.SetRemoveOnMethod (removeMethod);
2912 public void SetAddOnMethod (MethodBuilder addMethod)
2915 MyBuilder.SetAddOnMethod (addMethod);
2918 public void SetCustomAttribute (CustomAttributeBuilder cb)
2920 MyBuilder.SetCustomAttribute (cb);
2923 public override object [] GetCustomAttributes (bool inherit)
2925 // FIXME : There's nothing which can be seemingly done here because
2926 // we have no way of getting at the custom attribute objects of the
2931 public override object [] GetCustomAttributes (Type t, bool inherit)
2933 // FIXME : Same here !
2937 public override bool IsDefined (Type t, bool b)
2942 public override EventAttributes Attributes {
2948 public override string Name {
2954 public override Type DeclaringType {
2956 return declaring_type;
2960 public override Type ReflectedType {
2962 return reflected_type;
2966 public Type EventType {
2973 public class Event : MemberCore {
2975 const int AllowedModifiers =
2978 Modifiers.PROTECTED |
2979 Modifiers.INTERNAL |
2984 Modifiers.OVERRIDE |
2987 public readonly string Type;
2988 public readonly Object Initializer;
2989 public readonly Block Add;
2990 public readonly Block Remove;
2991 public MyEventBuilder EventBuilder;
2992 public FieldBuilder FieldBuilder;
2993 public Attributes OptAttributes;
2996 MethodBuilder AddBuilder, RemoveBuilder;
2999 public Event (string type, string name, Object init, int flags, Block add_block,
3000 Block rem_block, Attributes attrs, Location loc)
3005 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
3008 OptAttributes = attrs;
3011 public override bool Define (TypeContainer parent)
3013 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3016 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3017 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3019 EventType = RootContext.LookupType (parent, Type, false, Location);
3020 if (EventType == null)
3023 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3027 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3028 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3029 "' : event must be of a delegate type");
3033 Type [] parameters = new Type [1];
3034 parameters [0] = EventType;
3036 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3038 if (Add == null && Remove == null)
3039 FieldBuilder = parent.TypeBuilder.DefineField (Name, EventType, FieldAttributes.Private);
3042 // Now define the accessors
3045 AddBuilder = parent.TypeBuilder.DefineMethod (
3046 "add_" + Name, m_attr, null, parameters);
3047 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3048 EventBuilder.SetAddOnMethod (AddBuilder);
3051 // HACK because System.Reflection.Emit is lame
3053 Parameter [] parms = new Parameter [1];
3054 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3055 InternalParameters ip = new InternalParameters (
3056 parent, new Parameters (parms, null, Location));
3058 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3059 Report.Error (111, Location,
3060 "Class `" + parent.Name + "' already contains a definition with the " +
3061 "same return value and parameter types for the " +
3062 "'add' method of event `" + Name + "'");
3066 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3067 "remove_" + Name, m_attr, null, parameters);
3068 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3069 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3072 // HACK because System.Reflection.Emit is lame
3075 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3076 Report.Error (111, Location,
3077 "Class `" + parent.Name + "' already contains a definition with the " +
3078 "same return value and parameter types for the " +
3079 "'remove' method of event `" + Name + "'");
3083 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3084 Report.Error (111, Location,
3085 "Class `" + parent.Name +
3086 "' already contains a definition for the event `" +
3094 void EmitDefaultMethod (EmitContext ec, bool is_add)
3096 ILGenerator ig = ec.ig;
3097 MethodInfo method = null;
3100 method = TypeManager.delegate_combine_delegate_delegate;
3102 method = TypeManager.delegate_remove_delegate_delegate;
3104 ig.Emit (OpCodes.Ldarg_0);
3105 ig.Emit (OpCodes.Ldarg_0);
3106 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3107 ig.Emit (OpCodes.Ldarg_1);
3108 ig.Emit (OpCodes.Call, method);
3109 ig.Emit (OpCodes.Castclass, EventType);
3110 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3111 ig.Emit (OpCodes.Ret);
3114 public void Emit (TypeContainer tc)
3119 ig = AddBuilder.GetILGenerator ();
3120 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3123 ec.EmitTopBlock (Add, Location);
3125 EmitDefaultMethod (ec, true);
3127 ig = RemoveBuilder.GetILGenerator ();
3128 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3131 ec.EmitTopBlock (Remove, Location);
3133 EmitDefaultMethod (ec, false);
3135 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3136 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3143 // FIXME: This does not handle:
3145 // int INTERFACENAME [ args ]
3149 // int this [ args ]
3151 public class Indexer : MemberCore {
3153 const int AllowedModifiers =
3156 Modifiers.PROTECTED |
3157 Modifiers.INTERNAL |
3161 Modifiers.OVERRIDE |
3164 public readonly string Type;
3165 public readonly string InterfaceType;
3166 public readonly Parameters FormalParameters;
3167 public readonly Block Get;
3168 public readonly Block Set;
3169 public Attributes OptAttributes;
3170 public MethodBuilder GetBuilder;
3171 public MethodBuilder SetBuilder;
3172 public PropertyBuilder PropertyBuilder;
3173 public Type IndexerType;
3175 public Indexer (string type, string int_type, int flags, Parameters parms,
3176 Block get_block, Block set_block, Attributes attrs, Location loc)
3181 InterfaceType = int_type;
3182 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
3183 FormalParameters = parms;
3186 OptAttributes = attrs;
3189 void DefineMethod (TypeContainer parent, Type iface_type,
3190 Type ret_type, string name,
3191 Type [] parameters, bool is_get)
3193 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3194 MethodInfo implementing;
3196 implementing = parent.IsInterfaceMethod (
3197 iface_type, name, ret_type, parameters, false);
3200 // Setting null inside this block will trigger a more
3201 // verbose error reporting for missing interface implementations
3203 // The "candidate" function has been flagged already
3204 // but it wont get cleared
3206 if (implementing != null){
3207 if (iface_type == null){
3208 if ((ModFlags & Modifiers.PUBLIC) == 0)
3209 implementing = null;
3210 if ((ModFlags & Modifiers.STATIC) != 0)
3211 implementing = null;
3213 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3216 "`public' or `abstract' modifiers are not "+
3217 "allowed in explicit interface declarations"
3219 implementing = null;
3223 if (implementing != null){
3225 MethodAttributes.Virtual |
3226 MethodAttributes.NewSlot |
3227 MethodAttributes.HideBySig;
3229 // If an interface implementing, then we can set final.
3230 if (((attr & MethodAttributes.Abstract) == 0) &&
3231 implementing.DeclaringType.IsInterface)
3232 attr |= MethodAttributes.Final;
3235 // clear the pending flag
3237 parent.IsInterfaceMethod (
3238 iface_type, name, ret_type, parameters, true);
3243 string meth_name = "get_Item";
3244 if (iface_type != null)
3245 meth_name = iface_type + ".get_Item";
3247 GetBuilder = parent.TypeBuilder.DefineMethod (
3248 meth_name, attr, IndexerType, parameters);
3250 if (implementing != null)
3251 parent.TypeBuilder.DefineMethodOverride (
3252 GetBuilder, implementing);
3255 PropertyBuilder.SetGetMethod (GetBuilder);
3258 string meth_name = "set_Item";
3260 if (iface_type != null)
3261 meth_name = iface_type + ".set_Item";
3263 SetBuilder = parent.TypeBuilder.DefineMethod (
3264 meth_name, attr, null, parameters);
3265 if (implementing != null)
3266 parent.TypeBuilder.DefineMethodOverride (
3267 SetBuilder, implementing);
3269 PropertyBuilder.SetSetMethod (SetBuilder);
3273 public override bool Define (TypeContainer parent)
3275 PropertyAttributes prop_attr =
3276 PropertyAttributes.RTSpecialName |
3277 PropertyAttributes.SpecialName;
3280 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3281 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3283 // Check if the return type and arguments were correct
3284 if (IndexerType == null || parameters == null)
3287 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3288 "this" : InterfaceType, Location))
3292 // verify accessibility
3294 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3297 foreach (Type partype in parameters)
3298 if (!TypeContainer.AsAccessible (partype, ModFlags))
3304 Type iface_type = null;
3306 if (InterfaceType != null){
3307 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3308 if (iface_type == null)
3313 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3314 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3315 prop_attr, IndexerType, parameters);
3318 DefineMethod (parent, iface_type, IndexerType, "get_Item", parameters, true);
3319 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3320 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3321 Report.Error (111, Location,
3322 "Class `" + parent.Name +
3323 "' already contains a definition with the " +
3324 "same return value and parameter types for the " +
3331 int top = parameters.Length;
3332 Type [] set_pars = new Type [top + 1];
3333 parameters.CopyTo (set_pars, 0);
3334 set_pars [top] = IndexerType;
3336 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3338 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3340 fixed_parms.CopyTo (tmp, 0);
3341 tmp [fixed_parms.Length] = new Parameter (
3342 Type, "value", Parameter.Modifier.NONE, null);
3344 Parameters set_formal_params = new Parameters (tmp, null, Location);
3347 parent, iface_type, TypeManager.void_type,
3348 "set_Item", set_pars, false);
3350 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3352 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3355 "Class `" + parent.Name + "' already contains a " +
3356 "definition with the " +
3357 "same return value and parameter types for the " +
3364 // Now name the parameters
3366 Parameter [] p = FormalParameters.FixedParameters;
3370 for (i = 0; i < p.Length; ++i) {
3372 GetBuilder.DefineParameter (
3373 i + 1, p [i].Attributes, p [i].Name);
3376 SetBuilder.DefineParameter (
3377 i + 1, p [i].Attributes, p [i].Name);
3381 SetBuilder.DefineParameter (
3382 i + 1, ParameterAttributes.None, "value");
3384 if (i != parameters.Length) {
3385 Parameter array_param = FormalParameters.ArrayParameter;
3386 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3391 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3396 public void Emit (TypeContainer tc)
3401 ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3402 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3405 ig = GetBuilder.GetILGenerator ();
3406 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3408 ec.EmitTopBlock (Get, Location);
3412 ig = SetBuilder.GetILGenerator ();
3413 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3415 ec.EmitTopBlock (Set, Location);
3420 public class Operator : MemberCore {
3422 const int AllowedModifiers =
3426 const int RequiredModifiers =
3430 public enum OpType : byte {
3440 // Unary and Binary operators
3463 // Implicit and Explicit
3468 public readonly OpType OperatorType;
3469 public readonly string ReturnType;
3470 public readonly string FirstArgType;
3471 public readonly string FirstArgName;
3472 public readonly string SecondArgType;
3473 public readonly string SecondArgName;
3474 public readonly Block Block;
3475 public Attributes OptAttributes;
3476 public MethodBuilder OperatorMethodBuilder;
3478 public string MethodName;
3479 public Method OperatorMethod;
3481 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3482 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3485 OperatorType = type;
3486 ReturnType = ret_type;
3487 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
3488 FirstArgType = arg1type;
3489 FirstArgName = arg1name;
3490 SecondArgType = arg2type;
3491 SecondArgName = arg2name;
3493 OptAttributes = attrs;
3496 string Prototype (TypeContainer parent)
3498 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3499 SecondArgType + ")";
3502 public override bool Define (TypeContainer parent)
3505 MethodName = "op_" + OperatorType;
3507 if (SecondArgType != null)
3510 Parameter [] param_list = new Parameter [length];
3512 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3515 "User defined operators `" +
3516 Prototype (parent) +
3517 "' must be declared static and public");
3521 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3522 Parameter.Modifier.NONE, null);
3523 if (SecondArgType != null)
3524 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3525 Parameter.Modifier.NONE, null);
3527 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3528 new Parameters (param_list, null, Location),
3529 OptAttributes, Mono.CSharp.Location.Null);
3531 OperatorMethod.Define (parent);
3533 if (OperatorMethod.MethodBuilder == null)
3536 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3538 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3539 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3540 Type return_type = OperatorMethod.GetReturnType (parent);
3541 Type first_arg_type = param_types [0];
3543 // Rules for conversion operators
3545 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3546 if (first_arg_type == return_type && first_arg_type == declaring_type){
3549 "User-defined conversion cannot take an object of the " +
3550 "enclosing type and convert to an object of the enclosing" +
3555 if (first_arg_type != declaring_type && return_type != declaring_type){
3558 "User-defined conversion must convert to or from the " +
3563 if (first_arg_type == TypeManager.object_type ||
3564 return_type == TypeManager.object_type){
3567 "User-defined conversion cannot convert to or from " +
3572 if (first_arg_type.IsInterface || return_type.IsInterface){
3575 "User-defined conversion cannot convert to or from an " +
3580 if (first_arg_type.IsSubclassOf (return_type) ||
3581 return_type.IsSubclassOf (first_arg_type)){
3584 "User-defined conversion cannot convert between types " +
3585 "that derive from each other");
3588 } else if (SecondArgType == null) {
3589 // Checks for Unary operators
3591 if (first_arg_type != declaring_type){
3594 "The parameter of a unary operator must be the " +
3599 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3600 if (return_type != declaring_type){
3603 "The parameter and return type for ++ and -- " +
3604 "must be the containing type");
3610 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3611 if (return_type != TypeManager.bool_type){
3614 "The return type of operator True or False " +
3621 // Checks for Binary operators
3623 if (first_arg_type != declaring_type &&
3624 param_types [1] != declaring_type){
3627 "One of the parameters of a binary operator must " +
3628 "be the containing type");
3636 public void Emit (TypeContainer parent)
3638 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3639 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3641 OperatorMethod.Block = Block;
3642 OperatorMethod.Emit (parent);
3647 // This is used to compare method signatures
3649 struct MethodSignature {
3651 public Type RetType;
3652 public Type [] Parameters;
3654 public MethodSignature (string name, Type ret_type, Type [] parameters)
3658 Parameters = parameters;
3661 public override int GetHashCode ()
3663 return Name.GetHashCode ();
3666 public override bool Equals (Object o)
3668 MethodSignature other = (MethodSignature) o;
3670 if (other.Name != Name)
3673 if (other.RetType != RetType)
3676 if (Parameters == null){
3677 if (other.Parameters == null)
3682 if (other.Parameters == null)
3685 int c = Parameters.Length;
3686 if (other.Parameters.Length != c)
3689 for (int i = 0; i < c; i++)
3690 if (other.Parameters [i] != Parameters [i])