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;
85 // Attributes for this type
86 protected Attributes attributes;
88 // Information in the case we are an attribute type
90 public AttributeTargets Targets;
91 public bool AllowMultiple;
92 public bool Inherited;
95 public TypeContainer (TypeContainer parent, string name, Location l)
99 types = new ArrayList ();
100 this.parent = parent;
107 base_class_name = null;
109 //Console.WriteLine ("New class " + name + " inside " + n);
112 public AdditionResult AddConstant (Const constant)
115 string name = constant.Name;
117 if ((res = IsValid (name)) != AdditionResult.Success)
120 if (constants == null)
121 constants = new ArrayList ();
123 constants.Add (constant);
124 DefineName (name, constant);
126 return AdditionResult.Success;
129 public AdditionResult AddEnum (Mono.CSharp.Enum e)
132 string name = e.Name;
134 if ((res = IsValid (name)) != AdditionResult.Success)
138 enums = new ArrayList ();
141 DefineName (name, e);
143 return AdditionResult.Success;
146 public AdditionResult AddClass (Class c)
149 string name = c.Name;
152 if ((res = IsValid (name)) != AdditionResult.Success)
155 DefineName (name, c);
158 return AdditionResult.Success;
161 public AdditionResult AddStruct (Struct s)
164 string name = s.Name;
166 if ((res = IsValid (name)) != AdditionResult.Success)
169 DefineName (name, s);
172 return AdditionResult.Success;
175 public AdditionResult AddDelegate (Delegate d)
178 string name = d.Name;
180 if ((res = IsValid (name)) != AdditionResult.Success)
183 if (delegates == null)
184 delegates = new ArrayList ();
186 DefineName (name, d);
189 return AdditionResult.Success;
192 public AdditionResult AddMethod (Method method)
194 string name = method.Name;
195 Object value = defined_names [name];
197 if (value != null && (!(value is Method)))
198 return AdditionResult.NameExists;
201 methods = new ArrayList ();
203 methods.Add (method);
205 DefineName (name, method);
207 return AdditionResult.Success;
210 public AdditionResult AddConstructor (Constructor c)
212 if (c.Name != Basename)
213 return AdditionResult.NotAConstructor;
215 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
218 have_static_constructor = true;
219 if (default_static_constructor != null){
220 Console.WriteLine ("I have a static constructor already");
221 Console.WriteLine (" " + default_static_constructor);
222 return AdditionResult.MethodExists;
225 default_static_constructor = c;
228 if (default_constructor != null)
229 return AdditionResult.MethodExists;
230 default_constructor = c;
233 if (instance_constructors == null)
234 instance_constructors = new ArrayList ();
236 instance_constructors.Add (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 {
380 return base_class_name;
384 public ArrayList Bases {
394 public ArrayList Fields {
400 public ArrayList InstanceConstructors {
402 return instance_constructors;
406 public ArrayList Properties {
412 public ArrayList Events {
418 public ArrayList Enums {
424 public ArrayList Indexers {
430 public ArrayList Operators {
436 public ArrayList Delegates {
442 public Attributes OptAttributes {
449 // root_types contains all the types. All TopLevel types
450 // hence have a parent that points to `root_types', that is
451 // why there is a non-obvious test down here.
453 public bool IsTopLevel {
456 if (parent.Parent == null)
463 public bool HaveStaticConstructor {
465 return have_static_constructor;
469 public virtual TypeAttributes TypeAttr {
471 return Modifiers.TypeAttr (ModFlags, this);
476 // Emits the instance field initializers
478 public bool EmitFieldInitializers (EmitContext ec, bool is_static)
481 ILGenerator ig = ec.ig;
484 fields = initialized_static_fields;
486 fields = initialized_fields;
491 foreach (Field f in fields){
492 Object init = f.Initializer;
495 if (init is Expression)
496 e = (Expression) init;
498 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
499 string rank = f.Type.Substring (f.Type.IndexOf ("["));
500 e = new ArrayCreation (base_type, rank, (ArrayList) init, f.Location);
508 ig.Emit (OpCodes.Ldarg_0);
513 ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
515 ig.Emit (OpCodes.Stfld, f.FieldBuilder);
523 // Defines the default constructors
525 void DefineDefaultConstructor (bool is_static)
530 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
531 new ConstructorBaseInitializer (null, new Location (-1)),
535 mods = Modifiers.STATIC;
541 c.Block = new Block (null);
545 public void ReportStructInitializedInstanceError ()
547 string n = TypeBuilder.FullName;
549 foreach (Field f in initialized_fields){
552 "`" + n + "." + f.Name + "': can not have " +
553 "instance field initializers in structs");
557 struct TypeAndMethods {
559 public MethodInfo [] methods;
561 // Far from ideal, but we want to avoid creating a copy
563 public Type [][] args;
566 // This flag on the method says `We found a match, but
567 // because it was private, we could not use the match
569 public bool [] found;
573 // This array keeps track of the pending implementations
575 TypeAndMethods [] pending_implementations;
578 // Registers the required method implementations for this class
580 // Register method implementations are either abstract methods
581 // flagged as such on the base class or interface methods
583 public void RegisterRequiredImplementations ()
585 Type [] ifaces = TypeBuilder.GetInterfaces ();
586 Type b = TypeBuilder.BaseType;
590 icount = ifaces.Length;
595 pending_implementations = new TypeAndMethods [icount + (b.IsAbstract ? 1 : 0)];
599 foreach (Type t in ifaces){
602 if (t is TypeBuilder){
605 iface = RootContext.TypeManager.LookupInterface (t);
607 mi = iface.GetMethods ();
609 mi = t.GetMethods ();
611 int count = mi.Length;
612 pending_implementations [i].type = t;
613 pending_implementations [i].methods = mi;
614 pending_implementations [i].args = new Type [count][];
615 pending_implementations [i].found = new bool [count];
618 foreach (MethodInfo m in mi){
619 Type [] types = TypeManager.GetArgumentTypes (m);
621 pending_implementations [i].args [j] = types;
629 MemberInfo [] abstract_methods;
631 abstract_methods = FindMembers (
632 TypeBuilder.BaseType,
633 MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
634 abstract_method_filter, null);
636 if (abstract_methods != null){
637 int count = abstract_methods.Length;
638 pending_implementations [i].methods = new MethodInfo [count];
640 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
641 pending_implementations [i].found = new bool [count];
642 pending_implementations [i].args = new Type [count][];
643 pending_implementations [i].type = TypeBuilder;
646 foreach (MemberInfo m in abstract_methods){
647 MethodInfo mi = (MethodInfo) m;
649 Type [] types = TypeManager.GetArgumentTypes (mi);
651 pending_implementations [i].args [j] = types;
659 public static string MakeFQN (string nsn, string name)
661 string prefix = (nsn == "" ? "" : nsn + ".");
663 return prefix + name;
666 Type LookupInterfaceOrClass (object builder, string ns, string name, bool is_class, out bool error)
668 TypeContainer parent;
672 name = MakeFQN (ns, name);
674 t = RootContext.TypeManager.LookupType (name);
679 parent = (Class) RootContext.Tree.Classes [name];
681 parent = (Struct) RootContext.Tree.Structs [name];
685 t = parent.DefineType (builder);
687 Report.Error (146, "Class definition is circular: `"+name+"'");
699 // returns the type for an interface or a class, this will recursively
700 // try to define the types that it depends on.
702 Type GetInterfaceOrClass (object builder, string name, bool is_class)
708 // Attempt to lookup the class on our namespace
710 t = LookupInterfaceOrClass (builder, Namespace.Name, name, is_class, out error);
718 // Attempt to do a direct unqualified lookup
720 t = LookupInterfaceOrClass (builder, "", name, is_class, out error);
728 // Attempt to lookup the class on any of the `using'
732 for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
733 ArrayList using_list = ns.UsingTable;
735 if (using_list == null)
738 foreach (string n in using_list){
739 t = LookupInterfaceOrClass (builder, n, name, is_class, out error);
748 Report.Error (246, "Can not find type `"+name+"'");
753 /// This function computes the Base class and also the
754 /// list of interfaces that the class or struct @c implements.
756 /// The return value is an array (might be null) of
757 /// interfaces implemented (as Types).
759 /// The @parent argument is set to the parent object or null
760 /// if this is `System.Object'.
762 Type [] GetClassBases (object builder, bool is_class, out Type parent, out bool error)
764 ArrayList bases = Bases;
773 parent = TypeManager.value_type;
777 if (RootContext.StdLib)
778 parent = TypeManager.object_type;
779 else if (Name != "System.Object")
780 parent = TypeManager.object_type;
783 // If we are compiling our runtime,
784 // and we are defining ValueType, then our
785 // parent is `System.Object'.
787 if (!RootContext.StdLib && Name == "System.ValueType")
788 parent = TypeManager.object_type;
795 // Bases should be null if there are no bases at all
800 string name = (string) bases [0];
801 Type first = GetInterfaceOrClass (builder, name, is_class);
812 parent = TypeManager.object_type;
819 Type [] ifaces = new Type [count-start];
821 for (i = start, j = 0; i < count; i++, j++){
822 string name = (string) bases [i];
823 Type t = GetInterfaceOrClass (builder, name, is_class);
830 if (is_class == false && !t.IsInterface){
831 Report.Error (527, "In Struct `" + Name + "', type `"+
832 name +"' is not an interface");
841 detail = " (a class can not inherit from a struct)";
843 Report.Error (509, "class `"+ Name +
844 "': Cannot inherit from sealed class `"+
845 bases [i]+"'"+detail);
852 Report.Error (527, "In Class `" + Name + "', type `"+
853 name+"' is not an interface");
866 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
868 public TypeBuilder DefineType (object parent_builder)
875 if (TypeBuilder != null)
888 ifaces = GetClassBases (parent_builder, is_class, out parent, out error);
893 if (parent_builder is ModuleBuilder) {
894 ModuleBuilder builder = (ModuleBuilder) parent_builder;
896 // Structs with no fields need to have a ".size 1"
900 if (!is_class && Fields == null)
901 TypeBuilder = builder.DefineType (Name,
904 PackingSize.Unspecified, 1);
907 // classes or structs with fields
909 TypeBuilder = builder.DefineType (Name,
914 TypeBuilder builder = (System.Reflection.Emit.TypeBuilder) parent_builder;
917 // Structs with no fields need to have a ".size 1"
920 if (!is_class && Fields == null)
921 TypeBuilder = builder.DefineNestedType (Basename,
924 PackingSize.Unspecified);
927 // classes or structs with fields
929 TypeBuilder = builder.DefineNestedType (Basename,
935 RootContext.TypeManager.AddUserType (Name, TypeBuilder, this);
936 RootContext.RegisterOrder (this);
939 foreach (TypeContainer tc in Types)
940 tc.DefineType (TypeBuilder);
943 if (Delegates != null) {
944 foreach (Delegate d in Delegates)
945 d.DefineDelegate (TypeBuilder);
949 foreach (Enum en in Enums)
950 en.DefineEnum (TypeBuilder);
959 /// Defines the MemberCore objects that are in the `list' Arraylist
961 /// The `defined_names' array contains a list of members defined in
964 static ArrayList remove_list = new ArrayList ();
965 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
969 remove_list.Clear ();
971 foreach (MemberCore mc in list){
972 if (!mc.Define (this)){
973 remove_list.Add (mc);
977 if (defined_names == null)
980 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
983 if (RootContext.WarningLevel >= 4){
984 if ((mc.ModFlags & Modifiers.NEW) != 0)
985 Report109 (mc.Location, mc);
990 if (defined_names [idx] is PropertyInfo &&
991 ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
995 #if WANT_TO_VERIFY_SIGNATURES_HERE
996 if (defined_names [idx] is MethodBase && mc is MethodCore){
997 MethodBase mb = (MethodBase) defined_names [idx];
998 MethodCore met = (MethodCore) mc;
1000 if ((mb.IsVirtual || mb.IsAbstract) &&
1001 (mc.ModFlags & Modifiers.OVERRIDE) != 0)
1005 // FIXME: Compare the signatures here. If they differ,
1006 // then: `continue;'
1009 Report108 (mc.Location, defined_names [idx]);
1012 foreach (object o in remove_list)
1015 remove_list.Clear ();
1019 /// Populates our TypeBuilder with fields and methods
1021 public override bool Define (TypeContainer parent)
1023 MemberInfo [] defined_names = null;
1025 if (RootContext.WarningLevel > 1){
1029 // This code throws an exception in the comparer
1030 // I guess the string is not an object?
1032 ptype = TypeBuilder.BaseType;
1034 defined_names = FindMembers (
1035 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1036 BindingFlags.Public | BindingFlags.Instance |
1037 BindingFlags.Static, null, null);
1039 Array.Sort (defined_names, mif_compare);
1043 if (constants != null)
1044 DefineMembers (constants, defined_names);
1047 DefineMembers (fields, defined_names);
1050 if (instance_constructors == null){
1051 if (default_constructor == null)
1052 DefineDefaultConstructor (false);
1055 if (initialized_static_fields != null &&
1056 default_static_constructor == null)
1057 DefineDefaultConstructor (true);
1060 if (this is Struct){
1062 // Structs can not have initialized instance
1065 if (initialized_static_fields != null &&
1066 default_static_constructor == null)
1067 DefineDefaultConstructor (true);
1069 if (initialized_fields != null)
1070 ReportStructInitializedInstanceError ();
1073 RegisterRequiredImplementations ();
1076 // Constructors are not in the defined_names array
1078 if (instance_constructors != null)
1079 DefineMembers (instance_constructors, null);
1081 if (default_static_constructor != null)
1082 default_static_constructor.Define (this);
1084 if (methods != null)
1085 DefineMembers (methods, null);
1087 if (properties != null)
1088 DefineMembers (properties, defined_names);
1091 DefineMembers (events, defined_names);
1094 // FIXME: Make Indexers MemberCores?
1096 if (indexers != null) {
1097 foreach (Indexer i in Indexers)
1101 if (operators != null)
1102 DefineMembers (operators, null);
1105 // FIXME: I think we want to make Enums (hence DeclSpace)
1106 // a MemberCore so we can report 108 and 109 here.
1109 DefineMembers (enums, defined_names);
1111 if (delegates != null)
1112 DefineMembers (delegates, defined_names);
1118 /// Looks up the alias for the name
1120 public string LookupAlias (string name)
1122 if (Namespace != null)
1123 return Namespace.LookupAlias (name);
1129 /// This function is based by a delegate to the FindMembers routine
1131 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1136 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
1138 MethodInfo mi = (MethodInfo) m;
1140 return mi.IsAbstract;
1144 /// This filter is used by FindMembers, and we just keep
1145 /// a global for the filter to `AlwaysAccept'
1147 static MemberFilter accepting_filter;
1150 /// This delegate is a MemberFilter used to extract the
1151 /// abstact methods from a type.
1153 static MemberFilter abstract_method_filter;
1156 /// A member comparission method based on name only
1158 static IComparer mif_compare;
1160 static TypeContainer ()
1162 abstract_method_filter = new MemberFilter (IsAbstractMethod);
1163 accepting_filter = new MemberFilter (AlwaysAccept);
1164 mif_compare = new MemberInfoCompare ();
1168 /// This method returns the members of this type just like Type.FindMembers would
1169 /// Only, we need to use this for types which are _being_ defined because MS'
1170 /// implementation can't take care of that.
1173 // FIXME: return an empty static array instead of null, that cleans up
1174 // some code and is consistent with some coding conventions I just found
1176 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1177 MemberFilter filter, object criteria)
1179 ArrayList members = new ArrayList ();
1182 filter = accepting_filter;
1184 if ((mt & MemberTypes.Field) != 0) {
1185 if (Fields != null) {
1186 foreach (Field f in Fields) {
1187 FieldBuilder fb = f.FieldBuilder;
1188 if (filter (fb, criteria) == true)
1193 if (Constants != null) {
1194 foreach (Const con in Constants) {
1195 FieldBuilder fb = con.FieldBuilder;
1196 if (filter (fb, criteria) == true)
1202 if ((mt & MemberTypes.Method) != 0) {
1203 if (Methods != null) {
1204 foreach (Method m in Methods) {
1205 MethodBuilder mb = m.MethodBuilder;
1207 // If we are in transit, ignore
1208 // This case arises when we are still defining a PInvoke method
1209 // and we hit FindMembers because of the need to resolve named
1210 // arguments inside of Attribute.DefinePInvokeMethod
1214 if (filter (mb, criteria) == true)
1219 if (Operators != null){
1220 foreach (Operator o in Operators) {
1221 MethodBuilder ob = o.OperatorMethodBuilder;
1223 if (filter (ob, criteria) == true)
1229 if ((mt & MemberTypes.Event) != 0) {
1231 foreach (Event e in Events) {
1232 if (filter (e.EventBuilder, criteria) == true)
1233 members.Add (e.EventBuilder);
1237 if ((mt & MemberTypes.Property) != 0){
1238 if (Properties != null)
1239 foreach (Property p in Properties) {
1240 if (filter (p.PropertyBuilder, criteria) == true)
1241 members.Add (p.PropertyBuilder);
1244 if (Indexers != null)
1245 foreach (Indexer ix in Indexers) {
1246 if (filter (ix.PropertyBuilder, criteria) == true)
1247 members.Add (ix.PropertyBuilder);
1251 if ((mt & MemberTypes.NestedType) != 0) {
1254 foreach (TypeContainer t in Types)
1255 if (filter (t.TypeBuilder, criteria) == true)
1256 members.Add (t.TypeBuilder);
1259 foreach (Enum en in Enums)
1260 if (filter (en.TypeBuilder, criteria) == true)
1261 members.Add (en.TypeBuilder);
1265 if ((mt & MemberTypes.Constructor) != 0){
1266 if (instance_constructors != null){
1267 foreach (Constructor c in instance_constructors){
1268 ConstructorBuilder cb = c.ConstructorBuilder;
1270 if (filter (cb, criteria) == true)
1275 if (default_static_constructor != null){
1276 ConstructorBuilder cb =
1277 default_static_constructor.ConstructorBuilder;
1279 if (filter (cb, criteria) == true)
1285 // Lookup members in parent if requested.
1287 if ((bf & BindingFlags.DeclaredOnly) == 0){
1290 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1292 members.AddRange (mi);
1295 int count = members.Count;
1297 MemberInfo [] mi = new MemberInfo [count];
1298 members.CopyTo (mi);
1305 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1307 EventInfo ei = event_expr.EventInfo;
1309 foreach (Event e in events) {
1311 if (e.FieldBuilder == null)
1314 if (Type.FilterName (e.FieldBuilder, ei.Name))
1315 return e.FieldBuilder;
1321 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1322 MemberFilter filter, object criteria)
1324 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1327 return tc.FindMembers (mt, bf, filter, criteria);
1329 return t.FindMembers (mt, bf, filter, criteria);
1333 /// Whether the specified method is an interface method implementation
1337 /// If a method in Type `t' (or null to look in all interfaces
1338 /// and the base abstract class) with name `Name', return type `ret_type' and
1339 /// arguments `args' implements an interface, this method will
1340 /// return the MethodInfo that this method implements.
1342 /// This will remove the method from the list of "pending" methods
1343 /// that are required to be implemented for this class as a side effect.
1346 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1349 if (pending_implementations == null)
1352 foreach (TypeAndMethods tm in pending_implementations){
1353 if (!(t == null || tm.type == t))
1357 foreach (MethodInfo m in tm.methods){
1363 if (Name != m.Name){
1368 if (ret_type != m.ReturnType){
1374 if (tm.args [i] == null || tm.args [i].Length == 0){
1376 tm.methods [i] = null;
1377 tm.found [i] = true;
1384 if (tm.args == null){
1385 Console.WriteLine ("Type: " + tm.type);
1386 Console.WriteLine ("method: " + tm.methods [i]);
1389 if (tm.args [i] == null){
1395 // Check if we have the same parameters
1397 if (tm.args [i].Length != args.Length){
1404 for (j = 0; j < args.Length; j++){
1405 if (tm.args [i][j] != args[j]){
1412 tm.methods [i] = null;
1413 tm.found [i] = true;
1417 // If a specific type was requested, we can stop now.
1425 /// Verifies that any pending abstract methods or interface methods
1426 /// were implemented.
1428 bool VerifyPendingMethods ()
1430 int top = pending_implementations.Length;
1431 bool errors = false;
1434 for (i = 0; i < top; i++){
1435 Type type = pending_implementations [i].type;
1438 foreach (MethodInfo mi in pending_implementations [i].methods){
1442 if (type.IsInterface){
1445 if (pending_implementations [i].found [j])
1446 extra = ". (method might be private or static)";
1449 "`" + Name + "' does not implement " +
1450 "interface member `" +
1451 type.FullName + "." + mi.Name + "'" + extra);
1455 "`" + Name + "' does not implement " +
1456 "inherited abstract member `" +
1457 type.FullName + "." + mi.Name + "'");
1467 /// Emits the values for the constants
1469 public void EmitConstants ()
1471 if (constants != null)
1472 foreach (Const con in constants)
1473 con.EmitConstant (this);
1478 /// Emits the code, this step is performed after all
1479 /// the types, enumerations, constructors
1483 if (instance_constructors != null)
1484 foreach (Constructor c in instance_constructors)
1487 if (default_static_constructor != null)
1488 default_static_constructor.Emit (this);
1490 if (methods != null)
1491 foreach (Method m in methods)
1494 if (operators != null)
1495 foreach (Operator o in operators)
1498 if (properties != null)
1499 foreach (Property p in properties)
1502 if (indexers != null) {
1503 foreach (Indexer ix in indexers)
1506 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1508 TypeBuilder.SetCustomAttribute (cb);
1512 foreach (Field f in fields)
1515 if (events != null){
1516 foreach (Event e in Events)
1520 if (pending_implementations != null)
1521 if (!VerifyPendingMethods ())
1524 EmitContext ec = new EmitContext (
1525 this, Mono.CSharp.Location.Null, null, null,
1528 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1530 // if (types != null)
1531 // foreach (TypeContainer tc in types)
1535 public override void CloseType ()
1540 TypeBuilder.CreateType ();
1542 } catch (TypeLoadException){
1544 // This is fine, the code still created the type
1546 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1547 // Console.WriteLine (e.Message);
1551 foreach (Enum en in Enums)
1555 foreach (TypeContainer tc in Types)
1559 foreach (TypeContainer tc in Types)
1560 if (!(tc is Struct))
1564 if (Delegates != null)
1565 foreach (Delegate d in Delegates)
1569 public string MakeName (string n)
1571 return "`" + Name + "." + n + "'";
1574 public void Report108 (Location l, MemberInfo mi)
1577 108, l, "The keyword new is required on " +
1578 MakeName (mi.Name) + " because it hides `" +
1579 mi.ReflectedType.Name + "." + mi.Name + "'");
1582 public void Report109 (Location l, MemberCore mc)
1585 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1586 "inherited member, the keyword new is not required");
1589 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1595 // Performs the validation on a Method's modifiers (properties have
1596 // the same properties).
1598 public bool MethodModifiersValid (int flags, string n, Location loc)
1600 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1601 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1603 string name = MakeName (n);
1606 // At most one of static, virtual or override
1608 if ((flags & Modifiers.STATIC) != 0){
1609 if ((flags & vao) != 0){
1611 112, loc, "static method " + name + "can not be marked " +
1612 "as virtual, abstract or override");
1617 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1620 " marked as override cannot be marked as new or virtual");
1625 // If the declaration includes the abstract modifier, then the
1626 // declaration does not include static, virtual or extern
1628 if ((flags & Modifiers.ABSTRACT) != 0){
1629 if ((flags & Modifiers.EXTERN) != 0){
1631 180, loc, name + " can not be both abstract and extern");
1635 if ((flags & Modifiers.VIRTUAL) != 0){
1637 503, loc, name + " can not be both abstract and virtual");
1641 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1644 " is abstract but its container class is not");
1650 if ((flags & Modifiers.PRIVATE) != 0){
1651 if ((flags & vao) != 0){
1654 " virtual or abstract members can not be private");
1659 if ((flags & Modifiers.SEALED) != 0){
1660 if ((flags & Modifiers.OVERRIDE) == 0){
1663 " cannot be sealed because it is not an override");
1672 // Returns true if `type' is as accessible as the flags `flags'
1673 // given for this member
1675 static public bool AsAccessible (Type type, int flags)
1677 // FIXME: Implement me
1682 public class Class : TypeContainer {
1684 // Modifiers allowed in a class declaration
1686 public const int AllowedModifiers =
1689 Modifiers.PROTECTED |
1690 Modifiers.INTERNAL |
1692 Modifiers.ABSTRACT |
1695 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1696 : base (parent, name, l)
1700 if (parent.Parent == null)
1701 accmods = Modifiers.INTERNAL;
1703 accmods = Modifiers.PRIVATE;
1705 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods);
1706 this.attributes = attrs;
1710 // FIXME: How do we deal with the user specifying a different
1713 public override TypeAttributes TypeAttr {
1715 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1720 public class Struct : TypeContainer {
1722 // Modifiers allowed in a struct declaration
1724 public const int AllowedModifiers =
1727 Modifiers.PROTECTED |
1728 Modifiers.INTERNAL |
1731 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1732 : base (parent, name, l)
1736 if (parent.Parent == null)
1737 accmods = Modifiers.INTERNAL;
1739 accmods = Modifiers.PRIVATE;
1741 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods);
1743 this.ModFlags |= Modifiers.SEALED;
1744 this.attributes = attrs;
1749 // FIXME: Allow the user to specify a different set of attributes
1750 // in some cases (Sealed for example is mandatory for a class,
1751 // but what SequentialLayout can be changed
1753 public override TypeAttributes TypeAttr {
1755 return base.TypeAttr |
1756 TypeAttributes.SequentialLayout |
1757 TypeAttributes.Sealed |
1758 TypeAttributes.BeforeFieldInit;
1763 public abstract class MethodCore : MemberCore {
1764 public readonly Parameters Parameters;
1768 // Parameters, cached for semantic analysis.
1770 InternalParameters parameter_info;
1772 public MethodCore (string name, Parameters parameters, Location l)
1776 Parameters = parameters;
1780 // Returns the System.Type array for the parameters of this method
1782 Type [] parameter_types;
1783 static Type [] no_types = new Type [0];
1784 public Type [] ParameterTypes (TypeContainer parent)
1786 if (Parameters == null)
1789 if (parameter_types == null)
1790 parameter_types = Parameters.GetParameterInfo (parent);
1792 return parameter_types;
1795 public InternalParameters ParameterInfo
1798 return parameter_info;
1802 parameter_info = value;
1806 public Block Block {
1816 public CallingConventions GetCallingConvention (bool is_class)
1818 CallingConventions cc = 0;
1820 cc = Parameters.GetCallingConvention ();
1823 if ((ModFlags & Modifiers.STATIC) == 0)
1824 cc |= CallingConventions.HasThis;
1826 // FIXME: How is `ExplicitThis' used in C#?
1832 public class Method : MethodCore {
1833 public readonly string ReturnType;
1834 public MethodBuilder MethodBuilder;
1835 public readonly Attributes OptAttributes;
1837 MethodAttributes flags;
1840 /// Modifiers allowed in a class declaration
1842 const int AllowedModifiers =
1845 Modifiers.PROTECTED |
1846 Modifiers.INTERNAL |
1851 Modifiers.OVERRIDE |
1852 Modifiers.ABSTRACT |
1856 // return_type can be "null" for VOID values.
1858 public Method (string return_type, int mod, string name, Parameters parameters,
1859 Attributes attrs, Location l)
1860 : base (name, parameters, l)
1862 ReturnType = return_type;
1863 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1864 OptAttributes = attrs;
1867 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1871 if (! (m is MethodInfo))
1874 MethodSignature sig = (MethodSignature) filter_criteria;
1876 if (m.Name != sig.Name)
1879 mi = (MethodInfo) m;
1881 if (mi.ReturnType != sig.RetType)
1884 Type [] args = TypeManager.GetArgumentTypes (mi);
1885 Type [] sigp = sig.Parameters;
1887 if (args.Length != sigp.Length)
1890 for (int i = args.Length; i > 0; ){
1892 if (args [i] != sigp [i])
1899 /// This delegate is used to extract methods which have the
1900 /// same signature as the argument
1902 static MemberFilter method_signature_filter;
1906 method_signature_filter = new MemberFilter (MemberSignatureCompare);
1911 // Returns the `System.Type' for the ReturnType of this
1912 // function. Provides a nice cache. (used between semantic analysis
1913 // and actual code generation
1915 Type type_return_type;
1917 public Type GetReturnType (TypeContainer parent)
1919 if (type_return_type == null)
1920 type_return_type = RootContext.LookupType (
1921 parent, ReturnType, false, Location);
1923 return type_return_type;
1926 void DuplicatEntryPoint (MethodInfo b)
1930 "Program `" + RootContext.CodeGen.FileName +
1931 "' has more than one entry point defined: `" +
1932 b.DeclaringType.Name + "." + b.Name + "'");
1938 public override bool Define (TypeContainer parent)
1940 Type ret_type = GetReturnType (parent);
1941 Type [] parameters = ParameterTypes (parent);
1943 MethodInfo implementing;
1944 Type iface_type = null;
1945 string iface = "", short_name;
1947 // Check if the return type and arguments were correct
1948 if (ret_type == null || parameters == null)
1951 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
1955 // verify accessibility
1957 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
1960 foreach (Type partype in parameters)
1961 if (!TypeContainer.AsAccessible (partype, ModFlags))
1968 // Verify if the parent has a type with the same name, and then
1969 // check whether we have to create a new slot for it or not.
1971 Type ptype = parent.TypeBuilder.BaseType;
1973 // ptype is only null for System.Object while compiling corlib.
1975 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1976 MemberInfo [] mi, mi_static, mi_instance;
1978 mi_static = TypeContainer.FindMembers (
1979 ptype, MemberTypes.Method,
1980 BindingFlags.Public | BindingFlags.Static, method_signature_filter,
1983 mi_instance = TypeContainer.FindMembers (
1984 ptype, MemberTypes.Method,
1985 BindingFlags.Public | BindingFlags.Instance, method_signature_filter,
1988 if (mi_instance != null && mi_instance.Length > 0){
1990 } else if (mi_static != null && mi_static.Length > 0)
1995 if (mi != null && mi.Length > 0){
1996 if (!CheckMethodAgainstBase (parent, (MethodInfo) mi [0])){
2000 if ((ModFlags & Modifiers.NEW) != 0)
2001 WarningNotHiding (parent);
2003 if ((ModFlags & Modifiers.OVERRIDE) != 0)
2004 Report.Error (115, Location,
2005 parent.MakeName (Name) +
2006 " no suitable methods found to override");
2008 } else if ((ModFlags & Modifiers.NEW) != 0)
2009 WarningNotHiding (parent);
2012 // If we implement an interface, extract the interface name.
2014 flags = Modifiers.MethodAttr (ModFlags);
2016 if (Name.IndexOf (".") != -1){
2017 int pos = Name.LastIndexOf (".");
2018 iface = Name.Substring (0, pos);
2020 iface_type = RootContext.LookupType (parent, iface, false, Location);
2021 short_name = Name.Substring (pos + 1);
2023 if (iface_type == null)
2026 // Compute the full name that we need to export
2027 Name = iface_type.FullName + "." + short_name;
2032 // Check if we are an implementation of an interface method or
2035 implementing = parent.IsInterfaceMethod (
2036 iface_type, short_name, ret_type, parameters, false);
2039 // For implicit implementations, make sure we are public, for
2040 // explicit implementations, make sure we are private.
2042 if (implementing != null){
2044 // Setting null inside this block will trigger a more
2045 // verbose error reporting for missing interface implementations
2047 // The "candidate" function has been flagged already
2048 // but it wont get cleared
2050 if (iface_type == null){
2051 if ((ModFlags & Modifiers.PUBLIC) == 0)
2052 implementing = null;
2054 if ((ModFlags & Modifiers.STATIC) != 0)
2055 implementing = null;
2057 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2059 106, Location, "`public' or `abstract' modifiers "+
2060 "are not allowed in explicit interface declarations"
2062 implementing = null;
2068 // If implementing is still valid, set flags
2070 if (implementing != null){
2072 MethodAttributes.Virtual |
2073 MethodAttributes.NewSlot |
2074 MethodAttributes.HideBySig;
2076 // If not abstract, then we can set Final.
2077 if (((flags & MethodAttributes.Abstract) == 0) &&
2078 implementing.DeclaringType.IsInterface)
2079 flags |= MethodAttributes.Final;
2084 parent.IsInterfaceMethod (
2085 iface_type, short_name, ret_type, parameters, true);
2088 Attribute dllimport_attr = null;
2089 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2090 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2091 if (asec.Attributes == null)
2094 foreach (Attribute a in asec.Attributes)
2095 if (a.Name.IndexOf ("DllImport") != -1) {
2096 flags |= MethodAttributes.PinvokeImpl;
2103 // Finally, define the method
2106 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2107 EmitContext ec = new EmitContext (
2108 parent, Location, null, GetReturnType (parent), ModFlags);
2110 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2111 ec, parent.TypeBuilder,
2112 Name, flags, ret_type, parameters);
2114 MethodBuilder = parent.TypeBuilder.DefineMethod (
2116 GetCallingConvention (parent is Class),
2117 ret_type, parameters);
2119 if (implementing != null){
2120 parent.TypeBuilder.DefineMethodOverride (
2121 MethodBuilder, implementing);
2125 if (MethodBuilder == null)
2129 // HACK because System.Reflection.Emit is lame
2131 ParameterInfo = new InternalParameters (parent, Parameters);
2133 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2137 "Class `" + parent.Name + "' already contains a definition with " +
2138 " the same return value and parameter types for method `" +
2144 // This is used to track the Entry Point,
2146 // FIXME: Allow pluggable entry point, check arguments, etc.
2148 if (Name == "Main" &&
2149 ((ModFlags & Modifiers.STATIC) != 0) &&
2150 (RootContext.MainClass == null ||
2151 RootContext.MainClass == parent.TypeBuilder.FullName)){
2152 if (RootContext.EntryPoint != null){
2153 DuplicatEntryPoint (MethodBuilder);
2154 DuplicatEntryPoint (RootContext.EntryPoint);
2156 RootContext.EntryPoint = MethodBuilder;
2159 // FIXME: Verify that the method signature
2160 // is valid for an entry point, and report
2166 // Define each type attribute (in/out/ref) and
2167 // the argument names.
2169 Parameter [] p = Parameters.FixedParameters;
2173 for (i = 0; i < p.Length; i++)
2174 MethodBuilder.DefineParameter (
2175 i + 1, p [i].Attributes, p [i].Name);
2177 if (i != parameters.Length) {
2178 ParameterBuilder pb;
2180 Parameter array_param = Parameters.ArrayParameter;
2181 pb = MethodBuilder.DefineParameter (
2182 i + 1, array_param.Attributes,
2185 CustomAttributeBuilder a = new CustomAttributeBuilder (
2186 TypeManager.cons_param_array_attribute, new object [0]);
2188 pb.SetCustomAttribute (a);
2198 public void Emit (TypeContainer parent)
2200 if ((flags & MethodAttributes.PinvokeImpl) != 0)
2203 ILGenerator ig = MethodBuilder.GetILGenerator ();
2204 EmitContext ec = new EmitContext (parent, Location, ig,
2205 GetReturnType (parent), ModFlags);
2207 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2211 // abstract or extern methods have no bodies
2213 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2217 // Handle destructors specially
2219 // FIXME: This code generates buggy code
2221 if (Name == "Finalize" && type_return_type == TypeManager.void_type){
2222 Label end = ig.BeginExceptionBlock ();
2223 Label finish = ig.DefineLabel ();
2224 bool old_in_try = ec.InTry;
2226 ec.EmitTopBlock (Block, Location);
2227 ig.Emit (OpCodes.Leave, finish);
2228 ec.InTry = old_in_try;
2230 bool old_in_finally = ec.InFinally;
2231 ec.InFinally = true;
2232 ig.BeginFinallyBlock ();
2233 // throw new Exception ("IMPLEMENT BASE ACCESS!");
2234 // DONT FORGET TO SET THE EC VARIABLES.
2235 Console.WriteLine ("Implement base access here");
2237 ec.InFinally = old_in_finally;
2238 ig.EndExceptionBlock ();
2240 ec.EmitTopBlock (Block, Location);
2244 public abstract class ConstructorInitializer {
2245 ArrayList argument_list;
2246 ConstructorInfo parent_constructor;
2249 public ConstructorInitializer (ArrayList argument_list, Location location)
2251 this.argument_list = argument_list;
2252 this.location = location;
2255 public ArrayList Arguments {
2257 return argument_list;
2261 public bool Resolve (EmitContext ec)
2263 Expression parent_constructor_group;
2266 if (argument_list != null){
2267 for (int i = argument_list.Count; i > 0; ){
2270 Argument a = (Argument) argument_list [i];
2271 if (!a.Resolve (ec, location))
2276 if (this is ConstructorBaseInitializer)
2277 t = ec.TypeContainer.TypeBuilder.BaseType;
2279 t = ec.TypeContainer.TypeBuilder;
2281 parent_constructor_group = Expression.MemberLookup (
2282 ec, t, ".ctor", true,
2283 MemberTypes.Constructor,
2284 BindingFlags.Public | BindingFlags.Instance, location);
2286 if (parent_constructor_group == null){
2287 Console.WriteLine ("Could not find a constructor in our parent");
2291 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2292 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2294 if (parent_constructor == null){
2295 Console.WriteLine ("Could not locate a proper overload function");
2302 public void Emit (EmitContext ec)
2304 ec.ig.Emit (OpCodes.Ldarg_0);
2305 if (argument_list != null)
2306 Invocation.EmitArguments (ec, null, argument_list);
2307 ec.ig.Emit (OpCodes.Call, parent_constructor);
2311 public class ConstructorBaseInitializer : ConstructorInitializer {
2312 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2317 public class ConstructorThisInitializer : ConstructorInitializer {
2318 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2323 public class Constructor : MethodCore {
2324 public ConstructorBuilder ConstructorBuilder;
2325 public ConstructorInitializer Initializer;
2326 public Attributes OptAttributes;
2329 // Modifiers allowed for a constructor.
2331 const int AllowedModifiers =
2333 Modifiers.PROTECTED |
2334 Modifiers.INTERNAL |
2339 // The spec claims that static is not permitted, but
2340 // my very own code has static constructors.
2342 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2343 : base (name, args, l)
2349 // Returns true if this is a default constructor
2351 public bool IsDefault ()
2353 if ((ModFlags & Modifiers.STATIC) != 0)
2354 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2355 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2358 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2359 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2360 (Initializer is ConstructorBaseInitializer) &&
2361 (Initializer.Arguments == null);
2365 // Creates the ConstructorBuilder
2367 public override bool Define (TypeContainer parent)
2369 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2370 MethodAttributes.SpecialName);
2372 Type [] parameters = ParameterTypes (parent);
2374 if ((ModFlags & Modifiers.STATIC) != 0)
2375 ca |= MethodAttributes.Static;
2377 if (parent is Struct && parameters.Length == 0){
2380 "Structs can not contain explicit parameterless " +
2384 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2387 foreach (Type partype in parameters)
2388 if (!TypeContainer.AsAccessible (partype, ModFlags))
2391 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2392 ca, GetCallingConvention (parent is Class), parameters);
2395 // HACK because System.Reflection.Emit is lame
2397 ParameterInfo = new InternalParameters (parent, Parameters);
2399 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2402 "Class `" +parent.Name+ "' already contains a definition with the " +
2403 "same return value and parameter types for constructor `" + Name
2414 public void Emit (TypeContainer parent)
2416 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2417 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2419 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2420 if (Initializer == null)
2421 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2423 if (!Initializer.Resolve (ec)){
2424 Console.WriteLine ("Could not resolve initializer: " + parent.Name);
2429 // Classes can have base initializers and instance field initializers.
2431 if (parent is Class){
2432 if ((ModFlags & Modifiers.STATIC) == 0){
2433 Initializer.Emit (ec);
2434 parent.EmitFieldInitializers (ec, false);
2438 if ((ModFlags & Modifiers.STATIC) != 0)
2439 parent.EmitFieldInitializers (ec, true);
2441 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2443 ec.EmitTopBlock (Block, Location);
2447 public class Field : MemberCore {
2448 public readonly string Type;
2449 public readonly Object Initializer;
2450 public readonly Attributes OptAttributes;
2451 public FieldBuilder FieldBuilder;
2454 // Modifiers allowed in a class declaration
2456 const int AllowedModifiers =
2459 Modifiers.PROTECTED |
2460 Modifiers.INTERNAL |
2465 public Field (string type, int mod, string name, Object expr_or_array_init,
2466 Attributes attrs, Location loc)
2470 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
2471 Initializer = expr_or_array_init;
2472 OptAttributes = attrs;
2475 public override bool Define (TypeContainer parent)
2477 Type t = RootContext.LookupType (parent, Type, false, Location);
2482 if (!TypeContainer.AsAccessible (t, ModFlags))
2485 if (RootContext.WarningLevel > 1){
2486 Type ptype = parent.TypeBuilder.BaseType;
2488 // ptype is only null for System.Object while compiling corlib.
2492 mi = TypeContainer.FindMembers (
2493 ptype, MemberTypes.Method,
2494 BindingFlags.Public |
2495 BindingFlags.Static | BindingFlags.Instance,
2496 System.Type.FilterName, Name);
2500 FieldBuilder = parent.TypeBuilder.DefineField (
2501 Name, t, Modifiers.FieldAttr (ModFlags));
2506 public void Emit (TypeContainer tc)
2508 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
2510 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2514 public class Property : MemberCore {
2515 public readonly string Type;
2516 public Block Get, Set;
2517 public PropertyBuilder PropertyBuilder;
2518 public Attributes OptAttributes;
2519 MethodBuilder GetBuilder, SetBuilder;
2522 // The type, once we compute it.
2526 const int AllowedModifiers =
2529 Modifiers.PROTECTED |
2530 Modifiers.INTERNAL |
2534 Modifiers.OVERRIDE |
2535 Modifiers.ABSTRACT |
2538 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2539 Attributes attrs, Location loc)
2543 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2546 OptAttributes = attrs;
2550 // Checks our base implementation if any
2552 bool CheckBase (TypeContainer parent)
2555 // Find properties with the same name on the base class
2557 MemberInfo [] props;
2558 MemberInfo [] props_static = TypeContainer.FindMembers (
2559 parent.TypeBuilder.BaseType,
2560 MemberTypes.All, BindingFlags.Public | BindingFlags.Static,
2561 System.Type.FilterName, Name);
2563 MemberInfo [] props_instance = TypeContainer.FindMembers (
2564 parent.TypeBuilder.BaseType,
2565 MemberTypes.All, BindingFlags.Public | BindingFlags.Instance,
2566 System.Type.FilterName, Name);
2569 // Find if we have anything
2571 if (props_static != null && props_static.Length > 0)
2572 props = props_static;
2573 else if (props_instance != null && props_instance.Length > 0)
2574 props = props_instance;
2579 // If we have something on the base.
2580 if (props != null && props.Length > 0){
2583 // Currently we expect only to get 1 match at most from our
2584 // base class, maybe we can get more than one, investigate
2585 // whether this is possible
2587 if (props.Length > 1)
2588 throw new Exception ("How do we handle this?");
2590 PropertyInfo pi = (PropertyInfo) props [0];
2592 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2593 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2595 MethodInfo reference = inherited_get == null ?
2596 inherited_set : inherited_get;
2598 if (!CheckMethodAgainstBase (parent, reference))
2601 if ((ModFlags & Modifiers.NEW) != 0)
2602 WarningNotHiding (parent);
2604 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2605 Report.Error (115, Location,
2606 parent.MakeName (Name) +
2607 " no suitable methods found to override");
2614 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name, bool is_get)
2616 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
2617 Type [] parameters = null;
2618 MethodInfo implementing;
2622 flags |= MethodAttributes.HideBySig |
2623 MethodAttributes.SpecialName;
2626 fn_type = PropertyType;
2627 name = "get_" + short_name;
2629 name = "set_" + short_name;
2630 parameters = new Type [1];
2631 parameters [0] = PropertyType;
2632 fn_type = TypeManager.void_type;
2635 implementing = parent.IsInterfaceMethod (
2636 iface_type, name, fn_type, parameters, false);
2639 // For implicit implementations, make sure we are public, for
2640 // explicit implementations, make sure we are private.
2642 if (implementing != null){
2644 // Setting null inside this block will trigger a more
2645 // verbose error reporting for missing interface implementations
2647 // The "candidate" function has been flagged already
2648 // but it wont get cleared
2650 if (iface_type == null){
2651 if ((ModFlags & Modifiers.PUBLIC) == 0)
2652 implementing = null;
2653 if ((ModFlags & Modifiers.STATIC) != 0)
2654 implementing = null;
2656 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2658 106, Location, "`public' or `abstract' modifiers "+
2659 "are not allowed in explicit interface declarations"
2661 implementing = null;
2667 // If implementing is still valid, set flags
2669 if (implementing != null){
2671 MethodAttributes.Virtual |
2672 MethodAttributes.NewSlot |
2673 MethodAttributes.HideBySig;
2675 // If an interface implementation, then we can set Final.
2676 if (((flags & MethodAttributes.Abstract) == 0) &&
2677 implementing.DeclaringType.IsInterface)
2678 flags |= MethodAttributes.Final;
2681 // clear the pending flag
2683 parent.IsInterfaceMethod (
2684 iface_type, name, fn_type, parameters, true);
2688 GetBuilder = parent.TypeBuilder.DefineMethod (
2689 name, flags, PropertyType, null);
2690 PropertyBuilder.SetGetMethod (GetBuilder);
2692 if (implementing != null)
2693 parent.TypeBuilder.DefineMethodOverride (
2694 GetBuilder, implementing);
2697 // HACK because System.Reflection.Emit is lame
2699 InternalParameters ip = new InternalParameters (
2700 parent, Parameters.GetEmptyReadOnlyParameters ());
2702 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
2703 Report.Error (111, Location,
2704 "Class `" + parent.Name +
2705 "' already contains a definition with the " +
2706 "same return value and parameter types as the " +
2707 "'get' method of property `" + Name + "'");
2711 SetBuilder = parent.TypeBuilder.DefineMethod (
2712 name, flags, null, parameters);
2714 if (implementing != null)
2715 parent.TypeBuilder.DefineMethodOverride (
2716 SetBuilder, implementing);
2718 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2719 PropertyBuilder.SetSetMethod (SetBuilder);
2722 // HACK because System.Reflection.Emit is lame
2724 Parameter [] parms = new Parameter [1];
2725 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2726 InternalParameters ip = new InternalParameters (
2727 parent, new Parameters (parms, null, Location));
2729 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
2732 "Class `" + parent.Name +
2733 "' already contains a definition with the " +
2734 "same return value and parameter types as the " +
2735 "'set' method of property `" + Name + "'");
2743 public override bool Define (TypeContainer parent)
2745 Type iface_type = null;
2748 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2751 // Lookup Type, verify validity
2752 PropertyType = RootContext.LookupType (parent, Type, false, Location);
2753 if (PropertyType == null)
2756 // verify accessibility
2757 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
2760 if (!CheckBase (parent))
2764 // Check for explicit interface implementation
2766 if (Name.IndexOf (".") != -1){
2767 int pos = Name.LastIndexOf (".");
2768 string iface = Name.Substring (0, pos);
2770 iface_type = RootContext.LookupType (parent, iface, false, Location);
2771 if (iface_type == null)
2774 short_name = Name.Substring (pos + 1);
2776 // Compute the full name that we need to export.
2777 Name = iface_type.FullName + "." + short_name;
2781 // FIXME - PropertyAttributes.HasDefault ?
2783 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2784 PropertyAttributes.SpecialName;
2786 PropertyBuilder = parent.TypeBuilder.DefineProperty (
2787 Name, prop_attr, PropertyType, null);
2790 if (!DefineMethod (parent, iface_type, short_name, true))
2794 if (!DefineMethod (parent, iface_type, short_name, false))
2798 // HACK for the reasons exposed above
2800 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
2803 "Class `" + parent.Name +
2804 "' already contains a definition for the property `" +
2812 public void Emit (TypeContainer tc)
2817 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
2818 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
2822 // abstract or extern properties have no bodies
2824 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2828 ig = GetBuilder.GetILGenerator ();
2829 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
2831 ec.EmitTopBlock (Get, Location);
2835 ig = SetBuilder.GetILGenerator ();
2836 ec = new EmitContext (tc, Location, ig, null, ModFlags);
2838 ec.EmitTopBlock (Set, Location);
2845 /// Gigantic workaround for lameness in SRE follows :
2846 /// This class derived from EventInfo and attempts to basically
2847 /// wrap around the EventBuilder so that FindMembers can quickly
2848 /// return this in it search for members
2850 public class MyEventBuilder : EventInfo {
2853 // We use this to "point" to our Builder which is
2854 // not really a MemberInfo
2856 EventBuilder MyBuilder;
2859 // We "catch" and wrap these methods
2861 MethodInfo raise, remove, add;
2863 EventAttributes attributes;
2864 Type declaring_type, reflected_type, event_type;
2867 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
2869 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
2871 // And now store the values in our own fields.
2873 declaring_type = type_builder;
2875 // FIXME : This is supposed to be MyBuilder but since that doesn't
2876 // derive from Type, I have no clue what to do with this.
2877 reflected_type = null;
2879 attributes = event_attr;
2881 this.event_type = event_type;
2885 // Methods that you have to override. Note that you only need
2886 // to "implement" the variants that take the argument (those are
2887 // the "abstract" methods, the others (GetAddMethod()) are
2890 public override MethodInfo GetAddMethod (bool nonPublic)
2895 public override MethodInfo GetRemoveMethod (bool nonPublic)
2900 public override MethodInfo GetRaiseMethod (bool nonPublic)
2906 // These methods make "MyEventInfo" look like a Builder
2908 public void SetRaiseMethod (MethodBuilder raiseMethod)
2910 raise = raiseMethod;
2911 MyBuilder.SetRaiseMethod (raiseMethod);
2914 public void SetRemoveOnMethod (MethodBuilder removeMethod)
2916 remove = removeMethod;
2917 MyBuilder.SetRemoveOnMethod (removeMethod);
2920 public void SetAddOnMethod (MethodBuilder addMethod)
2923 MyBuilder.SetAddOnMethod (addMethod);
2926 public void SetCustomAttribute (CustomAttributeBuilder cb)
2928 MyBuilder.SetCustomAttribute (cb);
2931 public override object [] GetCustomAttributes (bool inherit)
2933 // FIXME : There's nothing which can be seemingly done here because
2934 // we have no way of getting at the custom attribute objects of the
2939 public override object [] GetCustomAttributes (Type t, bool inherit)
2941 // FIXME : Same here !
2945 public override bool IsDefined (Type t, bool b)
2950 public override EventAttributes Attributes {
2956 public override string Name {
2962 public override Type DeclaringType {
2964 return declaring_type;
2968 public override Type ReflectedType {
2970 return reflected_type;
2974 public Type EventType {
2981 public class Event : MemberCore {
2983 const int AllowedModifiers =
2986 Modifiers.PROTECTED |
2987 Modifiers.INTERNAL |
2992 Modifiers.OVERRIDE |
2995 public readonly string Type;
2996 public readonly Object Initializer;
2997 public readonly Block Add;
2998 public readonly Block Remove;
2999 public MyEventBuilder EventBuilder;
3000 public FieldBuilder FieldBuilder;
3001 public Attributes OptAttributes;
3004 MethodBuilder AddBuilder, RemoveBuilder;
3007 public Event (string type, string name, Object init, int flags, Block add_block,
3008 Block rem_block, Attributes attrs, Location loc)
3013 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
3016 OptAttributes = attrs;
3019 public override bool Define (TypeContainer parent)
3021 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3024 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3025 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3027 EventType = RootContext.LookupType (parent, Type, false, Location);
3028 if (EventType == null)
3031 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3035 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3036 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3037 "' : event must be of a delegate type");
3041 Type [] parameters = new Type [1];
3042 parameters [0] = EventType;
3044 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3046 if (Add == null && Remove == null)
3047 FieldBuilder = parent.TypeBuilder.DefineField (Name, EventType, FieldAttributes.Private);
3050 // Now define the accessors
3053 AddBuilder = parent.TypeBuilder.DefineMethod (
3054 "add_" + Name, m_attr, null, parameters);
3055 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3056 EventBuilder.SetAddOnMethod (AddBuilder);
3059 // HACK because System.Reflection.Emit is lame
3061 Parameter [] parms = new Parameter [1];
3062 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3063 InternalParameters ip = new InternalParameters (
3064 parent, new Parameters (parms, null, Location));
3066 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3067 Report.Error (111, Location,
3068 "Class `" + parent.Name + "' already contains a definition with the " +
3069 "same return value and parameter types for the " +
3070 "'add' method of event `" + Name + "'");
3074 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3075 "remove_" + Name, m_attr, null, parameters);
3076 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3077 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3080 // HACK because System.Reflection.Emit is lame
3083 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3084 Report.Error (111, Location,
3085 "Class `" + parent.Name + "' already contains a definition with the " +
3086 "same return value and parameter types for the " +
3087 "'remove' method of event `" + Name + "'");
3091 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3092 Report.Error (111, Location,
3093 "Class `" + parent.Name +
3094 "' already contains a definition for the event `" +
3102 void EmitDefaultMethod (EmitContext ec, bool is_add)
3104 ILGenerator ig = ec.ig;
3105 MethodInfo method = null;
3108 method = TypeManager.delegate_combine_delegate_delegate;
3110 method = TypeManager.delegate_remove_delegate_delegate;
3112 ig.Emit (OpCodes.Ldarg_0);
3113 ig.Emit (OpCodes.Ldarg_0);
3114 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3115 ig.Emit (OpCodes.Ldarg_1);
3116 ig.Emit (OpCodes.Call, method);
3117 ig.Emit (OpCodes.Castclass, EventType);
3118 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3119 ig.Emit (OpCodes.Ret);
3122 public void Emit (TypeContainer tc)
3127 ig = AddBuilder.GetILGenerator ();
3128 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3131 ec.EmitTopBlock (Add, Location);
3133 EmitDefaultMethod (ec, true);
3135 ig = RemoveBuilder.GetILGenerator ();
3136 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3139 ec.EmitTopBlock (Remove, Location);
3141 EmitDefaultMethod (ec, false);
3143 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3144 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3151 // FIXME: This does not handle:
3153 // int INTERFACENAME [ args ]
3157 // int this [ args ]
3159 public class Indexer : MemberCore {
3161 const int AllowedModifiers =
3164 Modifiers.PROTECTED |
3165 Modifiers.INTERNAL |
3169 Modifiers.OVERRIDE |
3172 public readonly string Type;
3173 public readonly string InterfaceType;
3174 public readonly Parameters FormalParameters;
3175 public readonly Block Get;
3176 public readonly Block Set;
3177 public Attributes OptAttributes;
3178 public MethodBuilder GetBuilder;
3179 public MethodBuilder SetBuilder;
3180 public PropertyBuilder PropertyBuilder;
3181 public Type IndexerType;
3183 public Indexer (string type, string int_type, int flags, Parameters parms,
3184 Block get_block, Block set_block, Attributes attrs, Location loc)
3189 InterfaceType = int_type;
3190 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
3191 FormalParameters = parms;
3194 OptAttributes = attrs;
3197 void DefineMethod (TypeContainer parent, Type iface_type,
3198 Type ret_type, string name,
3199 Type [] parameters, bool is_get)
3201 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3202 MethodInfo implementing;
3204 implementing = parent.IsInterfaceMethod (
3205 iface_type, name, ret_type, parameters, false);
3208 // Setting null inside this block will trigger a more
3209 // verbose error reporting for missing interface implementations
3211 // The "candidate" function has been flagged already
3212 // but it wont get cleared
3214 if (implementing != null){
3215 if (iface_type == null){
3216 if ((ModFlags & Modifiers.PUBLIC) == 0)
3217 implementing = null;
3218 if ((ModFlags & Modifiers.STATIC) != 0)
3219 implementing = null;
3221 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3224 "`public' or `abstract' modifiers are not "+
3225 "allowed in explicit interface declarations"
3227 implementing = null;
3231 if (implementing != null){
3233 MethodAttributes.Virtual |
3234 MethodAttributes.NewSlot |
3235 MethodAttributes.HideBySig;
3237 // If an interface implementing, then we can set final.
3238 if (((attr & MethodAttributes.Abstract) == 0) &&
3239 implementing.DeclaringType.IsInterface)
3240 attr |= MethodAttributes.Final;
3243 // clear the pending flag
3245 parent.IsInterfaceMethod (
3246 iface_type, name, ret_type, parameters, true);
3250 GetBuilder = parent.TypeBuilder.DefineMethod (
3251 "get_Item", attr, IndexerType, parameters);
3252 if (implementing != null)
3253 parent.TypeBuilder.DefineMethodOverride (
3254 GetBuilder, implementing);
3256 PropertyBuilder.SetGetMethod (GetBuilder);
3258 SetBuilder = parent.TypeBuilder.DefineMethod (
3259 "set_Item", attr, null, parameters);
3260 if (implementing != null)
3261 parent.TypeBuilder.DefineMethodOverride (
3262 SetBuilder, implementing);
3264 PropertyBuilder.SetSetMethod (SetBuilder);
3268 public override bool Define (TypeContainer parent)
3270 PropertyAttributes prop_attr =
3271 PropertyAttributes.RTSpecialName |
3272 PropertyAttributes.SpecialName;
3275 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3276 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3278 // Check if the return type and arguments were correct
3279 if (IndexerType == null || parameters == null)
3283 // verify accessibility
3285 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3288 foreach (Type partype in parameters)
3289 if (!TypeContainer.AsAccessible (partype, ModFlags))
3295 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3296 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3297 prop_attr, IndexerType, parameters);
3300 // FIXME: Implement explicit implementation
3302 Type iface_type = null;
3305 DefineMethod (parent, iface_type, IndexerType, "get_Item", parameters, true);
3306 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3307 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3308 Report.Error (111, Location,
3309 "Class `" + parent.Name +
3310 "' already contains a definition with the " +
3311 "same return value and parameter types for the " +
3318 int top = parameters.Length;
3319 Type [] set_pars = new Type [top + 1];
3320 parameters.CopyTo (set_pars, 0);
3321 set_pars [top] = IndexerType;
3323 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3325 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3327 fixed_parms.CopyTo (tmp, 0);
3328 tmp [fixed_parms.Length] = new Parameter (
3329 Type, "value", Parameter.Modifier.NONE, null);
3331 Parameters set_formal_params = new Parameters (tmp, null, Location);
3334 parent, iface_type, TypeManager.void_type,
3335 "set_Item", set_pars, false);
3337 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3339 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3342 "Class `" + parent.Name + "' already contains a " +
3343 "definition with the " +
3344 "same return value and parameter types for the " +
3351 // Now name the parameters
3353 Parameter [] p = FormalParameters.FixedParameters;
3357 for (i = 0; i < p.Length; ++i) {
3359 GetBuilder.DefineParameter (
3360 i + 1, p [i].Attributes, p [i].Name);
3363 SetBuilder.DefineParameter (
3364 i + 1, p [i].Attributes, p [i].Name);
3368 SetBuilder.DefineParameter (
3369 i + 1, ParameterAttributes.None, "value");
3371 if (i != parameters.Length) {
3372 Parameter array_param = FormalParameters.ArrayParameter;
3373 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3378 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3383 public void Emit (TypeContainer tc)
3388 ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3389 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3392 ig = GetBuilder.GetILGenerator ();
3393 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3395 ec.EmitTopBlock (Get, Location);
3399 ig = SetBuilder.GetILGenerator ();
3400 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3402 ec.EmitTopBlock (Set, Location);
3407 public class Operator : MemberCore {
3409 const int AllowedModifiers =
3413 const int RequiredModifiers =
3417 public enum OpType : byte {
3427 // Unary and Binary operators
3450 // Implicit and Explicit
3455 public readonly OpType OperatorType;
3456 public readonly string ReturnType;
3457 public readonly string FirstArgType;
3458 public readonly string FirstArgName;
3459 public readonly string SecondArgType;
3460 public readonly string SecondArgName;
3461 public readonly Block Block;
3462 public Attributes OptAttributes;
3463 public MethodBuilder OperatorMethodBuilder;
3465 public string MethodName;
3466 public Method OperatorMethod;
3468 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3469 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3472 OperatorType = type;
3473 ReturnType = ret_type;
3474 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
3475 FirstArgType = arg1type;
3476 FirstArgName = arg1name;
3477 SecondArgType = arg2type;
3478 SecondArgName = arg2name;
3480 OptAttributes = attrs;
3483 string Prototype (TypeContainer parent)
3485 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3486 SecondArgType + ")";
3489 public override bool Define (TypeContainer parent)
3492 MethodName = "op_" + OperatorType;
3494 if (SecondArgType != null)
3497 Parameter [] param_list = new Parameter [length];
3499 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3502 "User defined operators `" +
3503 Prototype (parent) +
3504 "' must be declared static and public");
3508 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3509 Parameter.Modifier.NONE, null);
3510 if (SecondArgType != null)
3511 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3512 Parameter.Modifier.NONE, null);
3514 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3515 new Parameters (param_list, null, Location),
3516 OptAttributes, Mono.CSharp.Location.Null);
3518 OperatorMethod.Define (parent);
3520 if (OperatorMethod.MethodBuilder == null)
3523 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3525 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3526 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3527 Type return_type = OperatorMethod.GetReturnType (parent);
3528 Type first_arg_type = param_types [0];
3530 // Rules for conversion operators
3532 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3533 if (first_arg_type == return_type && first_arg_type == declaring_type){
3536 "User-defined conversion cannot take an object of the " +
3537 "enclosing type and convert to an object of the enclosing" +
3542 if (first_arg_type != declaring_type && return_type != declaring_type){
3545 "User-defined conversion must convert to or from the " +
3550 if (first_arg_type == TypeManager.object_type ||
3551 return_type == TypeManager.object_type){
3554 "User-defined conversion cannot convert to or from " +
3559 if (first_arg_type.IsInterface || return_type.IsInterface){
3562 "User-defined conversion cannot convert to or from an " +
3567 if (first_arg_type.IsSubclassOf (return_type) ||
3568 return_type.IsSubclassOf (first_arg_type)){
3571 "User-defined conversion cannot convert between types " +
3572 "that derive from each other");
3575 } else if (SecondArgType == null) {
3576 // Checks for Unary operators
3578 if (first_arg_type != declaring_type){
3581 "The parameter of a unary operator must be the " +
3586 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3587 if (return_type != declaring_type){
3590 "The parameter and return type for ++ and -- " +
3591 "must be the containing type");
3597 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3598 if (return_type != TypeManager.bool_type){
3601 "The return type of operator True or False " +
3608 // Checks for Binary operators
3610 if (first_arg_type != declaring_type &&
3611 param_types [1] != declaring_type){
3614 "One of the parameters of a binary operator must " +
3615 "be the containing type");
3623 public void Emit (TypeContainer parent)
3625 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3626 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3628 OperatorMethod.Block = Block;
3629 OperatorMethod.Emit (parent);
3634 // This is used to compare method signatures
3636 struct MethodSignature {
3638 public Type RetType;
3639 public Type [] Parameters;
3641 public MethodSignature (string name, Type ret_type, Type [] parameters)
3645 Parameters = parameters;
3648 public override int GetHashCode ()
3650 return Name.GetHashCode ();
3653 public override bool Equals (Object o)
3655 MethodSignature other = (MethodSignature) o;
3657 if (other.Name != Name)
3660 if (other.RetType != RetType)
3663 if (Parameters == null){
3664 if (other.Parameters == null)
3669 if (other.Parameters == null)
3672 int c = Parameters.Length;
3673 if (other.Parameters.Length != c)
3676 for (int i = 0; i < c; i++)
3677 if (other.Parameters [i] != Parameters [i])