2001-10-31 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                 // 
88                 // The default compiler checked state
89                 //
90                 public bool Checked = false;
91
92                 string MakeFQN (string nsn, string name)
93                 {
94                         string prefix = (nsn == "" ? "" : nsn + ".");
95
96                         return prefix + name;
97                 }
98                        
99                 // <remarks>
100                 //   This function is used to resolve the hierarchy tree.
101                 //   It processes interfaces, structs and classes in that order.
102                 //
103                 //   It creates the TypeBuilder's as it processes the user defined
104                 //   types.  
105                 // </remarks>
106                 public void ResolveTree ()
107                 {
108                         //
109                         // Interfaces are processed first, as classes and
110                         // structs might inherit from an object or implement
111                         // a set of interfaces, we need to be able to tell
112                         // them appart by just using the TypeManager.
113                         //
114
115                         TypeContainer root = Tree.Types;
116
117                         ArrayList ifaces = root.Interfaces;
118                         if (ifaces != null){
119                                 interface_resolve_order = new ArrayList ();
120                                 
121                                 foreach (Interface i in ifaces) {
122                                         Type t = i.DefineInterface (mb);
123                                         if (t != null)
124                                                 interface_resolve_order.Add (i);
125                                 }
126                         }
127                                                 
128                         type_container_resolve_order = new ArrayList ();
129                         
130                         foreach (TypeContainer tc in root.Types) {
131                                 Type t = tc.DefineType (mb);
132                                 if (t != null)
133                                         type_container_resolve_order.Add (tc);
134                         }
135
136                         if (root.Delegates != null)
137                                 foreach (Delegate d in root.Delegates) 
138                                         d.DefineDelegate (mb);
139                         
140                 }
141                         
142                 // <summary>
143                 //   Closes all open types
144                 // </summary>
145                 //
146                 // <remarks>
147                 //   We usually use TypeBuilder types.  When we are done
148                 //   creating the type (which will happen after we have added
149                 //   methods, fields, etc) we need to "Define" them before we
150                 //   can save the Assembly
151                 // </remarks>
152                 public void CloseTypes ()
153                 {
154                         TypeContainer root = Tree.Types;
155                         
156                         ArrayList ifaces = root.Interfaces;
157
158                         if (ifaces != null)
159                                 foreach (Interface i in ifaces) 
160                                         i.CloseType ();
161                         
162                         foreach (TypeContainer tc in root.Types)
163                                 tc.CloseType ();
164
165                         if (root.Delegates != null)
166                                 foreach (Delegate d in root.Delegates)
167                                         d.CloseDelegate ();
168                         
169                 }
170                 
171                 //
172                 // Public function used to locate types, this can only
173                 // be used after the ResolveTree function has been invoked.
174                 //
175                 // Returns: Type or null if they type can not be found.
176                 //
177                 public Type LookupType (TypeContainer tc, string name, bool silent)
178                 {
179                         Type t;
180
181                         t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
182                         if (t != null)
183                                 return t;
184
185                         // It's possible that name already is fully qualified. So we do
186                         // a simple direct lookup without adding any namespace names
187
188                         t = TypeManager.LookupType (name); 
189                         if (t != null)
190                                 return t;
191                         
192                         for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
193                                 ArrayList using_list = ns.UsingTable;
194
195                                 if (using_list == null)
196                                         continue;
197
198                                 foreach (string n in using_list){
199                                         t = TypeManager.LookupType (MakeFQN (n, name));
200                                         if (t != null)
201                                                 return t;
202                                 }
203                         }
204
205                         // For the case the type we are looking for is nested within this one.
206                         t = TypeManager.LookupType (tc.Name + "." + name);
207                         if (t != null)
208                                 return t;
209                         
210                         if (!silent)
211                                 Report.Error (246, "Cannot find type `"+name+"'");
212                         
213                         return null;
214                 }
215
216                 // <summary>
217                 //   This is the silent version of LookupType, you can use this
218                 //   to `probe' for a type
219                 // </summary>
220                 public Type LookupType (TypeContainer tc, string name)
221                 {
222                         return LookupType (tc, name, true);
223                 }
224
225                 public bool IsNamespace (string name)
226                 {
227                         Namespace ns;
228
229                         if (tree.Namespaces != null){
230                                 ns = (Namespace) tree.Namespaces [name];
231
232                                 if (ns != null)
233                                         return true;
234                         }
235
236                         return false;
237                 }
238
239                 // <summary>
240                 //   Populates the structs and classes with fields and methods
241                 // </summary>
242                 //
243                 // This is invoked after all interfaces, structs and classes
244                 // have been defined through `ResolveTree' 
245                 public void PopulateTypes ()
246                 {
247                         if (interface_resolve_order != null)
248                                 foreach (Interface iface in interface_resolve_order)
249                                         iface.Populate ();
250
251                         if (type_container_resolve_order != null)
252                                 foreach (TypeContainer tc in type_container_resolve_order)
253                                         tc.Populate ();
254
255                         ArrayList delegates = Tree.Types.Delegates;
256                         if (delegates != null)
257                                 foreach (Delegate d in delegates)
258                                         d.Populate (Tree.Types);
259                        
260                 }
261
262                 public void EmitCode ()
263                 {
264                         if (type_container_resolve_order != null)
265                                 foreach (TypeContainer tc in type_container_resolve_order)
266                                         tc.Emit ();
267
268                 }
269                 
270                 // <summary>
271                 //   Compiling against Standard Libraries property.
272                 // </summary>
273                 public bool StdLib {
274                         get {
275                                 return stdlib;
276                         }
277
278                         set {
279                                 stdlib = value;
280                         }
281                 }
282
283                 public ModuleBuilder ModuleBuilder {
284                         get {
285                                 return mb;
286                         }
287                 }
288
289                 //
290                 // Public Field, used to track which method is the public entry
291                 // point.
292                 //
293                 public MethodInfo EntryPoint;
294         }
295 }
296