* TypeDef.cs: Make types into value types if specified. Also
[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                 private PEAPI.TypeAttr attr;
19                 private string name_space;
20                 private string name;
21                 private bool is_defined;
22                 private bool is_intransit;
23                 private IClassRef parent;
24                 private ArrayList impl_list;
25                 private PEAPI.ClassDef classdef;
26                 private Hashtable field_table;
27                 private Hashtable method_table;
28                 private ArrayList data_list;
29                 private ArrayList customattr_list;
30                 private ArrayList event_list;
31                 private ArrayList property_list;
32                 private ArrayList typar_list;
33                 private Hashtable constraint_table;
34                 private TypeDef outer;
35
36                 private EventDef current_event;
37                 private PropertyDef current_property;
38
39                 private int size;
40                 private int pack;
41
42                 private bool is_value_class;
43                 private bool is_enum_class;
44
45                 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
46                                 IClassRef parent, ArrayList impl_list, Location location)
47                 {
48                         this.attr = attr;
49                         this.name_space = name_space;
50                         this.name = name;
51                         this.parent = parent;
52                         this.impl_list = impl_list;
53                         field_table = new Hashtable ();
54                         method_table = new Hashtable ();
55                         data_list = new ArrayList ();
56
57                         size = -1;
58                         pack = -1;
59
60                         is_defined = false;
61                         is_intransit = false;
62
63                         is_value_class = false;
64                         is_value_class = false;
65                 }
66
67                 public string Name {
68                         get { return name; }
69                 }
70
71                 public string FullName {
72                         get { return MakeFullName (); }
73                 }
74
75                 public TypeDef OuterType {
76                         get { return outer; }
77                         set { outer = value; }
78                 }
79
80                 public PEAPI.ClassDef PeapiType {
81                         get { return classdef; }
82                 }
83
84                 public PEAPI.ClassDef ClassDef {
85                         get { return classdef; }
86                 }
87
88                 public bool IsGenericType {
89                         get { return (typar_list == null); }
90                 }
91
92                 public bool IsDefined {
93                         get { return is_defined; }
94                 }
95
96                 public EventDef CurrentEvent {
97                         get { return current_event; }
98                 }
99
100                 public PropertyDef CurrentProperty {
101                         get { return current_property; }
102                 }
103
104                 public void MakeValueClass ()
105                 {
106                         is_value_class = true;
107                 }
108
109                 public void MakeEnumClass ()
110                 {
111                         is_enum_class = true;
112                 }
113
114                 public void SetSize (int size)
115                 {
116                         this.size = size;
117                 }
118
119                 public void SetPack (int pack)
120                 {
121                         this.pack = pack;
122                 }
123
124                 public void AddFieldDef (FieldDef fielddef)
125                 {
126                         field_table.Add (fielddef.Name, fielddef);
127                 }
128
129                 public void AddDataDef (DataDef datadef)
130                 {
131                         data_list.Add (datadef);
132                 }
133
134                 public void AddMethodDef (MethodDef methoddef)
135                 {
136                         method_table.Add (methoddef.Signature, methoddef);
137                 }
138
139                 public void BeginEventDef (EventDef event_def)
140                 {
141                         if (current_event != null)
142                                 throw new Exception ("An event definition was not closed.");
143
144                         current_event = event_def;
145                 }
146
147                 public void EndEventDef ()
148                 {
149                         if (event_list == null)
150                                 event_list = new ArrayList ();
151
152                         event_list.Add (current_event);
153                         current_event = null;
154                 }
155
156                 public void BeginPropertyDef (PropertyDef property_def)
157                 {
158                         if (current_property != null)
159                                 throw new Exception ("A property definition was not closed.");
160
161                         current_property = property_def;
162                 }
163
164                 public void EndPropertyDef ()
165                 {
166                         if (property_list == null)
167                                 property_list = new ArrayList ();
168
169                         property_list.Add (current_property);
170                         current_property = null;
171                 }
172
173                 public void AddCustomAttribute (CustomAttr customattr)
174                 {
175                         if (customattr_list == null)
176                                 customattr_list = new ArrayList ();
177
178                         customattr_list.Add (customattr);
179                 }
180
181                 public void AddGenericParam (string id)
182                 {
183                         if (typar_list == null)
184                                 typar_list = new ArrayList ();
185
186                         typar_list.Add (id);
187                 }
188
189                 public void AddGenericConstraint (int index, ITypeRef constraint)
190                 {
191                         if (constraint_table == null)
192                                 constraint_table = new Hashtable ();
193
194                         constraint_table.Add (index, constraint);
195                 }
196
197                 public void Define (CodeGen code_gen)
198                 {
199                         if (is_defined)
200                                 return;
201
202                         if (is_intransit) {
203                                 // Circular definition
204                                 throw new Exception ("Circular definition of class: " + FullName);
205                         }
206
207                         if (parent != null) {
208                                 is_intransit = true;
209                                 parent.Resolve (code_gen);
210                                 is_intransit = false;
211                                 if (parent.PeapiClass == null) {
212                                         throw new Exception ("this type can not be a base type: "
213                                                         + parent);
214                                 }
215                                 if (outer != null) {
216                                         if (!outer.IsDefined)
217                                                 outer.Define (code_gen);
218                                         classdef = outer.PeapiType.AddNestedClass (attr,
219                                                         name_space, name, parent.PeapiClass);
220                                 } else {
221                                         if (is_value_class) {
222                                                 // Should probably confirm that the parent is System.ValueType
223                                                 classdef = code_gen.PEFile.AddValueClass (attr,
224                                                         name_space, name);
225                                         } else {
226                                                 classdef = code_gen.PEFile.AddClass (attr,
227                                                         name_space, name, parent.PeapiClass);
228                                         }
229                                 }
230                         } else {
231                                 if (outer != null) {
232                                         if (!outer.IsDefined)
233                                                 outer.Define (code_gen);
234                                         classdef = outer.PeapiType.AddNestedClass (attr,
235                                                 name_space, name);
236                                 } else {
237                                         if (is_value_class) {
238                                                 classdef = code_gen.PEFile.AddValueClass (attr,
239                                                         name_space, name);
240                                         } else {
241                                                 classdef = code_gen.PEFile.AddClass (attr,
242                                                         name_space, name);
243                                         }
244                                 }
245                         }
246
247                         if (size != -1)
248                                 classdef.AddLayoutInfo (pack, size);
249
250                         if (typar_list != null) {
251                                 short index = 0;
252                                 foreach (string id in typar_list) {
253                                         if (constraint_table != null && constraint_table.Contains ((int) index)) {
254                                                 ITypeRef constraint = (ITypeRef) constraint_table[(int) index];
255                                                 constraint.Resolve (code_gen);
256                                                 classdef.AddGenericParameter (index++, id, constraint.PeapiType);
257                                         } else {
258                                                 classdef.AddGenericParameter (index++, id);
259                                         }
260                                 }
261                         }
262
263                         is_intransit = false;
264                         is_defined = true;
265
266                         code_gen.AddToDefineContentsList (this);
267                 }
268
269                 public void DefineContents (CodeGen code_gen)
270                 {
271                         foreach (FieldDef fielddef in field_table.Values) {
272                                 fielddef.Define (code_gen, classdef);
273                         }
274
275                         foreach (MethodDef methoddef in method_table.Values) {
276                                 methoddef.Define (code_gen, classdef);
277                         }
278
279                         if (event_list != null) {
280                                 foreach (EventDef eventdef in event_list) {
281                                         eventdef.Define (code_gen, classdef);
282                                 }
283                         }
284
285                         if (property_list != null) {
286                                 foreach (PropertyDef propdef in property_list) {
287                                         propdef.Define (code_gen, classdef);
288                                 }
289
290                         }
291
292                         if (customattr_list != null) {
293                                 foreach (CustomAttr customattr in customattr_list)
294                                         customattr.AddTo (code_gen, classdef);
295                         }
296                 }
297
298                 public PEAPI.MethodDef ResolveMethod (string signature, CodeGen code_gen)
299                 {
300                         MethodDef methoddef = (MethodDef) method_table[signature];
301
302                         return methoddef.Resolve (code_gen, classdef);
303                 }
304
305                 public PEAPI.Method ResolveVarargMethod (string signature,
306                                 CodeGen code_gen, PEAPI.Type[] opt)
307                 {
308                         MethodDef methoddef = (MethodDef) method_table[signature];
309                         methoddef.Resolve (code_gen, classdef);
310
311                         return methoddef.GetVarargSig (opt);
312                 }
313
314                 public PEAPI.Field ResolveField (string name, CodeGen code_gen)
315                 {
316                         FieldDef fielddef = (FieldDef) field_table[name];
317
318                         return fielddef.Resolve (code_gen, classdef);
319                 }
320
321                 private string MakeFullName ()
322                 {
323                         if (name_space == null || name_space == String.Empty)
324                                 return name;
325
326                         return name_space + "." + name;
327                 }
328         }
329
330 }
331