* ClassTable.cs: Classes now store field tables
[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 MethodTable MethodTable {
50                                 get { return method_table; }
51                         }
52
53                         public FieldTable FieldTable {
54                                 get { return field_table; }
55                         }
56                         
57                 }
58
59                 protected readonly TypeAttr DefaultAttr;
60                 protected Hashtable table;
61                 protected PEFile pefile;
62                 
63                 public ClassTable (PEFile pefile)
64                 {
65                         DefaultAttr = TypeAttr.Public;
66                         this.pefile = pefile;
67                         table = new Hashtable ();
68                 }
69
70                 public Class Get (string full_name)
71                 {
72                         ClassTableItem item = table[full_name] as ClassTableItem;
73                         
74                         if (item == null)
75                                 return null;
76
77                         return item.Class;
78                 }
79                 
80                 public Class GetReference (string full_name, Location location)
81                 {
82                         ClassTableItem item = table[full_name] as ClassTableItem;
83                         
84                         if (item != null) {
85                                 item.LocationList.Add (location);
86                                 return item.Class;
87                         }
88                         
89                         string name_space, name;                        
90                         GetNameAndNamespace (full_name, out name_space, out name);
91                         ClassDef klass = pefile.AddClass (DefaultAttr, name_space, name);
92                         AddReference (full_name, klass, location);
93         
94                         return klass;
95                 }
96
97                 public MethodTable GetMethodTable (string full_name, Location location)
98                 {
99                         ClassTableItem item = table[full_name] as ClassTableItem;
100                         
101                         if (item == null) {
102                                 GetReference (full_name, location);
103                                 return GetMethodTable (full_name, location);
104                         }
105
106                         return item.MethodTable;
107                 }
108
109                 public FieldTable GetFieldTable (string full_name, Location location)
110                 {
111                         ClassTableItem item = table[full_name] as ClassTableItem;
112                         
113                         if (item == null) {
114                                 GetReference (full_name, location);
115                                 return GetFieldTable (full_name, location);
116                         }
117
118                         return item.FieldTable;
119                 }
120
121                 public ClassDef AddDefinition (string name_space, string name, 
122                         TypeAttr attr, Location location) 
123                 {
124                         string full_name = String.Format ("{0}.{1}", name_space, name);
125                         
126                         CheckExists (full_name);                                
127
128                         ClassDef klass = pefile.AddClass (attr, name_space, name);
129                         AddDefined (full_name, klass, location);
130
131                         return klass;
132                 }
133
134                 public ClassDef AddDefinition (string name_space, string name, 
135                         TypeAttr attr, Class parent, Location location) 
136                 {
137                         string full_name = String.Format ("{0}.{1}", name_space, name);
138
139                         CheckExists (full_name);                                
140
141                         ClassDef klass = pefile.AddClass (attr, name_space, name, parent);
142                         AddDefined (full_name, klass, location);
143
144                         return klass;
145                 }
146
147                 /// <summary>
148                 ///  When there is no code left to compile, check to make sure referenced types where defined
149                 ///  TODO: Proper error reporting
150                 /// </summary>
151                 public void CheckForUndefined ()
152                 {
153                         foreach (DictionaryEntry dic_entry in table) {
154                                 ClassTableItem table_item = (ClassTableItem) dic_entry.Value;
155                                 if (table_item.Defined)
156                                         continue;
157                                 throw new Exception (String.Format ("Type: {0} is not defined.", dic_entry.Key));
158                         }
159                 }
160
161                 /// <summary>
162                 ///  If a type is allready defined throw an Error
163                 /// </summary>
164                 protected void CheckExists (string full_name) 
165                 {
166                         ClassTableItem item = table[full_name] as ClassTableItem;
167                         
168                         if ((item != null) && (item.Defined)) {
169                                 throw new Exception (String.Format ("Class: {0} defined in multiple locations.", 
170                                         full_name));
171                         }
172                 }
173
174                 protected void AddDefined (string full_name, ClassDef klass, Location location)
175                 {
176                         if (table.Contains (full_name))
177                                 return; 
178
179                         ClassTableItem item = new ClassTableItem (klass, location);
180                         item.Defined = true;
181
182                         table[full_name] = item;
183                 }
184
185                 protected void AddReference (string full_name, ClassDef klass, Location location)
186                 {
187                         if (table.Contains (full_name))
188                                 return;
189
190                         ClassTableItem item = new ClassTableItem (klass, location);
191                         
192                         table[full_name] = item;
193                 }
194
195                 protected void GetNameAndNamespace (string full_name,
196                         out string name_space, out string name) {
197                         
198                         int last_dot = full_name.LastIndexOf ('.');
199         
200                         if (last_dot < 0) {
201                                 name_space = String.Empty;
202                                 name = full_name;
203                                 return;
204                         }
205                                 
206                         name_space = full_name.Substring (0, last_dot);
207                         name = full_name.Substring (last_dot + 1);
208                 }
209
210         }
211
212 }
213