* MethodDef.cs: Report when defining methods just like MS.
[mono.git] / mcs / ilasm / codegen / TypeDef.cs
1 //
2 // Mono.ILASM.TypeDef
3 //
4 // Author(s):
5 //  Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
9
10
11 using System;
12 using System.Collections;
13
14 namespace Mono.ILASM {
15
16         public class TypeDef {
17
18                 protected class GenericInfo {
19                         public string Id;
20                         public ArrayList ConstraintList;
21                 }
22
23                 private PEAPI.TypeAttr attr;
24                 private string name_space;
25                 private string name;
26                 private bool is_defined;
27                 private bool is_intransit;
28                 private IClassRef parent;
29                 private ArrayList impl_list;
30                 private PEAPI.ClassDef classdef;
31                 private Hashtable field_table;
32                 private Hashtable method_table;
33                 private ArrayList customattr_list;
34                 private ArrayList event_list;
35                 private ArrayList property_list;
36                 private ArrayList typar_list;
37                 private ArrayList override_list;
38                 private ArrayList override_long_list;
39                 private TypeDef outer;
40
41                 private EventDef current_event;
42                 private PropertyDef current_property;
43
44                 private int size;
45                 private int pack;
46
47                 private bool is_value_class;
48                 private bool is_enum_class;
49
50                 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
51                                 IClassRef parent, ArrayList impl_list, Location location)
52                 {
53                         this.attr = attr;
54                         this.name_space = name_space;
55                         this.name = name;
56                         this.parent = parent;
57                         this.impl_list = impl_list;
58                         field_table = new Hashtable ();
59                         method_table = new Hashtable ();
60
61                         size = -1;
62                         pack = -1;
63
64                         is_defined = false;
65                         is_intransit = false;
66
67                         is_value_class = false;
68                         is_value_class = false;
69                 }
70
71                 public string Name {
72                         get { return name; }
73                 }
74
75                 public string FullName {
76                         get { return MakeFullName (); }
77                 }
78
79                 public TypeDef OuterType {
80                         get { return outer; }
81                         set { outer = value; }
82                 }
83
84                 public PEAPI.ClassDef PeapiType {
85                         get { return classdef; }
86                 }
87
88                 public PEAPI.ClassDef ClassDef {
89                         get { return classdef; }
90                 }
91
92                 public bool IsGenericType {
93                         get { return (typar_list == null); }
94                 }
95
96                 public bool IsDefined {
97                         get { return is_defined; }
98                 }
99
100                 public EventDef CurrentEvent {
101                         get { return current_event; }
102                 }
103
104                 public PropertyDef CurrentProperty {
105                         get { return current_property; }
106                 }
107
108
109                 public void AddOverride (MethodDef body, ITypeRef parent, string name)
110                 {
111                         if (override_list == null)
112                                 override_list = new ArrayList ();
113                         override_list.Add (new DictionaryEntry (body,
114                                            new DictionaryEntry (parent, name)));
115                 }
116
117                 public void AddOverride (string sig, IMethodRef decl)
118                 {
119                         if (override_long_list == null)
120                                 override_long_list = new ArrayList ();
121                         override_long_list.Add (new DictionaryEntry (sig,
122                                                                 decl));
123                 }
124
125                 public void MakeValueClass ()
126                 {
127                         is_value_class = true;
128                 }
129
130                 public void MakeEnumClass ()
131                 {
132                         is_enum_class = true;
133                 }
134
135                 public void SetSize (int size)
136                 {
137                         this.size = size;
138                 }
139
140                 public void SetPack (int pack)
141                 {
142                         this.pack = pack;
143                 }
144
145                 public void AddFieldDef (FieldDef fielddef)
146                 {
147                         field_table.Add (fielddef.Name, fielddef);
148                 }
149
150                 public void AddMethodDef (MethodDef methoddef)
151                 {
152                         method_table.Add (methoddef.Signature, methoddef);
153                 }
154
155                 public void BeginEventDef (EventDef event_def)
156                 {
157                         if (current_event != null)
158                                 throw new Exception ("An event definition was not closed.");
159
160                         current_event = event_def;
161                 }
162
163                 public void EndEventDef ()
164                 {
165                         if (event_list == null)
166                                 event_list = new ArrayList ();
167
168                         event_list.Add (current_event);
169                         current_event = null;
170                 }
171
172                 public void BeginPropertyDef (PropertyDef property_def)
173                 {
174                         if (current_property != null)
175                                 throw new Exception ("A property definition was not closed.");
176
177                         current_property = property_def;
178                 }
179
180                 public void EndPropertyDef ()
181                 {
182                         if (property_list == null)
183                                 property_list = new ArrayList ();
184
185                         property_list.Add (current_property);
186                         current_property = null;
187                 }
188
189                 public void AddCustomAttribute (CustomAttr customattr)
190                 {
191                         if (customattr_list == null)
192                                 customattr_list = new ArrayList ();
193
194                         customattr_list.Add (customattr);
195                 }
196
197                 public void AddGenericParam (string id)
198                 {
199                         if (typar_list == null)
200                                 typar_list = new ArrayList ();
201
202                         GenericInfo gi = new GenericInfo ();
203                         gi.Id = id;
204
205                         typar_list.Add (gi);
206                 }
207
208                 public void AddGenericConstraint (int index, ITypeRef constraint)
209                 {
210                         GenericInfo gi = (GenericInfo) typar_list[index];
211
212                         if (gi.ConstraintList == null)
213                                 gi.ConstraintList = new ArrayList ();
214                         gi.ConstraintList.Add (constraint);
215                 }
216
217                 public void Define (CodeGen code_gen)
218                 {
219                         if (is_defined)
220                                 return;
221
222                         if (is_intransit) {
223                                 // Circular definition
224                                 throw new Exception ("Circular definition of class: " + FullName);
225                         }
226
227                         if (parent != null) {
228                                 is_intransit = true;
229                                 parent.Resolve (code_gen);
230                                 is_intransit = false;
231                                 if (parent.PeapiClass == null) {
232                                         throw new Exception ("this type can not be a base type: "
233                                                         + parent);
234                                 }
235                                 if (outer != null) {
236                                         if (!outer.IsDefined)
237                                                 outer.Define (code_gen);
238                                         classdef = outer.PeapiType.AddNestedClass (attr,
239                                                         name_space, name, parent.PeapiClass);
240                                 } else {
241                                         if (is_value_class) {
242                                                 // Should probably confirm that the parent is System.ValueType
243                                                 classdef = code_gen.PEFile.AddValueClass (attr,
244                                                         name_space, name);
245                                         } else {
246                                                 classdef = code_gen.PEFile.AddClass (attr,
247                                                         name_space, name, parent.PeapiClass);
248                                         }
249                                 }
250                         } else {
251                                 if (outer != null) {
252                                         if (!outer.IsDefined)
253                                                 outer.Define (code_gen);
254                                         classdef = outer.PeapiType.AddNestedClass (attr,
255                                                 name_space, name);
256                                 } else {
257                                         if (is_value_class) {
258                                                 classdef = code_gen.PEFile.AddValueClass (attr,
259                                                         name_space, name);
260                                         } else {
261                                                 classdef = code_gen.PEFile.AddClass (attr,
262                                                         name_space, name);
263                                         }
264                                 }
265                                 if (FullName == "System.Object")
266                                         classdef.SpecialNoSuper ();
267                         }
268
269                         if (size != -1)
270                                 classdef.AddLayoutInfo (pack, size);
271
272                         if (impl_list != null) {
273                                 foreach (IClassRef impl in impl_list) {
274                                         impl.Resolve (code_gen);
275                                         classdef.AddImplementedInterface (impl.PeapiClass);
276                                 }
277                         }
278
279                         if (typar_list != null) {
280                                 short index = 0;
281                                 foreach (GenericInfo gi in typar_list) {
282                                         PEAPI.GenericParameter gp = classdef.AddGenericParameter (index++, gi.Id);
283                                         if (gi.ConstraintList != null) {
284                                                 foreach (ITypeRef cnst in gi.ConstraintList) {
285                                                         cnst.Resolve (code_gen);
286                                                         gp.AddConstraint (cnst.PeapiType);
287                                                 }
288                                         }
289                                 }
290                         }
291
292                         is_intransit = false;
293                         is_defined = true;
294
295                         code_gen.AddToDefineContentsList (this);
296                 }
297
298                 public void DefineContents (CodeGen code_gen)
299                 {
300                         foreach (FieldDef fielddef in field_table.Values) {
301                                 fielddef.Define (code_gen, classdef);
302                         }
303
304                         foreach (MethodDef methoddef in method_table.Values) {
305                                 methoddef.Define (code_gen, this);
306                         }
307
308                         if (event_list != null) {
309                                 foreach (EventDef eventdef in event_list) {
310                                         eventdef.Define (code_gen, classdef);
311                                 }
312                         }
313
314                         if (property_list != null) {
315                                 foreach (PropertyDef propdef in property_list) {
316                                         propdef.Define (code_gen, classdef);
317                                 }
318
319                         }
320
321                         if (customattr_list != null) {
322                                 foreach (CustomAttr customattr in customattr_list)
323                                         customattr.AddTo (code_gen, classdef);
324                         }
325
326                         if (override_list != null) {
327                                 foreach (DictionaryEntry entry in override_list) {
328                                         MethodDef body = (MethodDef) entry.Key;
329                                         DictionaryEntry decl = (DictionaryEntry) entry.Value;
330                                         ITypeRef parent_type = (ITypeRef) decl.Key;
331                                         parent_type.Resolve (code_gen);
332                                         string over_name = (string) decl.Value;
333                                         IMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
334                                                         body.CallConv, over_name, body.ParamTypeList ());
335                                         over_meth.Resolve (code_gen);
336                                         classdef.AddMethodOverride (over_meth.PeapiMethod,
337                                                         body.PeapiMethodDef);
338                                 }
339                         }
340
341                         if (override_long_list != null) {
342                                 foreach (DictionaryEntry entry in override_long_list) {
343                                         string sig = (string) entry.Key;
344                                         IMethodRef decl = (IMethodRef) entry.Value;
345                                         MethodDef body = (MethodDef) method_table[sig];
346                                         decl.Resolve (code_gen);
347                                         classdef.AddMethodOverride (decl.PeapiMethod,
348                                                         body.PeapiMethodDef);
349                                 }
350                         }
351                 }
352
353                 public PEAPI.MethodDef ResolveMethod (string signature, CodeGen code_gen)
354                 {
355                         MethodDef methoddef = (MethodDef) method_table[signature];
356
357                         if (methoddef == null) {
358                                 code_gen.Report.Error ("Unable to resolve method: " + signature);
359                                 Environment.Exit (1);
360                         }
361
362                         return methoddef.Resolve (code_gen, classdef);
363                 }
364
365                 public PEAPI.Method ResolveVarargMethod (string signature,
366                                 CodeGen code_gen, PEAPI.Type[] opt)
367                 {
368                         MethodDef methoddef = (MethodDef) method_table[signature];
369
370                         if (methoddef == null) {
371                                 code_gen.Report.Error ("Unable to resolve method: " + signature);
372                                 Environment.Exit (1);
373                         }
374
375                         methoddef.Resolve (code_gen, classdef);
376                         return methoddef.GetVarargSig (opt);
377                 }
378
379                 public PEAPI.Field ResolveField (string name, CodeGen code_gen)
380                 {
381                         FieldDef fielddef = (FieldDef) field_table[name];
382
383                         return fielddef.Resolve (code_gen, classdef);
384                 }
385
386                 private string MakeFullName ()
387                 {
388                         if (name_space == null || name_space == String.Empty)
389                                 return name;
390
391                         return name_space + "." + name;
392                 }
393         }
394
395 }
396