7916decb5432246ed246d5339789b9aa1a78a5c2
[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                 //
60                 // Holds a reference to the Private Implementation Details
61                 // class.
62                 //
63                 TypeBuilder impl_details_class;
64
65                 //
66                 // Constructor
67                 //
68                 public RootContext ()
69                 {
70                         tree = new Tree (this);
71                         TypeManager = new TypeManager ();
72                 }
73
74                 public Tree Tree {
75                         get {
76                                 return tree;
77                         }
78                 }
79
80                 public CodeGen CodeGen {
81                         get {
82                                 return cg;
83                         }
84
85                         set {
86                                 //
87                                 // Temporary hack, we should probably
88                                 // intialize `cg' rather than depending on
89                                 // external initialization of it.
90                                 //
91                                 cg = value;
92                                 mb = cg.ModuleBuilder;
93                         }
94                 }
95
96                 // 
97                 // The default compiler checked state
98                 //
99                 public bool Checked = false;
100
101                 string MakeFQN (string nsn, string name)
102                 {
103                         string prefix = (nsn == "" ? "" : nsn + ".");
104
105                         return prefix + name;
106                 }
107                        
108                 // <remarks>
109                 //   This function is used to resolve the hierarchy tree.
110                 //   It processes interfaces, structs and classes in that order.
111                 //
112                 //   It creates the TypeBuilder's as it processes the user defined
113                 //   types.  
114                 // </remarks>
115                 public void ResolveTree ()
116                 {
117                         //
118                         // Interfaces are processed first, as classes and
119                         // structs might inherit from an object or implement
120                         // a set of interfaces, we need to be able to tell
121                         // them appart by just using the TypeManager.
122                         //
123
124                         TypeContainer root = Tree.Types;
125
126                         ArrayList ifaces = root.Interfaces;
127                         if (ifaces != null){
128                                 interface_resolve_order = new ArrayList ();
129                                 
130                                 foreach (Interface i in ifaces) {
131                                         Type t = i.DefineInterface (mb);
132                                         if (t != null)
133                                                 interface_resolve_order.Add (i);
134                                 }
135                         }
136                                                 
137                         type_container_resolve_order = new ArrayList ();
138                         
139                         foreach (TypeContainer tc in root.Types) {
140                                 Type t = tc.DefineType (mb);
141                                 if (t != null)
142                                         type_container_resolve_order.Add (tc);
143                         }
144
145                         if (root.Delegates != null)
146                                 foreach (Delegate d in root.Delegates) 
147                                         d.DefineDelegate (mb);
148                         
149                 }
150                         
151                 // <summary>
152                 //   Closes all open types
153                 // </summary>
154                 //
155                 // <remarks>
156                 //   We usually use TypeBuilder types.  When we are done
157                 //   creating the type (which will happen after we have added
158                 //   methods, fields, etc) we need to "Define" them before we
159                 //   can save the Assembly
160                 // </remarks>
161                 public void CloseTypes ()
162                 {
163                         TypeContainer root = Tree.Types;
164                         
165                         ArrayList ifaces = root.Interfaces;
166
167                         if (ifaces != null)
168                                 foreach (Interface i in ifaces) 
169                                         i.CloseType ();
170                         
171                         foreach (TypeContainer tc in root.Types)
172                                 tc.CloseType ();
173
174                         if (root.Delegates != null)
175                                 foreach (Delegate d in root.Delegates)
176                                         d.CloseDelegate ();
177
178                         //
179                         // If we have a <PrivateImplementationDetails> class, close it
180                         //
181                         if (impl_details_class != null){
182                                 impl_details_class.CreateType ();
183                         }
184                 }
185                 
186                 //
187                 // Public function used to locate types, this can only
188                 // be used after the ResolveTree function has been invoked.
189                 //
190                 // Returns: Type or null if they type can not be found.
191                 //
192                 public Type LookupType (TypeContainer tc, string name, bool silent)
193                 {
194                         Type t;
195
196                         t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
197                         if (t != null)
198                                 return t;
199
200                         // It's possible that name already is fully qualified. So we do
201                         // a simple direct lookup without adding any namespace names
202
203                         t = TypeManager.LookupType (name); 
204                         if (t != null)
205                                 return t;
206                         
207                         for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
208                                 ArrayList using_list = ns.UsingTable;
209
210                                 if (using_list == null)
211                                         continue;
212
213                                 foreach (string n in using_list){
214                                         t = TypeManager.LookupType (MakeFQN (n, name));
215                                         if (t != null)
216                                                 return t;
217                                 }
218                         }
219
220                         // For the case the type we are looking for is nested within this one.
221                         t = TypeManager.LookupType (tc.Name + "." + name);
222                         if (t != null)
223                                 return t;
224                         
225                         if (!silent)
226                                 Report.Error (246, "Cannot find type `"+name+"'");
227                         
228                         return null;
229                 }
230
231                 // <summary>
232                 //   This is the silent version of LookupType, you can use this
233                 //   to `probe' for a type
234                 // </summary>
235                 public Type LookupType (TypeContainer tc, string name)
236                 {
237                         return LookupType (tc, name, true);
238                 }
239
240                 public bool IsNamespace (string name)
241                 {
242                         Namespace ns;
243
244                         if (tree.Namespaces != null){
245                                 ns = (Namespace) tree.Namespaces [name];
246
247                                 if (ns != null)
248                                         return true;
249                         }
250
251                         return false;
252                 }
253
254                 // <summary>
255                 //   Populates the structs and classes with fields and methods
256                 // </summary>
257                 //
258                 // This is invoked after all interfaces, structs and classes
259                 // have been defined through `ResolveTree' 
260                 public void PopulateTypes ()
261                 {
262                         if (interface_resolve_order != null)
263                                 foreach (Interface iface in interface_resolve_order)
264                                         iface.Populate ();
265
266                         if (type_container_resolve_order != null)
267                                 foreach (TypeContainer tc in type_container_resolve_order)
268                                         tc.Populate ();
269
270                         ArrayList delegates = Tree.Types.Delegates;
271                         if (delegates != null)
272                                 foreach (Delegate d in delegates)
273                                         d.Populate (Tree.Types);
274                        
275                 }
276
277                 public void EmitCode ()
278                 {
279                         if (type_container_resolve_order != null)
280                                 foreach (TypeContainer tc in type_container_resolve_order)
281                                         tc.Emit ();
282
283                 }
284                 
285                 // <summary>
286                 //   Compiling against Standard Libraries property.
287                 // </summary>
288                 public bool StdLib {
289                         get {
290                                 return stdlib;
291                         }
292
293                         set {
294                                 stdlib = value;
295                         }
296                 }
297
298                 public ModuleBuilder ModuleBuilder {
299                         get {
300                                 return mb;
301                         }
302                 }
303
304                 //
305                 // Public Field, used to track which method is the public entry
306                 // point.
307                 //
308                 public MethodInfo EntryPoint;
309
310                 //
311                 // These are used to generate unique names on the structs and fields.
312                 //
313                 int field_count;
314                 
315                 //
316                 // Makes an initialized struct, returns the field builder that
317                 // references the data.  Thanks go to Sergey Chaban for researching
318                 // how to do this.  And coming up with a shorter mechanism than I
319                 // was able to figure out.
320                 //
321                 // This works but makes an implicit public struct $ArrayType$SIZE and
322                 // makes the fields point to it.  We could get more control if we did
323                 // use instead:
324                 //
325                 // 1. DefineNestedType on the impl_details_class with our struct.
326                 //
327                 // 2. Define the field on the impl_details_class
328                 //
329                 public FieldBuilder MakeStaticData (byte [] data)
330                 {
331                         FieldBuilder fb;
332                         int size = data.Length;
333                         
334                         if (impl_details_class == null)
335                                 impl_details_class = mb.DefineType (
336                                         "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
337
338                         fb = impl_details_class.DefineInitializedData (
339                                 "$$field-" + (field_count++), data,
340                                 FieldAttributes.Static | FieldAttributes.Assembly);
341                         
342                         return fb;
343                 }
344         }
345 }
346               
347