* ClassTable.cs: Set defined flag and type attributes for referenced
[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 = String.Format ("{0}.{1}", name_space, name);
139                         
140                         ClassTableItem item = (ClassTableItem) table[full_name];
141
142                         if (item == null) {
143                                 ClassDef klass = pefile.AddClass (attr, name_space, name);
144                                 AddDefined (full_name, klass, location);
145                                 return klass;
146                         }
147
148                         item.Class.AddAttribute (attr);
149                         item.Defined = true;
150
151                         return item.Class;
152                 }
153
154                 public ClassDef AddDefinition (string name_space, string name, 
155                         TypeAttr attr, Class parent, Location location) 
156                 {
157                         string full_name = String.Format ("{0}.{1}", name_space, name);
158
159                         ClassTableItem item = (ClassTableItem) table[full_name];
160
161                         if (item == null) {
162                                 ClassDef klass = pefile.AddClass (attr, name_space, name, parent);
163                                 AddDefined (full_name, klass, location);
164                                 return klass;
165                         }
166                         
167                         /// TODO: Need to set parent, will need to modify PEAPI for this.
168                         item.Class.AddAttribute (attr);
169                         item.Defined = true;
170
171                         return item.Class;
172                 }
173
174                 /// <summary>
175                 ///  When there is no code left to compile, check to make sure referenced types where defined
176                 ///  TODO: Proper error reporting
177                 /// </summary>
178                 public void CheckForUndefined ()
179                 {
180                         foreach (DictionaryEntry dic_entry in table) {
181                                 ClassTableItem table_item = (ClassTableItem) dic_entry.Value;
182                                 if (table_item.CheckDefined ())
183                                         continue;
184                                 throw new Exception (String.Format ("Type: {0} is not defined.", dic_entry.Key));
185                         }
186                 }
187
188                 /// <summary>
189                 ///  If a type is allready defined throw an Error
190                 /// </summary>
191                 protected void CheckExists (string full_name) 
192                 {
193                         ClassTableItem item = table[full_name] as ClassTableItem;
194                         
195                         if ((item != null) && (item.Defined)) {
196                                 throw new Exception (String.Format ("Class: {0} defined in multiple locations.", 
197                                         full_name));
198                         }
199                 }
200
201                 protected void AddDefined (string full_name, ClassDef klass, Location location)
202                 {
203                         if (table.Contains (full_name))
204                                 return; 
205
206                         ClassTableItem item = new ClassTableItem (klass, location);
207                         item.Defined = true;
208
209                         table[full_name] = item;
210                 }
211
212                 protected void AddReference (string full_name, ClassDef klass, Location location)
213                 {
214                         if (table.Contains (full_name))
215                                 return;
216
217                         ClassTableItem item = new ClassTableItem (klass, location);
218                         
219                         table[full_name] = item;
220                 }
221
222                 protected void GetNameAndNamespace (string full_name,
223                         out string name_space, out string name) {
224                         
225                         int last_dot = full_name.LastIndexOf ('.');
226         
227                         if (last_dot < 0) {
228                                 name_space = String.Empty;
229                                 name = full_name;
230                                 return;
231                         }
232                                 
233                         name_space = full_name.Substring (0, last_dot);
234                         name = full_name.Substring (last_dot + 1);
235                 }
236
237         }
238
239 }
240