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