2001-10-22 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / rootcontext.cs
1 //
2 // rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
3 //
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9
10 using System;
11 using System.Collections;
12 using System.Reflection;
13 using System.Reflection.Emit;
14 using System.Diagnostics;
15
16 namespace CIR {
17
18         public class RootContext {
19
20                 //
21                 // Contains the parsed tree
22                 //
23                 Tree tree;
24
25                 //
26                 // Contains loaded assemblies and our generated code as we go.
27                 //
28                 public TypeManager TypeManager;
29
30                 //
31                 // The System.Reflection.Emit CodeGenerator
32                 //
33                 CodeGen cg;
34
35                 //
36                 // The module builder pointer
37                 //
38                 ModuleBuilder mb;
39
40                 //
41                 // Whether we are being linked against the standard libraries.
42                 // This is only used to tell whether `System.Object' should
43                 // have a parent or not.
44                 //
45                 bool stdlib = true;
46
47                 //
48                 // This keeps track of the order in which classes were defined
49                 // so that we can poulate them in that order.
50                 //
51                 // Order is important, because we need to be able to tell by
52                 // examining the parent's list of methods which ones are virtual
53                 // or abstract as well as the parent names (to implement new, 
54                 // override).
55                 //
56                 ArrayList type_container_resolve_order;
57                 ArrayList interface_resolve_order;
58                 
59                 public RootContext ()
60                 {
61                         tree = new Tree (this);
62                         TypeManager = new TypeManager ();
63                 }
64
65                 public Tree Tree {
66                         get {
67                                 return tree;
68                         }
69                 }
70
71                 public CodeGen CodeGen {
72                         get {
73                                 return cg;
74                         }
75
76                         set {
77                                 //
78                                 // Temporary hack, we should probably
79                                 // intialize `cg' rather than depending on
80                                 // external initialization of it.
81                                 //
82                                 cg = value;
83                                 mb = cg.ModuleBuilder;
84                         }
85                 }
86
87                 string MakeFQN (string nsn, string name)
88                 {
89                         string prefix = (nsn == "" ? "" : nsn + ".");
90
91                         return prefix + name;
92                 }
93                        
94                 // <remarks>
95                 //   This function is used to resolve the hierarchy tree.
96                 //   It processes interfaces, structs and classes in that order.
97                 //
98                 //   It creates the TypeBuilder's as it processes the user defined
99                 //   types.  
100                 // </remarks>
101                 public void ResolveTree ()
102                 {
103                         //
104                         // Interfaces are processed first, as classes and
105                         // structs might inherit from an object or implement
106                         // a set of interfaces, we need to be able to tell
107                         // them appart by just using the TypeManager.
108                         //
109
110                         TypeContainer root = Tree.Types;
111
112                         ArrayList ifaces = root.Interfaces;
113                         if (ifaces != null){
114                                 interface_resolve_order = new ArrayList ();
115                                 
116                                 foreach (Interface i in ifaces) {
117                                         Type t = i.DefineInterface (mb);
118                                         if (t != null)
119                                                 interface_resolve_order.Add (i);
120                                 }
121                         }
122                                                 
123                         type_container_resolve_order = new ArrayList ();
124                         
125                         foreach (TypeContainer tc in root.Types) {
126                                 Type t = tc.DefineType (mb);
127                                 if (t != null)
128                                         type_container_resolve_order.Add (tc);
129                         }
130
131                         if (root.Delegates != null)
132                                 foreach (Delegate d in root.Delegates) 
133                                         d.DefineDelegate (mb);
134                         
135                 }
136                         
137                 // <summary>
138                 //   Closes all open types
139                 // </summary>
140                 //
141                 // <remarks>
142                 //   We usually use TypeBuilder types.  When we are done
143                 //   creating the type (which will happen after we have added
144                 //   methods, fields, etc) we need to "Define" them before we
145                 //   can save the Assembly
146                 // </remarks>
147                 public void CloseTypes ()
148                 {
149                         TypeContainer root = Tree.Types;
150                         
151                         ArrayList ifaces = root.Interfaces;
152
153                         if (ifaces != null)
154                                 foreach (Interface i in ifaces) 
155                                         i.CloseType ();
156                         
157                         foreach (TypeContainer tc in root.Types)
158                                 tc.CloseType ();
159
160                         if (root.Delegates != null)
161                                 foreach (Delegate d in root.Delegates)
162                                         d.CloseDelegate ();
163                         
164                 }
165                 
166                 //
167                 // Public function used to locate types, this can only
168                 // be used after the ResolveTree function has been invoked.
169                 //
170                 // Returns: Type or null if they type can not be found.
171                 //
172                 public Type LookupType (TypeContainer tc, string name, bool silent)
173                 {
174                         Type t;
175
176                         t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
177                         if (t != null)
178                                 return t;
179
180                         // It's possible that name already is fully qualified. So we do
181                         // a simple direct lookup without adding any namespace names
182
183                         t = TypeManager.LookupType (name); 
184                         if (t != null)
185                                 return t;
186                         
187                         for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
188                                 ArrayList using_list = ns.UsingTable;
189
190                                 if (using_list == null)
191                                         continue;
192
193                                 foreach (string n in using_list){
194                                         t = TypeManager.LookupType (MakeFQN (n, name));
195                                         if (t != null)
196                                                 return t;
197                                 }
198                         }
199
200                         // For the case the type we are looking for is nested within this one.
201                         t = TypeManager.LookupType (tc.Name + "." + name);
202                         if (t != null)
203                                 return t;
204                         
205                         if (!silent)
206                                 Report.Error (246, "Cannot find type `"+name+"'");
207                         
208                         return null;
209                 }
210
211                 // <summary>
212                 //   This is the silent version of LookupType, you can use this
213                 //   to `probe' for a type
214                 // </summary>
215                 public Type LookupType (TypeContainer tc, string name)
216                 {
217                         return LookupType (tc, name, true);
218                 }
219
220                 public bool IsNamespace (string name)
221                 {
222                         Namespace ns;
223
224                         if (tree.Namespaces != null){
225                                 ns = (Namespace) tree.Namespaces [name];
226
227                                 if (ns != null)
228                                         return true;
229                         }
230
231                         return false;
232                 }
233
234                 // <summary>
235                 //   Populates the structs and classes with fields and methods
236                 // </summary>
237                 //
238                 // This is invoked after all interfaces, structs and classes
239                 // have been defined through `ResolveTree' 
240                 public void PopulateTypes ()
241                 {
242                         if (interface_resolve_order != null)
243                                 foreach (Interface iface in interface_resolve_order)
244                                         iface.Populate ();
245
246                         if (type_container_resolve_order != null)
247                                 foreach (TypeContainer tc in type_container_resolve_order)
248                                         tc.Populate ();
249
250                         ArrayList delegates = Tree.Types.Delegates;
251                         if (delegates != null)
252                                 foreach (Delegate d in delegates)
253                                         d.Populate (Tree.Types);
254                        
255                 }
256
257                 public void EmitCode ()
258                 {
259                         if (type_container_resolve_order != null)
260                                 foreach (TypeContainer tc in type_container_resolve_order)
261                                         tc.Emit ();
262
263                 }
264                 
265                 // <summary>
266                 //   Compiling against Standard Libraries property.
267                 // </summary>
268                 public bool StdLib {
269                         get {
270                                 return stdlib;
271                         }
272
273                         set {
274                                 stdlib = value;
275                         }
276                 }
277
278                 //
279                 // Public Field, used to track which method is the public entry
280                 // point.
281                 //
282                 public MethodInfo EntryPoint;
283         }
284 }
285