* ClassTable.cs, CodeGen.cs: Add methods to allow types to inherit from another...
[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
27                         public ClassTableItem (Class klass, Location location)
28                         {
29                                 flags = 0;
30                                 Class = klass;
31                                 LocationList = new ArrayList ();
32                                 LocationList.Add (location);
33                         }
34                 
35                         public bool Defined {
36                                 get { return ((flags & DefinedFlag) != 0); }
37                                 set {
38                                         if (value)
39                                                 flags |= DefinedFlag;
40                                         else
41                                                 flags ^= DefinedFlag;
42                                 }
43                         }
44                 }
45
46                 protected readonly TypeAttr DefaultAttr;
47                 protected Hashtable table;
48                 protected PEFile pefile;
49                 
50                 public ClassTable (PEFile pefile)
51                 {
52                         DefaultAttr = TypeAttr.Public;
53                         this.pefile = pefile;
54                         table = new Hashtable ();
55                 }
56
57                 public Class Get (string full_name)
58                 {
59                         ClassTableItem item = table[full_name] as ClassTableItem;
60                         
61                         if (item == null)
62                                 return null;
63
64                         return item.Class;
65                 }
66                 
67                 public Class GetReference (string full_name, Location location)
68                 {
69                         ClassTableItem item = table[full_name] as ClassTableItem;
70                         
71                         if (item != null) {
72                                 item.LocationList.Add (location);
73                                 return item.Class;
74                         }
75                         
76                         string name_space, name;                        
77                         GetNameAndNamespace (full_name, out name_space, out name);
78                         Class klass = pefile.AddClass (DefaultAttr, name_space, name);
79                         AddReference (full_name, klass, location);
80                         
81         
82                         return klass;
83                 }
84
85                 public ClassDef AddDefinition (string name_space, string name, 
86                         TypeAttr attr, Location location) 
87                 {
88                         string full_name = String.Format ("{0}.{1}", name_space, name);
89                         
90                         CheckExists (full_name);                                
91
92                         ClassDef klass = pefile.AddClass (attr, name_space, name);
93                         AddDefined (full_name, klass, location);
94
95                         return klass;
96                 }
97
98                 public ClassDef AddDefinition (string name_space, string name, 
99                         TypeAttr attr, Class parent, Location location) 
100                 {
101                         string full_name = String.Format ("{0}.{1}", name_space, name);
102
103                         CheckExists (full_name);                                
104
105                         ClassDef klass = pefile.AddClass (attr, name_space, name, parent);
106                         AddDefined (full_name, klass, location);
107
108                         return klass;
109                 }
110
111                 /// <summary>
112                 ///  When there is no code left to compile, check to make sure referenced types where defined
113                 ///  TODO: Proper error reporting
114                 /// </summary>
115                 public void CheckForUndefined ()
116                 {
117                         foreach (DictionaryEntry dic_entry in table) {
118                                 ClassTableItem table_item = (ClassTableItem) dic_entry.Value;
119                                 if (table_item.Defined)
120                                         continue;
121                                 throw new Exception (String.Format ("Type: {0} is not defined.", dic_entry.Key));
122                         }
123                 }
124
125                 /// <summary>
126                 ///  If a type is allready defined throw an Error
127                 /// </summary>
128                 protected void CheckExists (string full_name) 
129                 {
130                         ClassTableItem item = table[full_name] as ClassTableItem;
131                         
132                         if ((item != null) && (item.Defined)) {
133                                 throw new Exception (String.Format ("Class: {0} defined in multiple locations.", 
134                                         full_name));
135                         }
136                 }
137
138                 protected void AddDefined (string full_name, Class klass, Location location)
139                 {
140                         if (table.Contains (full_name))
141                                 return; 
142
143                         ClassTableItem item = new ClassTableItem (klass, location);
144                         item.Defined = true;
145
146                         table[full_name] = item;
147                 }
148
149                 protected void AddReference (string full_name, Class klass, Location location)
150                 {
151                         if (table.Contains (full_name))
152                                 return;
153
154                         ClassTableItem item = new ClassTableItem (klass, location);
155                         
156                         table[full_name] = item;
157                 }
158
159                 protected void GetNameAndNamespace (string full_name,
160                         out string name_space, out string name) {
161                         
162                         int last_dot = full_name.LastIndexOf ('.');
163         
164                         if (last_dot < 0) {
165                                 name_space = String.Empty;
166                                 name = full_name;
167                                 return;
168                         }
169                                 
170                         name_space = full_name.Substring (0, last_dot);
171                         name = full_name.Substring (last_dot + 1);
172                 }
173
174         }
175
176 }
177