2 // class.cs: Class and Struct handlers
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
19 public class TypeContainer : DeclSpace {
20 protected int mod_flags;
22 // Holds a list of classes and structures
25 // Holds the list of properties
28 // Holds the list of enumerations
31 // Holds the list of delegates
34 // Holds the list of constructors
35 ArrayList constructors;
37 // Holds the list of fields
40 // Holds a list of fields that have initializers
41 ArrayList initialized_fields;
43 // Holds a list of static fields that have initializers
44 ArrayList initialized_static_fields;
46 // Holds the list of constants
61 // Holds the operators
64 // Maps MethodBuilders to Methods
65 static Hashtable method_builders_to_parameters;
68 // Pointers to the default constructor and the default static constructor
70 Constructor default_constructor;
71 Constructor default_static_constructor;
74 // Whether we have seen a static constructor for this class or not
76 bool have_static_constructor = false;
79 // This is the namespace in which this typecontainer
80 // was declared. We use this to resolve names.
82 Namespace my_namespace;
85 // This one is computed after we can distinguish interfaces
86 // from classes from the arraylist `type_bases'
88 string base_class_name;
94 // This behaves like a property ;-)
96 public readonly RootContext RootContext;
98 // Attributes for this type
99 protected Attributes attributes;
101 public TypeContainer (RootContext rc, TypeContainer parent, string name, Location l)
105 types = new ArrayList ();
106 this.parent = parent;
114 base_class_name = null;
116 //Console.WriteLine ("New class " + name + " inside " + n);
119 public AdditionResult AddConstant (Constant constant)
122 string name = constant.Name;
124 if ((res = IsValid (name)) != AdditionResult.Success)
127 if (constants == null)
128 constants = new ArrayList ();
130 constants.Add (constant);
131 DefineName (name, constant);
133 return AdditionResult.Success;
136 public AdditionResult AddEnum (CIR.Enum e)
139 string name = e.Name;
141 if ((res = IsValid (name)) != AdditionResult.Success)
145 enums = new ArrayList ();
148 DefineName (name, e);
150 return AdditionResult.Success;
153 public AdditionResult AddClass (Class c)
156 string name = c.Name;
159 if ((res = IsValid (name)) != AdditionResult.Success)
162 DefineName (name, c);
165 return AdditionResult.Success;
168 public AdditionResult AddStruct (Struct s)
171 string name = s.Name;
173 if ((res = IsValid (name)) != AdditionResult.Success)
176 DefineName (name, s);
179 return AdditionResult.Success;
182 public AdditionResult AddDelegate (Delegate d)
185 string name = d.Name;
187 if ((res = IsValid (name)) != AdditionResult.Success)
190 if (delegates == null)
191 delegates = new ArrayList ();
193 DefineName (name, d);
196 return AdditionResult.Success;
199 public AdditionResult AddMethod (Method method)
201 string name = method.Name;
202 Object value = defined_names [name];
204 if (value != null && (!(value is Method)))
205 return AdditionResult.NameExists;
208 methods = new ArrayList ();
210 methods.Add (method);
212 DefineName (name, method);
214 return AdditionResult.Success;
217 public AdditionResult AddConstructor (Constructor c)
219 if (c.Name != Basename)
220 return AdditionResult.NotAConstructor;
222 if (constructors == null)
223 constructors = new ArrayList ();
225 constructors.Add (c);
227 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
230 have_static_constructor = true;
232 if (c.IsDefault ()) {
234 default_static_constructor = c;
236 default_constructor = c;
239 return AdditionResult.Success;
242 public AdditionResult AddInterface (Interface iface)
245 string name = iface.Name;
247 if ((res = IsValid (name)) != AdditionResult.Success)
250 if (interfaces == null)
251 interfaces = new ArrayList ();
252 interfaces.Add (iface);
253 DefineName (name, iface);
255 return AdditionResult.Success;
258 public AdditionResult AddField (Field field)
261 string name = field.Name;
263 if ((res = IsValid (name)) != AdditionResult.Success)
267 fields = new ArrayList ();
270 if (field.Initializer != null){
271 if ((field.ModFlags & Modifiers.STATIC) != 0){
272 if (initialized_static_fields == null)
273 initialized_static_fields = new ArrayList ();
275 initialized_static_fields.Add (field);
278 // We have not seen a static constructor,
279 // but we will provide static initialization of fields
281 have_static_constructor = true;
283 if (initialized_fields == null)
284 initialized_fields = new ArrayList ();
286 initialized_fields.Add (field);
290 DefineName (name, field);
291 return AdditionResult.Success;
294 public AdditionResult AddProperty (Property prop)
297 string name = prop.Name;
299 if ((res = IsValid (name)) != AdditionResult.Success)
302 if (properties == null)
303 properties = new ArrayList ();
305 properties.Add (prop);
306 DefineName (name, prop);
308 return AdditionResult.Success;
311 public AdditionResult AddEvent (Event e)
314 string name = e.Name;
316 if ((res = IsValid (name)) != AdditionResult.Success)
320 events = new ArrayList ();
323 DefineName (name, e);
325 return AdditionResult.Success;
328 public AdditionResult AddIndexer (Indexer i)
330 if (indexers == null)
331 indexers = new ArrayList ();
335 return AdditionResult.Success;
338 public AdditionResult AddOperator (Operator op)
340 if (operators == null)
341 operators = new ArrayList ();
345 return AdditionResult.Success;
348 public TypeContainer Parent {
354 public ArrayList Types {
360 public ArrayList Methods {
366 public ArrayList Constants {
372 public ArrayList Interfaces {
378 public int ModFlags {
386 return base_class_name;
390 public ArrayList Bases {
400 public ArrayList Fields {
406 public ArrayList Constructors {
412 public ArrayList Properties {
418 public ArrayList Events {
424 public ArrayList Enums {
430 public ArrayList Indexers {
436 public ArrayList Operators {
442 public ArrayList Delegates {
448 public Attributes OptAttributes {
454 public Namespace Namespace {
460 my_namespace = value;
465 // root_types contains all the types. All TopLevel types
466 // hence have a parent that points to `root_types', that is
467 // why there is a non-obvious test down here.
469 public bool IsTopLevel {
472 if (parent.Parent == null)
479 public bool HaveStaticConstructor {
481 return have_static_constructor;
485 public virtual TypeAttributes TypeAttr {
487 return Modifiers.TypeAttr (mod_flags, this);
492 // Emits the instance field initializers
494 public bool EmitFieldInitializers (EmitContext ec, bool is_static)
497 ILGenerator ig = ec.ig;
500 fields = initialized_static_fields;
502 fields = initialized_fields;
507 foreach (Field f in fields){
508 Object init = f.Initializer;
510 if (init is Expression){
511 Expression e = (Expression) init;
518 ig.Emit (OpCodes.Ldarg_0);
523 ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
525 ig.Emit (OpCodes.Stfld, f.FieldBuilder);
533 // Defines the default constructors
535 void DefineDefaultConstructor (bool is_static)
540 c = new Constructor (Basename, new Parameters (null, null),
541 new ConstructorBaseInitializer (null, new Location (-1)),
546 c.Block = new Block (null);
549 mods = Modifiers.STATIC;
555 public void ReportStructInitializedInstanceError ()
557 string n = TypeBuilder.FullName;
559 foreach (Field f in initialized_fields){
562 "`" + n + "." + f.Name + "': can not have " +
563 "instance field initializers in structs");
567 public void RegisterRequiredImplementations ()
569 Type [] ifaces = TypeBuilder.GetInterfaces ();
570 Type b = TypeBuilder.BaseType;
573 SetRequiredInterfaces (ifaces);
576 MemberInfo [] abstract_methods;
578 abstract_methods = FindMembers (
579 TypeBuilder.BaseType,
580 MemberTypes.Method, BindingFlags.Public,
581 abstract_method_filter, null);
583 if (abstract_methods != null){
584 MethodInfo [] mi = new MethodInfo [abstract_methods.Length];
586 abstract_methods.CopyTo (mi, 0);
587 RequireMethods (mi, b);
593 static object MakeKey (MethodBase mb)
595 if (mb is MethodBuilder || mb is ConstructorBuilder)
596 return mb.ReflectedType.FullName + ":" + mb;
598 return mb.MethodHandle.ToString ();
602 public static string MakeFQN (string nsn, string name)
604 string prefix = (nsn == "" ? "" : nsn + ".");
606 return prefix + name;
609 Type LookupInterfaceOrClass (object builder, string ns, string name, bool is_class, out bool error)
611 TypeContainer parent;
615 name = MakeFQN (ns, name);
617 t = RootContext.TypeManager.LookupType (name);
622 parent = (Class) RootContext.Tree.Classes [name];
624 parent = (Struct) RootContext.Tree.Structs [name];
628 t = parent.DefineType (builder);
630 Report.Error (146, "Class definition is circular: `"+name+"'");
642 // returns the type for an interface or a class, this will recursively
643 // try to define the types that it depends on.
645 Type GetInterfaceOrClass (object builder, string name, bool is_class)
651 // Attempt to lookup the class on our namespace
653 t = LookupInterfaceOrClass (builder, Namespace.Name, name, is_class, out error);
661 // Attempt to do a direct unqualified lookup
663 t = LookupInterfaceOrClass (builder, "", name, is_class, out error);
671 // Attempt to lookup the class on any of the `using'
675 for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
676 ArrayList using_list = ns.UsingTable;
678 if (using_list == null)
681 foreach (string n in using_list){
682 t = LookupInterfaceOrClass (builder, n, name, is_class, out error);
691 Report.Error (246, "Can not find type `"+name+"'");
696 // This function computes the Base class and also the
697 // list of interfaces that the class or struct @c implements.
699 // The return value is an array (might be null) of
700 // interfaces implemented (as Types).
702 // The @parent argument is set to the parent object or null
703 // if this is `System.Object'.
705 Type [] GetClassBases (object builder, bool is_class, out Type parent, out bool error)
707 ArrayList bases = Bases;
716 parent = TypeManager.value_type;
720 if (RootContext.StdLib)
721 parent = TypeManager.object_type;
722 else if (Name != "System.Object")
723 parent = TypeManager.object_type;
726 // If we are compiling our runtime,
727 // and we are defining ValueType, then our
728 // parent is `System.Object'.
730 if (!RootContext.StdLib && Name == "System.ValueType")
731 parent = TypeManager.object_type;
738 // Bases should be null if there are no bases at all
743 string name = (string) bases [0];
744 Type first = GetInterfaceOrClass (builder, name, is_class);
755 parent = TypeManager.object_type;
762 Type [] ifaces = new Type [count-start];
764 for (i = start, j = 0; i < count; i++, j++){
765 string name = (string) bases [i];
766 Type t = GetInterfaceOrClass (builder, name, is_class);
773 if (is_class == false && !t.IsInterface){
774 Report.Error (527, "In Struct `" + Name + "', type `"+
775 name +"' is not an interface");
784 detail = " (a class can not inherit from a struct)";
786 Report.Error (509, "class `"+ Name +
787 "': Cannot inherit from sealed class `"+
788 bases [i]+"'"+detail);
795 Report.Error (527, "In Class `" + Name + "', type `"+
796 name+"' is not an interface");
809 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
811 public TypeBuilder DefineType (object parent_builder)
828 ifaces = GetClassBases (parent_builder, is_class, out parent, out error);
833 if (parent_builder is ModuleBuilder) {
834 ModuleBuilder builder = (ModuleBuilder) parent_builder;
837 // Structs with no fields need to have a ".size 1"
840 if (!is_class && Fields == null)
841 TypeBuilder = builder.DefineType (Name,
844 PackingSize.Unspecified, 1);
847 // classes or structs with fields
849 TypeBuilder = builder.DefineType (Name,
855 TypeBuilder builder = (TypeBuilder) parent_builder;
858 // Structs with no fields need to have a ".size 1"
861 if (!is_class && Fields == null)
862 TypeBuilder = builder.DefineNestedType (Name,
865 PackingSize.Unspecified);
868 // classes or structs with fields
870 TypeBuilder = builder.DefineNestedType (Name,
876 RootContext.TypeManager.AddUserType (Name, TypeBuilder, this);
879 foreach (TypeContainer tc in Types)
880 tc.DefineType (TypeBuilder);
883 if (Delegates != null) {
884 foreach (Delegate d in Delegates)
885 d.DefineDelegate (TypeBuilder);
889 foreach (Enum en in Enums)
890 en.DefineEnum (TypeBuilder);
898 // Populates our TypeBuilder with fields and methods
900 public void Populate ()
902 if (Constants != null){
903 foreach (Constant c in Constants)
904 c.EmitConstant (RootContext, this);
908 foreach (Field f in Fields)
912 if (this is Class && constructors == null){
913 if (default_constructor == null)
914 DefineDefaultConstructor (false);
916 if (initialized_static_fields != null &&
917 default_static_constructor == null)
918 DefineDefaultConstructor (true);
923 // Structs can not have initialized instance
926 if (initialized_static_fields != null &&
927 default_static_constructor == null)
928 DefineDefaultConstructor (true);
930 if (initialized_fields != null)
931 ReportStructInitializedInstanceError ();
934 RegisterRequiredImplementations ();
936 ArrayList remove_list = new ArrayList ();
938 if (constructors != null || methods != null ||
939 properties != null || operators != null){
940 if (method_builders_to_parameters == null)
941 method_builders_to_parameters = new Hashtable ();
944 if (constructors != null){
945 foreach (Constructor c in constructors){
946 MethodBase builder = c.Define (this);
951 InternalParameters ip = c.ParameterInfo;
953 method_builders_to_parameters.Add (MakeKey (builder), ip);
957 foreach (object o in remove_list)
958 constructors.Remove (o);
960 remove_list.Clear ();
963 if (Methods != null){
964 foreach (Method m in methods){
965 MethodBase key = m.Define (this);
969 // The following key is not enoug
970 // class x { public void X () {} }
971 // class y : x { public void X () {}}
977 InternalParameters ip = m.ParameterInfo;
978 method_builders_to_parameters.Add (MakeKey (key), ip);
981 foreach (object o in remove_list)
984 remove_list.Clear ();
987 if (Properties != null) {
988 foreach (Property p in Properties)
992 if (Events != null) {
993 foreach (Event e in Events)
997 if (Indexers != null) {
998 foreach (Indexer i in Indexers)
1002 if (Operators != null) {
1003 foreach (Operator o in Operators) {
1006 InternalParameters ip = o.OperatorMethod.ParameterInfo;
1008 method_builders_to_parameters.Add (
1009 MakeKey (o.OperatorMethodBuilder), ip);
1014 foreach (Enum en in Enums)
1017 if (Delegates != null) {
1018 foreach (Delegate d in Delegates)
1022 if (Types != null) {
1023 foreach (TypeContainer tc in Types)
1031 // Since System.Reflection.Emit can not retrieve parameter information
1032 // from methods that are dynamically defined, we have to look those
1033 // up ourselves using this
1035 static public ParameterData LookupParametersByBuilder (MethodBase mb)
1037 return (ParameterData) method_builders_to_parameters [MakeKey (mb)];
1041 // Indexers and properties can register more than one method at once,
1042 // so we need to provide a mechanism for those to register their
1043 // various methods to parameter info mappers.
1045 static public void RegisterParameterForBuilder (MethodBase mb, InternalParameters pi)
1047 method_builders_to_parameters.Add (MakeKey (mb), pi);
1050 public Type LookupType (string name, bool silent)
1052 return RootContext.LookupType (this, name, silent);
1055 public string LookupAlias (string Name)
1058 // Read the comments on `mcs/mcs/TODO' for details
1064 // This function is based by a delegate to the FindMembers routine
1066 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1072 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
1074 MethodInfo mi = (MethodInfo) m;
1076 return mi.IsAbstract;
1079 // This filter is used by FindMembers, and we just keep
1080 // a global for the filter to `AlwaysAccept'
1082 static MemberFilter accepting_filter;
1085 // This delegate is a MemberFilter used to extract the
1086 // abstact methods from a type.
1088 static MemberFilter abstract_method_filter;
1090 static TypeContainer ()
1092 abstract_method_filter = new MemberFilter (IsAbstractMethod);
1093 accepting_filter = new MemberFilter (AlwaysAccept);
1097 // This method returns the members of this type just like Type.FindMembers would
1098 // Only, we need to use this for types which are _being_ defined because MS'
1099 // implementation can't take care of that.
1101 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1102 MemberFilter filter, object criteria)
1104 ArrayList members = new ArrayList ();
1107 filter = accepting_filter;
1109 if ((mt & MemberTypes.Field) != 0 && Fields != null) {
1110 foreach (Field f in Fields) {
1111 if (filter (f.FieldBuilder, criteria) == true)
1112 members.Add (f.FieldBuilder);
1116 if ((mt & MemberTypes.Method) != 0) {
1117 if (Methods != null){
1118 foreach (Method m in Methods) {
1119 MethodBuilder mb = m.MethodBuilder;
1121 if (filter (mb, criteria) == true)
1126 if (Operators != null){
1127 foreach (Operator o in Operators) {
1128 MethodBuilder ob = o.OperatorMethodBuilder;
1130 if (filter (ob, criteria) == true)
1136 // FIXME : This ain't right because EventBuilder is not a
1137 // MemberInfo. What do we do ?
1139 if ((mt & MemberTypes.Event) != 0 && Events != null) {
1140 //foreach (Event e in Events) {
1141 // if (filter (e.EventBuilder, criteria) == true)
1142 // mi [i++] = e.EventBuilder;
1146 if ((mt & MemberTypes.Property) != 0){
1147 if (Properties != null)
1148 foreach (Property p in Properties) {
1149 if (filter (p.PropertyBuilder, criteria) == true)
1150 members.Add (p.PropertyBuilder);
1153 if (Indexers != null)
1154 foreach (Indexer ix in Indexers){
1155 if (filter (ix.PropertyBuilder, criteria) == true)
1156 members.Add (ix.PropertyBuilder);
1160 if ((mt & MemberTypes.NestedType) != 0 && Types != null) {
1161 foreach (TypeContainer t in Types) {
1162 if (filter (t.TypeBuilder, criteria) == true)
1163 members.Add (t.TypeBuilder);
1167 if ((mt & MemberTypes.Constructor) != 0){
1168 if (Constructors != null){
1169 foreach (Constructor c in Constructors){
1170 ConstructorBuilder cb = c.ConstructorBuilder;
1172 if (filter (cb, criteria) == true)
1179 // Lookup members in parent if requested.
1181 if ((bf & BindingFlags.DeclaredOnly) == 0){
1184 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1186 members.AddRange (mi);
1189 int count = members.Count;
1191 MemberInfo [] mi = new MemberInfo [count];
1192 members.CopyTo (mi);
1199 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1200 MemberFilter filter, object criteria)
1202 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1205 return tc.FindMembers (mt, bf, filter, criteria);
1207 return t.FindMembers (mt, bf, filter, criteria);
1211 Hashtable pending_implementations;
1214 // Requires that the methods in `mi' be implemented for this
1217 public void RequireMethods (MethodInfo [] mi, object data)
1219 if (pending_implementations == null)
1220 pending_implementations = new Hashtable ();
1222 foreach (MethodInfo m in mi){
1223 Type [] types = TypeManager.GetArgumentTypes (m);
1225 pending_implementations.Add (
1227 (m.Name, m.ReturnType, types), data);
1232 // Used to set the list of interfaces that this typecontainer
1237 // For each element exposed by the type, we create a MethodSignature
1238 // struct that we will label as `implemented' as we define the various
1241 public void SetRequiredInterfaces (Type [] ifaces)
1243 foreach (Type t in ifaces){
1246 if (t is TypeBuilder){
1247 Interface iface = RootContext.TypeManager.LookupInterface (t);
1249 mi = iface.GetMethods ();
1251 mi = t.GetMethods ();
1253 RequireMethods (mi, t);
1258 // If a method with name `Name', return type `ret_type' and
1259 // arguments `args' implements an interface, this method will
1262 // This will remove the method from the list of "pending" methods
1263 // that are required to be implemented for this class as a side effect.
1266 public bool IsInterfaceMethod (string Name, Type ret_type, Type [] args)
1268 MethodSignature query;
1270 if (pending_implementations == null)
1273 query = new MethodSignature (Name, ret_type, args);
1275 if (pending_implementations.Contains (query)){
1276 pending_implementations.Remove (query);
1284 // Verifies that any pending abstract methods or interface methods
1285 // were implemented.
1287 void VerifyPendingMethods ()
1291 foreach (object m in pending_implementations){
1292 DictionaryEntry de = (DictionaryEntry) m;
1293 Type t = (Type) de.Value;
1296 MethodSignature method = (MethodSignature) de.Key;
1301 "`" + Name + "' does not implement interface member `" +
1302 t.FullName + "." + method.Name + "'");
1306 "`" + Name + "' does not implement inherited abstract " +
1307 "member `" + t.FullName + "." + method.Name + "'");
1312 // Emits the code, this step is performed after all
1313 // the types, enumerations, constructors
1317 if (Constructors != null)
1318 foreach (Constructor c in Constructors)
1321 if (methods != null)
1322 foreach (Method m in methods)
1325 if (operators != null)
1326 foreach (Operator o in operators)
1329 if (properties != null)
1330 foreach (Property p in properties)
1333 if (indexers != null)
1334 foreach (Indexer ix in indexers)
1338 foreach (Field f in fields)
1342 foreach (Event e in Events)
1345 if (pending_implementations != null)
1346 VerifyPendingMethods ();
1348 if (OptAttributes != null) {
1349 EmitContext ec = new EmitContext (this, null, null, ModFlags, false);
1351 if (OptAttributes.AttributeSections != null) {
1352 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
1353 if (asec.Attributes != null) {
1354 foreach (Attribute a in asec.Attributes) {
1355 CustomAttributeBuilder cb = a.Resolve (ec);
1357 TypeBuilder.SetCustomAttribute (cb);
1365 foreach (TypeContainer tc in types)
1369 public void CloseType ()
1372 TypeBuilder.CreateType ();
1373 } catch (InvalidOperationException e){
1374 Console.WriteLine ("Exception while creating class: " + TypeBuilder.Name);
1375 Console.WriteLine ("Message:" + e.Message);
1379 foreach (TypeContainer tc in Types)
1383 foreach (Enum en in Enums)
1386 if (Delegates != null)
1387 foreach (Delegate d in Delegates)
1391 string MakeName (string n)
1393 return "`" + Name + "." + n + "'";
1396 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1402 public class Class : TypeContainer {
1404 // Modifiers allowed in a class declaration
1406 public const int AllowedModifiers =
1409 Modifiers.PROTECTED |
1410 Modifiers.INTERNAL |
1412 Modifiers.ABSTRACT |
1415 public Class (RootContext rc, TypeContainer parent, string name, int mod,
1416 Attributes attrs, Location l)
1417 : base (rc, parent, name, l)
1421 if (parent.Parent == null)
1422 accmods = Modifiers.INTERNAL;
1424 accmods = Modifiers.PRIVATE;
1426 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1427 this.attributes = attrs;
1431 // FIXME: How do we deal with the user specifying a different
1434 public override TypeAttributes TypeAttr {
1436 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1441 public class Struct : TypeContainer {
1443 // Modifiers allowed in a struct declaration
1445 public const int AllowedModifiers =
1448 Modifiers.PROTECTED |
1449 Modifiers.INTERNAL |
1452 public Struct (RootContext rc, TypeContainer parent, string name, int mod,
1453 Attributes attrs, Location l)
1454 : base (rc, parent, name, l)
1458 if (parent.Parent == null)
1459 accmods = Modifiers.INTERNAL;
1461 accmods = Modifiers.PRIVATE;
1463 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1465 this.mod_flags |= Modifiers.SEALED;
1466 this.attributes = attrs;
1471 // FIXME: Allow the user to specify a different set of attributes
1472 // in some cases (Sealed for example is mandatory for a class,
1473 // but what SequentialLayout can be changed
1475 public override TypeAttributes TypeAttr {
1477 return base.TypeAttr |
1478 TypeAttributes.SequentialLayout |
1479 TypeAttributes.Sealed |
1480 TypeAttributes.BeforeFieldInit;
1485 public class MethodCore {
1486 public readonly Parameters Parameters;
1487 public readonly string Name;
1488 public int ModFlags;
1490 public readonly Location Location;
1493 // Parameters, cached for semantic analysis.
1495 InternalParameters parameter_info;
1497 public MethodCore (string name, Parameters parameters, Location l)
1500 Parameters = parameters;
1505 // Returns the System.Type array for the parameters of this method
1507 Type [] parameter_types;
1508 public Type [] ParameterTypes (TypeContainer parent)
1510 if (Parameters == null)
1513 if (parameter_types == null)
1514 parameter_types = Parameters.GetParameterInfo (parent);
1516 return parameter_types;
1519 public InternalParameters ParameterInfo
1522 return parameter_info;
1526 parameter_info = value;
1530 public Block Block {
1540 public CallingConventions GetCallingConvention (bool is_class)
1542 CallingConventions cc = 0;
1544 cc = Parameters.GetCallingConvention ();
1547 if ((ModFlags & Modifiers.STATIC) == 0)
1548 cc |= CallingConventions.HasThis;
1550 // FIXME: How is `ExplicitThis' used in C#?
1556 public class Method : MethodCore {
1557 public readonly string ReturnType;
1558 public MethodBuilder MethodBuilder;
1559 public readonly Attributes OptAttributes;
1562 // Modifiers allowed in a class declaration
1564 const int AllowedModifiers =
1567 Modifiers.PROTECTED |
1568 Modifiers.INTERNAL |
1573 Modifiers.OVERRIDE |
1574 Modifiers.ABSTRACT |
1577 // return_type can be "null" for VOID values.
1578 public Method (string return_type, int mod, string name, Parameters parameters,
1579 Attributes attrs, Location l)
1580 : base (name, parameters, l)
1582 ReturnType = return_type;
1583 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1584 OptAttributes = attrs;
1587 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1591 if (! (m is MethodInfo))
1594 MethodSignature sig = (MethodSignature) filter_criteria;
1596 if (m.Name != sig.Name)
1599 mi = (MethodInfo) m;
1601 if (mi.ReturnType != sig.RetType)
1604 Type [] args = TypeManager.GetArgumentTypes (mi);
1605 Type [] sigp = sig.Parameters;
1608 // FIXME: remove this assumption if we manage to
1609 // not enter a null as a the Parameters in TypeManager's
1610 // MethodBase to Type argument mapper.
1617 } else if (sigp == null)
1620 if (args.Length != sigp.Length)
1623 for (int i = args.Length; i > 0; ){
1625 if (args [i] != sigp [i])
1632 // This delegate is used to extract methods which have the
1633 // same signature as the argument
1635 static MemberFilter method_signature_filter;
1639 method_signature_filter = new MemberFilter (MemberSignatureCompare);
1643 // Returns the `System.Type' for the ReturnType of this
1644 // function. Provides a nice cache. (used between semantic analysis
1645 // and actual code generation
1647 Type type_return_type;
1648 public Type GetReturnType (TypeContainer parent)
1650 if (type_return_type == null)
1651 type_return_type = parent.LookupType (ReturnType, false);
1653 return type_return_type;
1656 void WarningNotHiding (TypeContainer parent)
1660 "The member `" + parent.Name + "." + Name + "' does not hide an " +
1661 "inherited member. The keyword new is not required");
1665 string MakeName (TypeContainer parent)
1667 return "`" + parent.Name + "." + Name + "'";
1670 string MethodBaseName (MethodBase mb)
1672 return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
1675 bool CheckMethod (TypeContainer parent, MemberInfo [] mi)
1677 MethodInfo mb = (MethodInfo) mi [0];
1679 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1681 108, Location, "The keyword new is required on " +
1682 MakeName (parent) + " because it hides `" +
1683 mb.ReflectedType.Name + "." +
1687 if (mb.IsVirtual || mb.IsAbstract){
1688 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1690 114, Location, MakeName (parent) +
1691 "hides inherited member " + MethodBaseName (mb) +
1692 ". To make the current member override that " +
1693 "implementation, add the override keyword, " +
1694 "otherwise use the new keyword");
1705 public MethodBuilder Define (TypeContainer parent)
1707 Type ret_type = GetReturnType (parent);
1708 Type [] parameters = ParameterTypes (parent);
1709 MethodAttributes flags;
1713 // Verify if the parent has a type with the same name, and then
1714 // check whether we have to create a new slot for it or not.
1716 Type ptype = parent.TypeBuilder.BaseType;
1718 // ptype is only null for System.Object while compiling corlib.
1720 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1723 mi = TypeContainer.FindMembers (
1724 ptype, MemberTypes.Method,
1725 BindingFlags.Public, method_signature_filter,
1728 if (mi != null && mi.Length > 0){
1729 CheckMethod (parent, mi);
1731 if ((ModFlags & Modifiers.NEW) != 0)
1732 WarningNotHiding (parent);
1734 if ((ModFlags & Modifiers.OVERRIDE) != 0)
1735 Report.Error (115, Location,
1737 " no suitable methods found to override");
1739 } else if ((ModFlags & Modifiers.NEW) != 0)
1740 WarningNotHiding (parent);
1743 // If we implement an interface, then set the proper flags.
1745 flags = Modifiers.MethodAttr (ModFlags);
1747 if (parent.IsInterfaceMethod (Name, ret_type, parameters))
1748 flags |= MethodAttributes.Virtual | MethodAttributes.Final |
1749 MethodAttributes.NewSlot | MethodAttributes.HideBySig;
1752 // Catch invalid uses of virtual and abtract modifiers
1754 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1755 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1756 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1758 if ((ModFlags & va) == va){
1759 if ((ModFlags & va) == va){
1761 503, Location, "The abstract method " +
1762 MakeName (parent) + "can not be marked virtual");
1767 if ((ModFlags & Modifiers.ABSTRACT) != 0){
1768 if ((parent.ModFlags & Modifiers.ABSTRACT) == 0){
1770 513, Location, MakeName (parent) +
1771 " is abstract but its container class is not");
1776 if ((ModFlags & va) != 0 && ((ModFlags & Modifiers.PRIVATE) != 0)){
1778 621, Location, MakeName (parent) +
1779 " virtual or abstract members can not be private");
1783 if ((ModFlags & Modifiers.STATIC) != 0){
1784 if ((ModFlags & vao) != 0){
1786 112, Location, "static method " + MakeName (parent) +
1787 " can not be marked as virtual, abstract or override");
1793 if ((ModFlags & Modifiers.OVERRIDE) != 0 && ((ModFlags & nv) != 0)){
1795 113, Location, MakeName (parent) +
1796 "marked as override cannot be marked as new or virtual");
1804 // Finally, define the method
1807 MethodBuilder = parent.TypeBuilder.DefineMethod (
1809 GetCallingConvention (parent is Class),
1810 ret_type, parameters);
1813 // HACK because System.Reflection.Emit is lame
1815 if (!TypeManager.RegisterMethod (MethodBuilder, parameters)) {
1816 Report.Error (111, Location,
1817 "Class `" + parent.Name + "' already contains a definition with the " +
1818 "same return value and parameter types for method `" + Name + "'");
1822 ParameterInfo = new InternalParameters (parent, Parameters);
1825 // This is used to track the Entry Point,
1827 // FIXME: Allow pluggable entry point, check arguments, etc.
1829 if (Name == "Main"){
1830 if ((ModFlags & Modifiers.STATIC) != 0){
1831 parent.RootContext.EntryPoint = MethodBuilder;
1836 // Define each type attribute (in/out/ref) and
1837 // the argument names.
1839 Parameter [] p = Parameters.FixedParameters;
1843 for (i = 0; i < p.Length; i++)
1844 MethodBuilder.DefineParameter (
1845 i + 1, p [i].Attributes, p [i].Name);
1847 if (i != parameters.Length) {
1848 Parameter array_param = Parameters.ArrayParameter;
1849 MethodBuilder.DefineParameter (i + 1, array_param.Attributes,
1854 return MethodBuilder;
1860 public void Emit (TypeContainer parent)
1862 ILGenerator ig = MethodBuilder.GetILGenerator ();
1863 EmitContext ec = new EmitContext (parent, ig, GetReturnType (parent), ModFlags);
1865 if (OptAttributes != null) {
1866 if (OptAttributes.AttributeSections != null) {
1867 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
1868 if (asec.Attributes != null) {
1869 foreach (Attribute a in asec.Attributes) {
1870 CustomAttributeBuilder cb = a.Resolve (ec);
1872 MethodBuilder.SetCustomAttribute (cb);
1879 ec.EmitTopBlock (Block);
1883 public abstract class ConstructorInitializer {
1884 ArrayList argument_list;
1885 ConstructorInfo parent_constructor;
1888 public ConstructorInitializer (ArrayList argument_list, Location location)
1890 this.argument_list = argument_list;
1891 this.location = location;
1894 public ArrayList Arguments {
1896 return argument_list;
1900 public bool Resolve (EmitContext ec)
1902 Expression parent_constructor_group;
1904 if (argument_list != null){
1905 for (int i = argument_list.Count; i > 0; ){
1908 Argument a = (Argument) argument_list [i];
1909 if (!a.Resolve (ec))
1914 parent_constructor_group = Expression.MemberLookup (
1916 ec.TypeContainer.TypeBuilder.BaseType, ".ctor", true,
1917 MemberTypes.Constructor,
1918 BindingFlags.Public | BindingFlags.Instance, location);
1920 if (parent_constructor_group == null){
1921 Console.WriteLine ("Could not find a constructor in our parent");
1925 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
1926 (MethodGroupExpr) parent_constructor_group, argument_list, location);
1928 if (parent_constructor == null)
1934 public void Emit (EmitContext ec)
1936 ec.ig.Emit (OpCodes.Ldarg_0);
1937 if (argument_list != null)
1938 Invocation.EmitArguments (ec, argument_list);
1939 ec.ig.Emit (OpCodes.Call, parent_constructor);
1943 public class ConstructorBaseInitializer : ConstructorInitializer {
1944 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1949 public class ConstructorThisInitializer : ConstructorInitializer {
1950 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1955 public class Constructor : MethodCore {
1956 public ConstructorBuilder ConstructorBuilder;
1957 public ConstructorInitializer Initializer;
1958 public Attributes OptAttributes;
1961 // Modifiers allowed for a constructor.
1963 const int AllowedModifiers =
1965 Modifiers.PROTECTED |
1966 Modifiers.INTERNAL |
1971 // The spec claims that static is not permitted, but
1972 // my very own code has static constructors.
1974 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
1975 : base (name, args, l)
1981 // Returns true if this is a default constructor
1983 public bool IsDefault ()
1985 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
1986 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
1987 (Initializer is ConstructorBaseInitializer) &&
1988 (Initializer.Arguments == null);
1992 // Creates the ConstructorBuilder
1994 public ConstructorBuilder Define (TypeContainer parent)
1996 MethodAttributes ca = (MethodAttributes.RTSpecialName |
1997 MethodAttributes.SpecialName);
1999 Type [] parameters = ParameterTypes (parent);
2001 if ((ModFlags & Modifiers.STATIC) != 0)
2002 ca |= MethodAttributes.Static;
2004 if (parent is Struct && parameters == null){
2007 "Structs can not contain explicit parameterless " +
2013 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2014 ca, GetCallingConvention (parent is Class),
2017 // HACK because System.Reflection.Emit is lame
2019 if (!TypeManager.RegisterMethod (ConstructorBuilder, parameters)) {
2020 Report.Error (111, Location,
2021 "Class `" + parent.Name + "' already contains a definition with the " +
2022 "same return value and parameter types for constructor `" + Name + "'");
2027 ParameterInfo = new InternalParameters (parent, Parameters);
2029 return ConstructorBuilder;
2035 public void Emit (TypeContainer parent)
2037 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2038 EmitContext ec = new EmitContext (parent, ig, null, ModFlags, true);
2040 if (parent is Class){
2041 if (Initializer == null)
2042 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2044 if (!Initializer.Resolve (ec))
2049 // Classes can have base initializers and instance field initializers.
2051 if (parent is Class){
2052 if ((ModFlags & Modifiers.STATIC) == 0)
2053 Initializer.Emit (ec);
2054 parent.EmitFieldInitializers (ec, false);
2057 if ((ModFlags & Modifiers.STATIC) != 0)
2058 parent.EmitFieldInitializers (ec, true);
2060 if (OptAttributes != null) {
2061 if (OptAttributes.AttributeSections != null) {
2062 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2063 if (asec.Attributes != null) {
2064 foreach (Attribute a in asec.Attributes) {
2065 CustomAttributeBuilder cb = a.Resolve (ec);
2067 ConstructorBuilder.SetCustomAttribute (cb);
2074 ec.EmitTopBlock (Block);
2078 public class Field {
2079 public readonly string Type;
2080 public readonly Object Initializer;
2081 public readonly string Name;
2082 public readonly int ModFlags;
2083 public readonly Attributes OptAttributes;
2084 public FieldBuilder FieldBuilder;
2088 // Modifiers allowed in a class declaration
2090 const int AllowedModifiers =
2093 Modifiers.PROTECTED |
2094 Modifiers.INTERNAL |
2099 public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
2102 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
2104 Initializer = expr_or_array_init;
2105 OptAttributes = attrs;
2108 public void Define (TypeContainer parent)
2110 Type t = parent.LookupType (Type, false);
2115 FieldBuilder = parent.TypeBuilder.DefineField (
2116 Name, t, Modifiers.FieldAttr (ModFlags));
2119 public void Emit (TypeContainer tc)
2121 EmitContext ec = new EmitContext (tc, null, FieldBuilder.FieldType, ModFlags);
2123 if (OptAttributes == null)
2126 if (OptAttributes.AttributeSections == null)
2129 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2130 if (asec.Attributes == null)
2133 foreach (Attribute a in asec.Attributes) {
2134 CustomAttributeBuilder cb = a.Resolve (ec);
2138 FieldBuilder.SetCustomAttribute (cb);
2144 public class Property {
2146 public readonly string Type;
2147 public readonly string Name;
2148 public readonly int ModFlags;
2149 public Block Get, Set;
2150 public PropertyBuilder PropertyBuilder;
2151 public Attributes OptAttributes;
2152 MethodBuilder GetBuilder, SetBuilder;
2157 // The type, once we compute it.
2161 const int AllowedModifiers =
2164 Modifiers.PROTECTED |
2165 Modifiers.INTERNAL |
2169 Modifiers.OVERRIDE |
2170 Modifiers.ABSTRACT |
2173 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2174 Attributes attrs, Location loc)
2178 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2181 OptAttributes = attrs;
2185 public void Define (TypeContainer parent)
2188 MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
2190 // FIXME - PropertyAttributes.HasDefault ?
2192 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2193 PropertyAttributes.SpecialName;
2196 PropertyType = parent.LookupType (Type, false);
2197 Type [] parameters = new Type [1];
2198 parameters [0] = PropertyType;
2200 PropertyBuilder = parent.TypeBuilder.DefineProperty (
2201 Name, prop_attr, PropertyType, null);
2205 GetBuilder = parent.TypeBuilder.DefineMethod (
2206 "get_" + Name, method_attr, PropertyType, null);
2207 PropertyBuilder.SetGetMethod (GetBuilder);
2209 // HACK because System.Reflection.Emit is lame
2211 if (!TypeManager.RegisterMethod (GetBuilder, null)) {
2212 Report.Error (111, Location,
2213 "Class `" + parent.Name + "' already contains a definition with the " +
2214 "same return value and parameter types as the " +
2215 "'get' method of property `" + Name + "'");
2224 SetBuilder = parent.TypeBuilder.DefineMethod (
2225 "set_" + Name, method_attr, null, parameters);
2226 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2227 PropertyBuilder.SetSetMethod (SetBuilder);
2229 // HACK because System.Reflection.Emit is lame
2231 if (!TypeManager.RegisterMethod (SetBuilder, parameters)) {
2232 Report.Error (111, Location,
2233 "Class `" + parent.Name + "' already contains a definition with the " +
2234 "same return value and parameter types as the " +
2235 "'set' method of property `" + Name + "'");
2240 // HACK for the reasons exposed above
2242 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
2243 Report.Error (111, Location,
2244 "Class `" + parent.Name + "' already contains a definition for the " +
2245 " property `" + Name + "'");
2253 public void Emit (TypeContainer tc)
2258 if (OptAttributes != null) {
2259 ec = new EmitContext (tc, null, PropertyType, ModFlags);
2260 if (OptAttributes.AttributeSections != null) {
2261 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2262 if (asec.Attributes == null)
2265 foreach (Attribute a in asec.Attributes) {
2266 CustomAttributeBuilder cb = a.Resolve (ec);
2269 PropertyBuilder.SetCustomAttribute (cb);
2276 ig = GetBuilder.GetILGenerator ();
2277 ec = new EmitContext (tc, ig, PropertyType, ModFlags);
2279 ec.EmitTopBlock (Get);
2283 ig = SetBuilder.GetILGenerator ();
2284 ec = new EmitContext (tc, ig, null, ModFlags);
2286 ec.EmitTopBlock (Set);
2291 public class Event {
2293 const int AllowedModifiers =
2296 Modifiers.PROTECTED |
2297 Modifiers.INTERNAL |
2302 Modifiers.OVERRIDE |
2305 public readonly string Type;
2306 public readonly string Name;
2307 public readonly Object Initializer;
2308 public readonly int ModFlags;
2309 public readonly Block Add;
2310 public readonly Block Remove;
2311 public EventBuilder EventBuilder;
2312 public Attributes OptAttributes;
2318 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
2319 Attributes attrs, Location loc)
2324 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
2327 OptAttributes = attrs;
2331 public void Define (TypeContainer parent)
2333 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
2335 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
2339 EventType = parent.LookupType (Type, false);
2340 Type [] parameters = new Type [1];
2341 parameters [0] = EventType;
2343 EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, EventType);
2346 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null,
2348 mb.DefineParameter (1, ParameterAttributes.None, "value");
2349 EventBuilder.SetAddOnMethod (mb);
2351 // HACK because System.Reflection.Emit is lame
2353 if (!TypeManager.RegisterMethod (mb, parameters)) {
2354 Report.Error (111, Location,
2355 "Class `" + parent.Name + "' already contains a definition with the " +
2356 "same return value and parameter types for the " +
2357 "'add' method of event `" + Name + "'");
2362 if (Remove != null) {
2363 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null,
2365 mb.DefineParameter (1, ParameterAttributes.None, "value");
2366 EventBuilder.SetRemoveOnMethod (mb);
2369 // HACK because System.Reflection.Emit is lame
2371 if (!TypeManager.RegisterMethod (mb, parameters)) {
2372 Report.Error (111, Location,
2373 "Class `" + parent.Name + "' already contains a definition with the " +
2374 "same return value and parameter types for the " +
2375 "'remove' method of event `" + Name + "'");
2383 public void Emit (TypeContainer tc)
2385 EmitContext ec = new EmitContext (tc, null, EventType, ModFlags);
2387 if (OptAttributes == null)
2390 if (OptAttributes.AttributeSections == null)
2393 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2394 if (asec.Attributes == null)
2397 foreach (Attribute a in asec.Attributes) {
2398 CustomAttributeBuilder cb = a.Resolve (ec);
2402 EventBuilder.SetCustomAttribute (cb);
2410 // FIXME: This does not handle:
2412 // int INTERFACENAME [ args ]
2416 // int this [ args ]
2418 public class Indexer {
2420 const int AllowedModifiers =
2423 Modifiers.PROTECTED |
2424 Modifiers.INTERNAL |
2428 Modifiers.OVERRIDE |
2431 public readonly string Type;
2432 public readonly string InterfaceType;
2433 public readonly Parameters FormalParameters;
2434 public readonly int ModFlags;
2435 public readonly Block Get;
2436 public readonly Block Set;
2437 public Attributes OptAttributes;
2438 public MethodBuilder GetBuilder;
2439 public MethodBuilder SetBuilder;
2440 public PropertyBuilder PropertyBuilder;
2441 public Type IndexerType;
2445 public Indexer (string type, string int_type, int flags, Parameters parms,
2446 Block get_block, Block set_block, Attributes attrs, Location loc)
2450 InterfaceType = int_type;
2451 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
2452 FormalParameters = parms;
2455 OptAttributes = attrs;
2459 public void Define (TypeContainer parent)
2461 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
2462 PropertyAttributes prop_attr =
2463 PropertyAttributes.RTSpecialName |
2464 PropertyAttributes.SpecialName;
2466 IndexerType = parent.LookupType (Type, false);
2467 Type [] parameters = FormalParameters.GetParameterInfo (parent);
2469 PropertyBuilder = parent.TypeBuilder.DefineProperty (
2470 TypeManager.IndexerPropertyName (parent.TypeBuilder),
2471 prop_attr, IndexerType, parameters);
2474 GetBuilder = parent.TypeBuilder.DefineMethod (
2475 "get_Item", attr, IndexerType, parameters);
2477 if (!TypeManager.RegisterMethod (GetBuilder, parameters)) {
2478 Report.Error (111, Location,
2479 "Class `" + parent.Name + "' already contains a definition with the " +
2480 "same return value and parameter types for the " +
2485 TypeContainer.RegisterParameterForBuilder (
2486 GetBuilder, new InternalParameters (parent, FormalParameters));
2490 int top = parameters.Length;
2491 Type [] set_pars = new Type [top + 1];
2492 parameters.CopyTo (set_pars, 0);
2493 set_pars [top] = IndexerType;
2495 Parameter [] fixed_parms = FormalParameters.FixedParameters;
2497 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
2499 fixed_parms.CopyTo (tmp, 0);
2500 tmp [fixed_parms.Length] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2502 Parameters set_formal_params = new Parameters (tmp, null);
2504 SetBuilder = parent.TypeBuilder.DefineMethod (
2505 "set_Item", attr, null, set_pars);
2507 if (!TypeManager.RegisterMethod (SetBuilder, set_pars)) {
2508 Report.Error (111, Location,
2509 "Class `" + parent.Name + "' already contains a definition with the " +
2510 "same return value and parameter types for the " +
2515 TypeContainer.RegisterParameterForBuilder (
2516 SetBuilder, new InternalParameters (parent, set_formal_params));
2519 PropertyBuilder.SetGetMethod (GetBuilder);
2520 PropertyBuilder.SetSetMethod (SetBuilder);
2522 Parameter [] p = FormalParameters.FixedParameters;
2527 for (i = 0; i < p.Length; ++i) {
2529 GetBuilder.DefineParameter (
2530 i + 1, p [i].Attributes, p [i].Name);
2533 SetBuilder.DefineParameter (
2534 i + 1, p [i].Attributes, p [i].Name);
2538 SetBuilder.DefineParameter (
2539 i + 1, ParameterAttributes.None, "value");
2541 if (i != parameters.Length) {
2542 Parameter array_param = FormalParameters.ArrayParameter;
2543 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
2548 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
2551 public void Emit (TypeContainer tc)
2556 if (OptAttributes != null) {
2557 ec = new EmitContext (tc, null, IndexerType, ModFlags);
2558 if (OptAttributes.AttributeSections != null) {
2559 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2560 if (asec.Attributes != null) {
2561 foreach (Attribute a in asec.Attributes) {
2562 CustomAttributeBuilder cb = a.Resolve (ec);
2564 PropertyBuilder.SetCustomAttribute (cb);
2572 ig = GetBuilder.GetILGenerator ();
2573 ec = new EmitContext (tc, ig, IndexerType, ModFlags);
2575 ec.EmitTopBlock (Get);
2579 ig = SetBuilder.GetILGenerator ();
2580 ec = new EmitContext (tc, ig, null, ModFlags);
2582 ec.EmitTopBlock (Set);
2587 public class Operator {
2589 const int AllowedModifiers =
2593 const int RequiredModifiers =
2597 public enum OpType {
2607 // Unary and Binary operators
2630 // Implicit and Explicit
2635 public readonly OpType OperatorType;
2636 public readonly string ReturnType;
2637 public readonly string FirstArgType;
2638 public readonly string FirstArgName;
2639 public readonly string SecondArgType;
2640 public readonly string SecondArgName;
2641 public readonly int ModFlags;
2642 public readonly Block Block;
2643 public Attributes OptAttributes;
2644 public MethodBuilder OperatorMethodBuilder;
2645 public Location Location;
2647 public string MethodName;
2648 public Method OperatorMethod;
2650 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
2651 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
2653 OperatorType = type;
2654 ReturnType = ret_type;
2655 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
2656 FirstArgType = arg1type;
2657 FirstArgName = arg1name;
2658 SecondArgType = arg2type;
2659 SecondArgName = arg2name;
2661 OptAttributes = attrs;
2665 string Prototype (TypeContainer parent)
2667 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
2668 SecondArgType + ")";
2671 public void Define (TypeContainer parent)
2674 MethodName = "op_" + OperatorType;
2676 if (SecondArgType != null)
2679 Parameter [] param_list = new Parameter [length];
2681 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2684 "User defined operators `" +
2685 Prototype (parent) +
2686 "' must be declared static and public");
2689 param_list[0] = new Parameter (FirstArgType, FirstArgName,
2690 Parameter.Modifier.NONE, null);
2691 if (SecondArgType != null)
2692 param_list[1] = new Parameter (SecondArgType, SecondArgName,
2693 Parameter.Modifier.NONE, null);
2695 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
2696 new Parameters (param_list, null),
2697 OptAttributes, Location.Null);
2699 OperatorMethod.Define (parent);
2700 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
2702 Type [] param_types = OperatorMethod.ParameterTypes (parent);
2703 Type declaring_type = OperatorMethodBuilder.DeclaringType;
2704 Type return_type = OperatorMethod.GetReturnType (parent);
2705 Type first_arg_type = param_types [0];
2707 // Rules for conversion operators
2709 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2711 if (first_arg_type == return_type && first_arg_type == declaring_type)
2712 Report.Error (555, Location,
2713 "User-defined conversion cannot take an object of the enclosing type " +
2714 "and convert to an object of the enclosing type");
2716 if (first_arg_type != declaring_type && return_type != declaring_type)
2717 Report.Error (556, Location,
2718 "User-defined conversion must convert to or from the enclosing type");
2720 if (first_arg_type == TypeManager.object_type || return_type == TypeManager.object_type)
2721 Report.Error (-8, Location,
2722 "User-defined conversion cannot convert to or from object type");
2724 if (first_arg_type.IsInterface || return_type.IsInterface)
2725 Report.Error (-9, Location,
2726 "User-defined conversion cannot convert to or from an interface type");
2728 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type))
2729 Report.Error (-10, Location,
2730 "User-defined conversion cannot convert between types that " +
2731 "derive from each other");
2733 } else if (SecondArgType == null) {
2734 // Checks for Unary operators
2736 if (first_arg_type != declaring_type)
2737 Report.Error (562, Location,
2738 "The parameter of a unary operator must be the containing type");
2741 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2742 if (return_type != declaring_type)
2743 Report.Error (559, Location,
2744 "The parameter and return type for ++ and -- " +
2745 "must be the containing type");
2749 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2750 if (return_type != TypeManager.bool_type)
2751 Report.Error (215, Location,
2752 "The return type of operator True or False " +
2757 // Checks for Binary operators
2759 if (first_arg_type != declaring_type &&
2760 param_types [1] != declaring_type)
2761 Report.Error (563, Location,
2762 "One of the parameters of a binary operator must be the containing type");
2769 public void Emit (TypeContainer parent)
2771 if (OptAttributes != null) {
2772 EmitContext ec = new EmitContext (parent, null, null, ModFlags);
2773 if (OptAttributes.AttributeSections != null) {
2774 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2775 if (asec.Attributes != null) {
2776 foreach (Attribute a in asec.Attributes) {
2777 CustomAttributeBuilder cb = a.Resolve (ec);
2779 OperatorMethodBuilder.SetCustomAttribute (cb);
2786 OperatorMethod.Block = Block;
2787 OperatorMethod.Emit (parent);
2794 // This is used to compare method signatures
2796 struct MethodSignature {
2798 public Type RetType;
2799 public Type [] Parameters;
2801 public MethodSignature (string name, Type ret_type, Type [] parameters)
2805 Parameters = parameters;
2807 if (parameters != null){
2808 if (parameters.Length == 0)
2813 public override int GetHashCode ()
2815 return Name.GetHashCode ();
2818 public override bool Equals (Object o)
2820 MethodSignature other = (MethodSignature) o;
2822 if (other.Name != Name)
2825 if (other.RetType != RetType)
2828 if (Parameters == null){
2829 if (other.Parameters == null)
2834 if (other.Parameters == null)
2837 int c = Parameters.Length;
2838 if (other.Parameters.Length != c)
2841 for (int i = 0; i < c; i++)
2842 if (other.Parameters [i] != Parameters [i])