Create xammac_net_4_5 profile for XM 4.5 Unified to remove references to unshippable...
[mono.git] / mcs / ilasm / codegen / ClassTable.cs
1 //
2 // Mono.ILASM.ClassTable.cs
3 //
4 // Author(s):
5 //  Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
9
10 using PEAPI;
11 using System;
12 using System.Collections;
13
14 namespace Mono.ILASM {
15
16         public class ClassTable {
17
18                 private class ClassTableItem {
19
20                         private static readonly int DefinedFlag = 2;
21
22                         private int flags;
23
24                         public ArrayList LocationList;
25                         public ClassDef Class;
26                         public MethodTable method_table;
27                         public FieldTable field_table;
28
29                         public ClassTableItem (ClassDef klass, Location location)
30                         {
31                                 flags = 0;
32                                 Class = klass;
33                                 LocationList = new ArrayList ();
34                                 LocationList.Add (location);
35                                 method_table = new MethodTable (klass);
36                                 field_table = new FieldTable (klass);
37                         }
38
39                         public bool Defined {
40                                 get { return ((flags & DefinedFlag) != 0); }
41                                 set {
42                                         if (value)
43                                                 flags |= DefinedFlag;
44                                         else
45                                                 flags ^= DefinedFlag;
46                                 }
47                         }
48
49                         public bool CheckDefined ()
50                         {
51                                 if (!Defined)
52                                         return false;
53
54                                 if (!FieldTable.CheckDefined ())
55                                         return false;
56
57                                 if (!MethodTable.CheckDefined ())
58                                         return false;
59
60                                 return true;
61                         }
62
63                         public MethodTable MethodTable {
64                                 get { return method_table; }
65                         }
66
67                         public FieldTable FieldTable {
68                                 get { return field_table; }
69                         }
70
71                 }
72
73                 protected readonly TypeAttr DefaultAttr;
74                 protected Hashtable table;
75                 protected PEFile pefile;
76
77                 public ClassTable (PEFile pefile)
78                 {
79                         DefaultAttr = TypeAttr.Public;
80                         this.pefile = pefile;
81                         table = new Hashtable ();
82                 }
83
84                 public Class Get (string full_name)
85                 {
86                         ClassTableItem item = table[full_name] as ClassTableItem;
87
88                         if (item == null)
89                                 return null;
90
91                         return item.Class;
92                 }
93
94                 public Class GetReference (string full_name, Location location)
95                 {
96                         ClassTableItem item = table[full_name] as ClassTableItem;
97
98                         if (item != null) {
99                                 item.LocationList.Add (location);
100                                 return item.Class;
101                         }
102
103                         string name_space, name;
104                         GetNameAndNamespace (full_name, out name_space, out name);
105                         ClassDef klass = pefile.AddClass (DefaultAttr, name_space, name);
106                         AddReference (full_name, klass, location);
107
108                         return klass;
109                 }
110
111                 public MethodTable GetMethodTable (string full_name, Location location)
112                 {
113                         ClassTableItem item = table[full_name] as ClassTableItem;
114
115                         if (item == null) {
116                                 GetReference (full_name, location);
117                                 return GetMethodTable (full_name, location);
118                         }
119
120                         return item.MethodTable;
121                 }
122
123                 public FieldTable GetFieldTable (string full_name, Location location)
124                 {
125                         ClassTableItem item = table[full_name] as ClassTableItem;
126
127                         if (item == null) {
128                                 GetReference (full_name, location);
129                                 return GetFieldTable (full_name, location);
130                         }
131
132                         return item.FieldTable;
133                 }
134
135                 public ClassDef AddDefinition (string name_space, string name,
136                         TypeAttr attr, Location location)
137                 {
138                         string full_name;
139
140                         if (name_space != null)
141                                 full_name = String.Format ("{0}.{1}", name_space, name);
142                         else
143                                 full_name = name;
144
145                         ClassTableItem item = (ClassTableItem) table[full_name];
146
147                         if (item == null) {
148                                 ClassDef klass = pefile.AddClass (attr, name_space, name);
149                                 AddDefined (full_name, klass, location);
150                                 return klass;
151                         }
152
153                         item.Class.AddAttribute (attr);
154                         item.Defined = true;
155
156                         return item.Class;
157                 }
158
159                 public ClassDef AddDefinition (string name_space, string name,
160                         TypeAttr attr, Class parent, Location location)
161                 {
162                         string full_name;
163
164                         if (name_space != null)
165                                 full_name = String.Format ("{0}.{1}", name_space, name);
166                         else
167                                 full_name = name;
168
169                         ClassTableItem item = (ClassTableItem) table[full_name];
170
171                         if (item == null) {
172                                 ClassDef klass = pefile.AddClass (attr, name_space, name, parent);
173                                 AddDefined (full_name, klass, location);
174                                 return klass;
175                         }
176
177                         /// TODO: Need to set parent, will need to modify PEAPI for this.
178                         item.Class.AddAttribute (attr);
179                         item.Defined = true;
180
181                         return item.Class;
182                 }
183
184                 /// <summary>
185                 ///  When there is no code left to compile, check to make sure referenced types where defined
186                 ///  TODO: Proper error reporting
187                 /// </summary>
188                 public void CheckForUndefined ()
189                 {
190                         foreach (DictionaryEntry dic_entry in table) {
191                                 ClassTableItem table_item = (ClassTableItem) dic_entry.Value;
192                                 if (table_item.CheckDefined ())
193                                         continue;
194                                 Report.Error (String.Format ("Type: {0} is not defined.", dic_entry.Key));
195                         }
196                 }
197
198                 /// <summary>
199                 ///  If a type is allready defined throw an Error
200                 /// </summary>
201                 protected void CheckExists (string full_name)
202                 {
203                         ClassTableItem item = table[full_name] as ClassTableItem;
204
205                         if ((item != null) && (item.Defined)) {
206                                 Report.Error (String.Format ("Class: {0} defined in multiple locations.",
207                                         full_name));
208                         }
209                 }
210
211                 protected void AddDefined (string full_name, ClassDef klass, Location location)
212                 {
213                         if (table.Contains (full_name))
214                                 return;
215
216                         ClassTableItem item = new ClassTableItem (klass, location);
217                         item.Defined = true;
218
219                         table[full_name] = item;
220                 }
221
222                 protected void AddReference (string full_name, ClassDef klass, Location location)
223                 {
224                         if (table.Contains (full_name))
225                                 return;
226
227                         ClassTableItem item = new ClassTableItem (klass, location);
228
229                         table[full_name] = item;
230                 }
231
232                 public static void GetNameAndNamespace (string full_name,
233                         out string name_space, out string name) {
234
235                         int last_dot = full_name.LastIndexOf ('.');
236
237                         if (last_dot < 0) {
238                                 name_space = String.Empty;
239                                 name = full_name;
240                                 return;
241                         }
242
243                         name_space = full_name.Substring (0, last_dot);
244                         name = full_name.Substring (last_dot + 1);
245                 }
246
247         }
248
249 }
250