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