In ilasm/tests:
[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 : ICustomAttrTarget, IDeclSecurityTarget {
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 ArrayList field_list;
33                 private Hashtable method_table;
34                 private ArrayList customattr_list;
35                 private ArrayList declsecurity_list;
36                 private ArrayList event_list;
37                 private ArrayList property_list;
38                 private ArrayList typar_list;
39                 private ArrayList override_list;
40                 private ArrayList override_long_list;
41                 private TypeDef outer;
42
43                 private EventDef current_event;
44                 private PropertyDef current_property;
45
46                 private int size;
47                 private int pack;
48
49                 private bool is_value_class;
50                 private bool is_enum_class;
51
52                 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
53                                 IClassRef parent, ArrayList impl_list, Location location)
54                 {
55                         this.attr = attr;
56                         this.name_space = name_space;
57                         this.name = name;
58                         this.parent = parent;
59                         this.impl_list = impl_list;
60
61                         field_table = new Hashtable ();
62                         field_list = new ArrayList ();
63
64                         method_table = new Hashtable ();
65
66                         size = -1;
67                         pack = -1;
68
69                         is_defined = false;
70                         is_intransit = false;
71
72                         is_value_class = false;
73                         is_enum_class = false;
74                 }
75
76                 public string Name {
77                         get { return name; }
78                 }
79
80                 public string FullName {
81                         get { return MakeFullName (); }
82                 }
83
84                 public TypeDef OuterType {
85                         get { return outer; }
86                         set { outer = value; }
87                 }
88
89                 public PEAPI.ClassDef PeapiType {
90                         get { return classdef; }
91                 }
92
93                 public PEAPI.ClassDef ClassDef {
94                         get { return classdef; }
95                 }
96
97                 public bool IsGenericType {
98                         get { return (typar_list == null); }
99                 }
100
101                 public bool IsDefined {
102                         get { return is_defined; }
103                 }
104
105                 public EventDef CurrentEvent {
106                         get { return current_event; }
107                 }
108
109                 public PropertyDef CurrentProperty {
110                         get { return current_property; }
111                 }
112
113                 public bool IsInterface {
114                         get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
115                 }
116
117                 public void AddOverride (MethodDef body, ITypeRef parent, string name)
118                 {
119                         if (override_list == null)
120                                 override_list = new ArrayList ();
121                         override_list.Add (new DictionaryEntry (body,
122                                            new DictionaryEntry (parent, name)));
123                 }
124
125                 public void AddOverride (string sig, IMethodRef decl)
126                 {
127                         if (override_long_list == null)
128                                 override_long_list = new ArrayList ();
129                         override_long_list.Add (new DictionaryEntry (sig,
130                                                                 decl));
131                 }
132
133                 public void MakeValueClass ()
134                 {
135                         is_value_class = true;
136                 }
137
138                 public void MakeEnumClass ()
139                 {
140                         is_enum_class = true;
141                 }
142
143                 public void SetSize (int size)
144                 {
145                         this.size = size;
146                 }
147
148                 public void SetPack (int pack)
149                 {
150                         this.pack = pack;
151                 }
152
153                 public void AddFieldDef (FieldDef fielddef)
154                 {
155                         if (IsInterface && !fielddef.IsStatic) {
156                                 Console.WriteLine ("warning -- Non-static field in interface, set to such");
157                                 fielddef.Attributes |= PEAPI.FieldAttr.Static;
158                         }
159
160                         field_table.Add (fielddef.Name, fielddef);
161                         field_list.Add (fielddef);
162                 }
163
164                 public void AddMethodDef (MethodDef methoddef)
165                 {
166                         if (IsInterface && !(methoddef.IsVirtual || methoddef.IsAbstract)) {
167                                 Console.WriteLine ("warning -- Non-virtual, non-abstract instance method in interface, set to such");
168                                 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
169                         }
170
171                         method_table.Add (methoddef.Signature, methoddef);
172                 }
173
174                 public void BeginEventDef (EventDef event_def)
175                 {
176                         if (current_event != null)
177                                 throw new Exception ("An event definition was not closed.");
178
179                         current_event = event_def;
180                 }
181
182                 public void EndEventDef ()
183                 {
184                         if (event_list == null)
185                                 event_list = new ArrayList ();
186
187                         event_list.Add (current_event);
188                         current_event = null;
189                 }
190
191                 public void BeginPropertyDef (PropertyDef property_def)
192                 {
193                         if (current_property != null)
194                                 throw new Exception ("A property definition was not closed.");
195
196                         current_property = property_def;
197                 }
198
199                 public void EndPropertyDef ()
200                 {
201                         if (property_list == null)
202                                 property_list = new ArrayList ();
203
204                         property_list.Add (current_property);
205                         current_property = null;
206                 }
207
208                 public void AddCustomAttribute (CustomAttr customattr)
209                 {
210                         if (customattr_list == null)
211                                 customattr_list = new ArrayList ();
212
213                         customattr_list.Add (customattr);
214                 }
215
216                 public void AddDeclSecurity (DeclSecurity declsecurity)
217                 {
218                         if (declsecurity_list == null)
219                                 declsecurity_list = new ArrayList ();
220
221                         declsecurity_list.Add (declsecurity);
222                 }
223
224                 public void AddGenericParam (string id)
225                 {
226                         if (typar_list == null)
227                                 typar_list = new ArrayList ();
228
229                         GenericInfo gi = new GenericInfo ();
230                         gi.Id = id;
231
232                         typar_list.Add (gi);
233                 }
234
235                 public void AddGenericConstraint (int index, ITypeRef constraint)
236                 {
237                         GenericInfo gi = (GenericInfo) typar_list[index];
238
239                         if (gi.ConstraintList == null)
240                                 gi.ConstraintList = new ArrayList ();
241                         gi.ConstraintList.Add (constraint);
242                 }
243
244                 public void Define (CodeGen code_gen)
245                 {
246                         if (is_defined)
247                                 return;
248
249                         if (is_intransit) {
250                                 // Circular definition
251                                 throw new Exception ("Circular definition of class: " + FullName);
252                         }
253
254                         if (parent != null) {
255                                 is_intransit = true;
256                                 parent.Resolve (code_gen);
257                                 is_intransit = false;
258                                 if (parent.PeapiClass == null) {
259                                         throw new Exception ("this type can not be a base type: "
260                                                         + parent);
261                                 }
262
263                                 if (parent.PeapiClass.nameSpace != null && 
264                                         parent.PeapiClass.nameSpace.CompareTo ("System") == 0) {
265                                         
266                                         if (parent.PeapiClass.name.CompareTo ("ValueType") == 0)
267                                                 is_value_class = true;
268                                         else
269                                         if (parent.PeapiClass.name.CompareTo ("Enum") == 0 )
270                                                 is_enum_class = true;          
271                                 } 
272
273                                 if (outer != null) {
274                                         if (!outer.IsDefined)
275                                                 outer.Define (code_gen);
276                                         classdef = outer.PeapiType.AddNestedClass (attr,
277                                                         name_space, name, parent.PeapiClass);
278                                 } else {
279                                         if (is_value_class || is_enum_class) {
280                                                 // Should probably confirm that the parent is System.ValueType
281                                                 classdef = code_gen.PEFile.AddValueClass (attr,
282                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
283                                         } else {
284                                                 classdef = code_gen.PEFile.AddClass (attr,
285                                                         name_space, name, parent.PeapiClass);
286                                         }
287                                 }
288                         } else {
289                                 if (outer != null) {
290                                         if (!outer.IsDefined)
291                                                 outer.Define (code_gen);
292                                         classdef = outer.PeapiType.AddNestedClass (attr,
293                                                 name_space, name);
294                                 } else {
295                                         if (is_value_class || is_enum_class) {
296                                                 classdef = code_gen.PEFile.AddValueClass (attr,
297                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
298                                         } else {
299                                                 classdef = code_gen.PEFile.AddClass (attr,
300                                                         name_space, name);
301                                         }
302                                 }
303                                 if (FullName == "System.Object")
304                                         classdef.SpecialNoSuper ();
305                         }
306
307                         if (size != -1 || pack != -1)
308                                 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
309
310                         if (impl_list != null) {
311                                 foreach (IClassRef impl in impl_list) {
312                                         impl.Resolve (code_gen);
313                                         classdef.AddImplementedInterface (impl.PeapiClass);
314                                 }
315                         }
316
317                         if (typar_list != null) {
318                                 short index = 0;
319                                 foreach (GenericInfo gi in typar_list) {
320                                         PEAPI.GenericParameter gp = classdef.AddGenericParameter (index++, gi.Id);
321                                         if (gi.ConstraintList != null) {
322                                                 foreach (ITypeRef cnst in gi.ConstraintList) {
323                                                         cnst.Resolve (code_gen);
324                                                         gp.AddConstraint (cnst.PeapiType);
325                                                 }
326                                         }
327                                 }
328                         }
329
330                         is_intransit = false;
331                         is_defined = true;
332
333                         code_gen.AddToDefineContentsList (this);
334                 }
335
336                 public void DefineContents (CodeGen code_gen)
337                 {
338                         ArrayList fielddef_list = new ArrayList ();
339                         foreach (FieldDef fielddef in field_list) {
340                                 fielddef.Define (code_gen, classdef);
341                                 fielddef_list.Add (fielddef.PeapiFieldDef);
342                         }
343
344                         classdef.SetFieldOrder (fielddef_list);
345
346                         foreach (MethodDef methoddef in method_table.Values) {
347                                 methoddef.Define (code_gen, this);
348                         }
349
350                         if (event_list != null) {
351                                 foreach (EventDef eventdef in event_list) {
352                                         eventdef.Define (code_gen, classdef);
353                                 }
354                         }
355
356                         if (property_list != null) {
357                                 foreach (PropertyDef propdef in property_list) {
358                                         propdef.Define (code_gen, classdef);
359                                 }
360
361                         }
362
363                         if (customattr_list != null) {
364                                 foreach (CustomAttr customattr in customattr_list) {
365                                         customattr.AddTo (code_gen, classdef);
366                                         if (customattr.IsSuppressUnmanaged (code_gen))
367                                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
368                                 }
369                         }
370                         
371                         /// Add declarative security to this method
372                         if (declsecurity_list != null) {
373                                 foreach (DeclSecurity declsecurity in declsecurity_list)
374                                         declsecurity.AddTo (code_gen, classdef);
375
376                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
377                         }       
378
379                         if (override_list != null) {
380                                 foreach (DictionaryEntry entry in override_list) {
381                                         MethodDef body = (MethodDef) entry.Key;
382                                         DictionaryEntry decl = (DictionaryEntry) entry.Value;
383                                         ITypeRef parent_type = (ITypeRef) decl.Key;
384                                         parent_type.Resolve (code_gen);
385                                         string over_name = (string) decl.Value;
386                                         IMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
387                                                         body.CallConv, over_name, body.ParamTypeList ());
388                                         over_meth.Resolve (code_gen);
389                                         classdef.AddMethodOverride (over_meth.PeapiMethod,
390                                                         body.PeapiMethodDef);
391                                 }
392                         }
393
394                         if (override_long_list != null) {
395                                 foreach (DictionaryEntry entry in override_long_list) {
396                                         string sig = (string) entry.Key;
397                                         IMethodRef decl = (IMethodRef) entry.Value;
398                                         MethodDef body = (MethodDef) method_table[sig];
399                                         decl.Resolve (code_gen);
400                                         classdef.AddMethodOverride (decl.PeapiMethod,
401                                                         body.PeapiMethodDef);
402                                 }
403                         }
404                 }
405
406                 public PEAPI.MethodDef ResolveMethod (string signature, CodeGen code_gen)
407                 {
408                         MethodDef methoddef = (MethodDef) method_table[signature];
409
410                         if (methoddef == null) {
411                                 code_gen.Report.Error ("Unable to resolve method: " + signature);
412                                 Environment.Exit (1);
413                         }
414
415                         return methoddef.Resolve (code_gen, classdef);
416                 }
417
418                 public PEAPI.Method ResolveVarargMethod (string signature,
419                                 CodeGen code_gen, PEAPI.Type[] opt)
420                 {
421                         MethodDef methoddef = (MethodDef) method_table[signature];
422
423                         if (methoddef == null) {
424                                 code_gen.Report.Error ("Unable to resolve method: " + signature);
425                                 Environment.Exit (1);
426                         }
427
428                         methoddef.Resolve (code_gen, classdef);
429                         return methoddef.GetVarargSig (opt);
430                 }
431
432                 public PEAPI.Field ResolveField (string name, CodeGen code_gen)
433                 {
434                         FieldDef fielddef = (FieldDef) field_table[name];
435
436                         return fielddef.Resolve (code_gen, classdef);
437                 }
438
439                 private string MakeFullName ()
440                 {
441                         if (name_space == null || name_space == String.Empty)
442                                 return name;
443
444                         return name_space + "." + name;
445                 }
446         }
447
448 }
449